七、面向对象

7 面向对象

7.1 类与对象

7.1.1 类的定义

命名规则:首字母大写,不用_相连,命名驼峰式
最基本作用: 封装代码,只负责定义,不负责执行

1
2
3
4
5
6
7
8
9
class StuInfo():
name = ' '
age = 0
def print_file(self):
print('name: ' + self.name)
print('age: ' + str(self.age))

tom = StuInfo()
tom.print_file()

类的定义和调用尽量分开进行,尽量不要在同一模块进行:

7.1.2 类和对象

类:类是现实世界或思维世界中的实体在计算机中的反映,类似一个模板。
它将数据以及这些数据上的操作封装在一起。
行为与特征是类的要点。
对象:类的具体化,通过类这样一个模板印刷出很多的对象。这些对象都有类的共同属性。

7.2 构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class PersonInfo():
age = 0
name = ' '
#构造函数
def __init__(self):
print('Person info') #只能默认返回None类型
# return 'persson' #强制返回会报错


def job_name(self):
print('saler')

tom = PersonInfo()#会自动调用构造函数
a = tom.__init__()
print(a)
print(type(a))#检测构造函数__init__会返回什么类型
# Result
g:\Python\Demon2\pk3>b5.py
Person info
Person info
None
<class 'NoneType'>

g:\Python\Demon2\pk3>

7.3 实例方法、实例变量、类变量及self

a. 对象或类的dict变量保存着当前对象的所有变量和函数,它是字典类型;
当访问对象的变量时,首先在对象的实例变量中查找,若未找到则去对象的类变量中查找,若还未找到则去父类中查找。
b. 在类中的方法内部访问对象或类变量不能直接使用变量名,因为对象或类变量的查找机制只在类外部调用时才 有,直接在内部方法中使用只会寻找该方法是否有这样的局部变量;
在实例方法中访问类变量两种方式:①类名.类变量名②self.class.类变量名
实例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class CatInfo():
#类变量(与类相关联)
# 统计有多少只猫
COUNT = 0
name = 'cat_name'
age = 0
eye_color = 'White'

def __init__(self,name,age,eye_color):
#构造函数,初始化对象
#实例变量(与对象相关联)
CatInfo.COUNT += 1 # 一、实例方法中访问类变量
self.name = name
self.age = age
self.eye_color = eye_color
print('The ' + str(CatInfo.COUNT) +' cat was born')
#第二种方法:在实例方法中访问类变量
self.__class__.COUNT += 1
print('AGAIN,The ' + str(self.__class__.COUNT) +' cat was born')
print(name) # 访问的是对象的name,不是类中的name属性

def catch_mouse(self): #类的行为与特性
print('Big mouse')

mini = CatInfo('mini',1,'blue')
kitty = CatInfo('kitty',2,'black')
print(mini.eye_color)
print(kitty.eye_color)
print(CatInfo.name)
print(CatInfo.__dict__)
print(kitty.__dict__)

7.4 类方法与静态方法

7.4.1 类方法

a.类方法格式:
@classmethod
def func(cls):
pass
注:这里的cls表示class类,也可以使用别的名字表示,但是建议使用cls这个名字作为参数;
此外,类方法中操作类变量,直接使用‘cls.类变量’即可。
b.类方法调用:
直接用类来调用:
Student.plus_sum()
用对象来调用类的方法:
student1.plus_sum()
建议还是用类来调用。
实例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class SchoolInfo():
#类变量(对象属性)
name = 'SZU'
location = 'SZ'
size = 2000
Stu_Sum = 0
Stu_Sum2 = 1
Stu_Sum3 = 2
#对象初始化方法,构造函数
def __init__(self,name,location,size):
self.name = name
self.location = location
self.size = size
#构造函数里直接调用类变量
self.__class__.Stu_Sum += 1
SchoolInfo.Stu_Sum2 += 1
print('The '+ str(self.__class__.Stu_Sum) + ' students')
print('The ' + str(SchoolInfo.Stu_Sum2)+ ' students')
SchoolInfo.SumAdd()
#类方法
@classmethod
def SumAdd(cls):
cls.Stu_Sum3 += 1 #直接调用类变量
print('The ' + str(cls.Stu_Sum3) + ' students')

NanJingUni = SchoolInfo('NanJingUni','SuZhou',2200)
HeNanUni = SchoolInfo('HeNanUni','HeNan','500')
#实例对象调用类方法(不建议,虽然Python允许,但逻辑上讲不通)
HeNanUni.SumAdd()

7.4.2 静态方法

python中静态方法格式:
@staticmethod
def add(x, y):
pass
注:静态方法无需传入类似self,cls之类的参数,而且它可以被对象和类调用。静态方法可以访问类变量。尽量少用静态方法,因为它和类与对象的关系很弱,和普通函数区别不大。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class CatInfo():
#类变量(与类相关联)
# 统计有多少只猫
COUNT = 0
name = 'cat_name'
age = 0
eye_color = 'White'

def __init__(self,name,age,eye_color):
#CatInfo.COUNT += 1 # 实例方法中访问类变量
self.name = name
self.age = age
self.eye_color = eye_color
CatInfo.sum_add()

def catch_mouse(self): #类的行为与特性
print('Big mouse')

#类方法
@classmethod
def sum_add(cls):
cls.COUNT += 1
print('第' + str(cls.COUNT) + '只猫咪')

#静态方法
@staticmethod
def special():
print('you are special ' + str(CatInfo.COUNT))

mini = CatInfo('mini',1,'blue')
mini.special()
CatInfo.special()

# result:
g:\Python\Demon2\pk3>b61.py
第1只猫咪
you are special 1
you are special 1

部分小结

7.5 成员可见性与继承

7.5.1 成员的可见性:公开和私有

a. python中定义私有变量或私有方法只需在名称前加双下划线即可;
但若在名称结尾也加了双下划线则不是私有的,应尽量避免定义开头和结尾都有双下划线的变量或函数名称(init函数外部也可以访问,python内部函数,特殊)
b. python中实际上没有私有变量机制,当设置私有变量时python只是将其自动更名,在类外部直接使用更名后的变量名也是可以访问的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class SchoolInfo():
#类变量(对象属性)
name = 'SZU'
location = 'SZ'
size = 2000
Stu_Sum = 0
#通过在类变量前添加__将其有公开性(外部可访问)变为私有性
__score = 0

#对象初始化方法,构造函数
def __init__(self,name,location,size):
self.name = name
self.location = location
self.size = size
SchoolInfo.SumAdd()

#类方法
@classmethod
def SumAdd(cls):
cls.Stu_Sum += 1 #直接调用类变量
print('The ' + str(cls.Stu_Sum) + ' students')

def marking(self,score):
self.__score = score
if score > 0 :
print('得分: ' + str(self.__score))
else:
print('非法得分')



NanJingUni = SchoolInfo('NanJingUni','SuZhou',2200)
#score加了__ 后,只能通过方法来访问,不能直接访问
NanJingUni.marking(-12)
print(NanJingUni.__dict__)
#动态语言,直接动态添加...
NanJingUni.score = 10
NanJingUni.__score = 2
print(NanJingUni.__dict__)
HeNanUni = SchoolInfo('HeNanUni','HeNan',500)
print(HeNanUni.__dict__)
#通过_类名__私有变量名,依旧可以改变私有变量名,但是不推荐
NanJingUni._SchoolInfo__score = 100
print(NanJingUni.__dict__)

# result
g:\Python\Demon2\pk3>b71.py
The 1 students
非法得分
{'name': 'NanJingUni', 'location': 'SuZhou', 'size': 2200, '_SchoolInfo__score': -12}
{'name': 'NanJingUni', 'location': 'SuZhou', 'size': 2200, '_SchoolInfo__score': -12, 'score': 10, '__score': 2}
The 2 students
{'name': 'HeNanUni', 'location': 'HeNan', 'size': 500}
{'name': 'NanJingUni', 'location': 'SuZhou', 'size': 2200, '_SchoolInfo__score': 0, 'score': 10, '__score': 2}

7.5.2 继承

a.python中类继承格式:
class Student(父类):
pass
注:子类继承父类的类变量、实例变量和构造方法。

b. 面向对象三大特性:继承、封装、多态
建议:一个模块写一个类
Python可以多继承,子类可以拥有多个父类
类调用方法时候需要传入self
举例如下:

7.6 子类方法调用父类方法:super关键字

a. python中super关键字用法与java不同,它主要是用来在子类中调用父类方法,如在子类构造函数中调用父类构造函数:
def init(self, name, age):
super(子类名, self).init(name, age)
b. 也可以调用父类普通方法;
当子类的方法和父类的方法同名时,Python会优先调用子类的方法 需要用super关键字去调用父类方法
举例如图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from b8 import Human

class Stu(Human):
sum = 0

def __init__(self,school,name,age):
self.school = school
#Human.__init__(self,name,age)
# 推荐使用super来调用父类初始化
super(Stu,self).__init__(name, age)

@classmethod
def count_stu(cls):
cls.sum += 1
print('For now: '+str(cls.sum) + ' students' )
# 实例方法
def do_homework(self):
super(Stu,self).do_homework()
print('Subclass method')

stu1 = Stu('实验中学','MingMing',14)
Stu.count_stu()
stu1.do_homework()
print(stu1.__dict__)
分享到