0%

python-面对对象进阶

1. 面对对象进阶

为了能够更好的使用面向对象编程思想进行程序开发,还需要对Python中的面向对象编程进行更为深入的了解。

2. @property装饰器

我们之前的建议是将属性命名以单下划线开头,通过这种方式来暗示属性是受保护的,不建议外界直接访问,那么如果想访问属性可以通过属性的getter(访问器)和setter(修改器)方法进行对应的操作。如果要做到这点,就可以考虑使用@property包装器来包装getter和setter方法,使得对属性的访问既安全又方便,代码如下所示:


3. slots魔法

如果我们需要限定自定义类型的对象只能绑定某些属性,可以通过在类中定义slots变量来进行限定。需要注意的是slots的限定只对当前类的对象生效,对子类并不起任何作用


4. 静态方法和类方法

之前,我们在类中定义的方法都是对象方法,也就是说这些方法都是发送给对象的消息。实际上,我们写在类中的方法并不需要都是对象方法,例如我们定义一个“三角形”类,通过传入三条边长来构造三角形,并提供计算周长和面积的方法,但是传入的三条边长未必能构造出三角形对象,因此我们可以先写一个方法来验证三条边长是否可以构成三角形,这个方法很显然就不是对象方法,因为在调用这个方法时三角形对象尚未创建出来(因为都不知道三条边能不能构成三角形),所以这个方法是属于三角形类而并不属于三角形对象的。我们可以使用静态方法来解决这类问题,代码如下所示

和静态方法比较类似,Python还可以在类中定义类方法,类方法的第一个参数约定名为cls,它代表的是当前类相关的信息的对象(类本身也是一个对象,有的地方也称之为类的元数据对象),通过这个参数我们可以获取和类相关的信息并且可以创建出类的对象,代码如下所示。
获取当地时间:

1
2
3
4
from time import time,localtime
def now(clc):
ctime=localtime(time())
return clc(ctime.tm_hour,ctime.tm_min,ctime.tm_sec)


5. 类之间的关系

类和类之间的关系有三种:is-a、has-a和use-a关系。分别为继承、关联、依赖


6. 继承和多态

  1. 提供继承信息的我们称之为父类,也叫超类或基类;得到继承信息的我们称之为子类,也叫派生类或衍生类。子类除了继承父类提供的属性和方法,还可以定义自己特有的属性和方法,所以子类比父类拥有的更多的能力,在实际开发中,我们经常会用子类对象去替换掉一个父类对象,这是面向对象编程中一个常见的行为,对应的原则称之为里氏替换原则。

  2. 子类在继承了父类的方法后,可以对父类已有的方法给出新的实现版本,这个动作称之为方法重写(override)。通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本,当我们调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态。

例子:

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
class Person(object):
"""人"""

def __init__(self, name, age):
self._name = name
self._age = age

@property
def name(self):
return self._name

@property
def age(self):
return self._age

@age.setter
def age(self, age):
self._age = age

def play(self):
print('%s正在愉快的玩耍.' % self._name)

def watch_av(self):
if self._age >= 18:
print('%s正在观看美剧.' % self._name)
else:
print('%s只能观看《熊出没》.' % self._name)


class Student(Person):
"""学生"""

def __init__(self, name, age, grade):
super().__init__(name, age)
self._grade = grade

@property
def grade(self):
return self._grade

@grade.setter
def grade(self, grade):
self._grade = grade

def study(self, course):
print('%s的%s正在学习%s.' % (self._grade, self._name, course))


class Teacher(Person):
"""老师"""

def __init__(self, name, age, title):
super().__init__(name, age)
self._title = title

@property
def title(self):
return self._title

@title.setter
def title(self, title):
self._title = title

def teach(self, course):
print('%s%s正在讲%s.' % (self._name, self._title, course))


def main():
stu = Student('王大锤', 15, '初三')
stu.study('数学')
stu.watch_av()
t = Teacher('骆昊', 38, '老叫兽')
t.teach('Python程序设计')
t.watch_av()


if __name__ == '__main__':
main()

结果: