65.类和对象
一、类和对象
类的意思:种类、分类、类别,是面向对象设计最重要的概念,对象是特征与技能的结合体,而类则是一系列对象相似的特征与技能的结合体
对象是特征与技能的结合体,我可能有身高体重、而你也有身高体重,所以你会说你像我,但是你一定不会说你像阿猫阿狗。并且我和你其实就可以说成是一类,而你和选课系统不能说是一类,因此给出类的定义:类就是一系列对象相似的特征与技能的结合体。
那么问题来了,先有的一个个具体存在的对象(比如一个具体存在的人),还是先有的人类这个概念,这个问题需要分两种情况去看:
1.在现实世界中:先有对象,再有类
世界上肯定是先出现各种各样的实际存在的物体,然后随着人类文明的发展,人类站在不同的角度总结出了不同的种类,如人类、动物类、植物类等概念,也就说,对象是具体的存在,而类仅仅只是一个概念,并不真实存在
2.在程序中:务必保证先定义类,后产生对象
这与函数的使用是类似的,先定义函数,后调用函数,类也是一样的,在程序中需要先定义类,后调用类,不一样的是,调用函数会执行函数体代码返回的是函数体执行的结果,而调用类会产生对象,返回的是对象
二、现实世界中定义类和对象
2.1 定义对象
就拿选课系统来讲,我们先总结一套现实世界中的学生对象:
- 对象1:
- 特征:
- 学校='oldboy'
- 姓名='lwx'
- 年龄=18
- 性别='male'
- 技能:
- 选课
- 特征:
- 对象2:
- 特征:
- 学校='oldboy'
- 姓名='xiaoming'
- 年龄=17
- 性别='male'
- 技能:
- 选课
- 特征:
- 对象3:
- 特征:
- 学校='oldboy'
- 姓名='xiaozhang'
- 年龄=19
- 性别='female'
- 技能:
- 选课
- 特征:
2.2 定义对象
站在未来选课系统的角度,我们还可以总结现实世界中的学生类:
- 老男孩学生类:
- 相似的特征:
- 学校='oldboy'
- 相似的技能
- 选课
- 相似的特征:
三、程序中定义类和对象
3.1 定义类
# 注意类中定义变量使用驼峰体
class OldboyStudent():
school = 'oldboy'
def choose_course(self):
print('is choosing course')
我们曾经在定义函数的时候,只检测函数题的语法,不执行其代码,但是定义类的时候,类体代码会在类定义阶段就立刻执行,并且会产生一个类的名称空间,也就是说类的本身其实就是一个容器/名称空间,是用来存放名字的,这是类的用途之一
print(OldboyStudent.__dict__)
#{'__module__': '__main__', 'school': 'oldboy', 'choose_course': <function OldboyStudent.choose_course at 0x10d653ae8>, '__dict__': <attribute '__dict__' of 'OldboyStudent' objects>, '__weakref__': <attribute '__weakref__' of 'OldboyStudent' objects>, '__doc__': None}
print(OldboyStudent.__dict__['school'])
3oldboy
print(OldboyStudent.__dict__['choose_course'])
#<function OldboyStudent.choose_course at 0x10d653ae8>
try:
OldboyStudent.__dict__['choose_course']()
except Exception as e:
print('error:', e)
error: choose_course() missing 1 required positional argument: 'self'
print(OldboyStudent.school)
#oldboy
OldboyStudent.choose_course(111)
is choosing course
print(OldboyStudent.choose_course)
#<function OldboyStudent.choose_course at 0x10d653ae8>
OldboyStudent.__dict__['choose_course']
#<function __main__.OldboyStudent.choose_course(self)>
OldboyStudent.country='China'
OldboyStudent.__dict__['country']
#'China'
OldboyStudent.country='CHINA'
OldboyStudent.__dict__['country']
#'CHINA'
del OldboyStudent.school
print(OldboyStudent.__dict__)
#{'__module__': '__main__', 'school': 'oldboy', 'choose_course': <function OldboyStudent.choose_course at 0x10d653ae8>, '__dict__': <attribute '__dict__' of 'OldboyStudent' objects>, '__weakref__': <attribute '__weakref__' of 'OldboyStudent' objects>, '__doc__': None, 'country': 'CHINA'}
3.2 定义对象
调用类即可产生对象,调用类的过程,又称为类的实例化,实例化的结果称为类的对象/实例
stu1=OldboyStudent() # 调用类会得到一个返回值,该返回值就是类的一个具体存在的对象/实例
print(stu1.school)
#oldboy
stu2=OldboyStudent() # 调用类会得到一个返回值,该返回值就是类的一个具体存在的对象/实例
print(stu2.school)
#oldboy
stu3=OldboyStudent() # 调用类会得到一个返回值,该返回值就是类的一个具体存在的对象/实例
stu3.choose_course()
is choosing course
3.3 python为类内置的特殊属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中)
四、补充说明
4.1 先定义,后使用
在程序中,务必保证:先定义(类),后使用(产生对象):
- 在程序中特征用变量标识,技能用函数标识
- 因而类中最常见的无非是:变量和函数的定义
#程序中的类
class OldboyStudent:
school='oldboy'
def learn(self):
print('is learning')
def eat(self):
print('is eating')
def sleep(self):
print('is sleeping')
注意:
1.类中可以有任意python代码,这些代码在类定义阶段便会执行
2.因而会产生新的名称空间,用来存放类的变量名与函数名,可以通过OldboyStudent.__dict__查看
3.对于经典类来说我们可以通过该字典操作类名称空间的名字(新式类有限制),但python为我们提供专门的.语法
4.点是访问属性的语法,类中定义的名字,都是类的属性
4.2 程序中类的用法
“.”:专门用来访问属性,本质操作的就是__dict__
OldboyStudent.school #等于经典类的操作OldboyStudent.__dict__['school']
OldboyStudent.school='Oldboy' #等于经典类的操作OldboyStudent.__dict__['school']='Oldboy'
OldboyStudent.x=1 #等于经典类的操作OldboyStudent.__dict__['x']=1
del OldboyStudent.x #等于经典类的操作OldboyStudent.__dict__.pop('x')
4.3 程序中的对象
调用类,或称为实例化,得到对象
s1=OldboyStudent()
s2=OldboyStudent()
s3=OldboyStudent()
#如此,s1、s2、s3都一样了,而这三者除了相似的属性之外还各种不同的属性,这就用到了__init__
#注意:该方法是在对象产生之后才会执行,只用来为对象进行初始化操作,可以有任意代码,但一定不能有返回值
class OldboyStudent:
......
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
......
s1=OldboyStudent('李坦克','男',18) #先调用类产生空对象s1,然后调用OldboyStudent.__init__(s1,'李坦克','男',18)
s2=OldboyStudent('王大炮','女',38)
s3=OldboyStudent('牛榴弹','男',78)
4.4 程序中对象的用法
#执行__init__,s1.name='牛榴弹',很明显也会产生对象的名称空间
s2.__dict__
{'name': '王大炮', 'age': '女', 'sex': 38}
s2.name #s2.__dict__['name']
s2.name='王三炮' #s2.__dict__['name']='王三炮'
s2.course='python' #s2.__dict__['course']='python'
del s2.course #s2.__dict__.pop('course')
在程序中:先定义类,后产生对象
4.5 总结说明
- 站的角度不同,定义出的类是截然不同的,详见面向对象实战之需求分析
- 现实中的类并不完全等于程序中的类,比如现实中的公司类,在程序中有时需要拆分成部门类,业务类
- 有时为了编程需求,程序中也可能会定义现实中不存在的类,比如策略类,现实中并不存在,但是在程序中却是一个很常见的类