Python之面向对象高级编程
一、使用_slots_
1.如何为实例对象绑定实例方法?
正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性。
说明:用MethodType()
方法将实例函数绑定到对象上。
eg:
from types import MethodType
class Student(object):
pass
def set_age(self, age):
self.age = age
s = Student()
s.set_age = MethodType(set_age, s) #(核心语句)第一个参数是要绑定的方法,第二个参数是要绑定的对象,第三个参数是类名(可省略)
s.set_age(30)
print(s.age)
#结果:
30
注意:给一个实例绑定的方法,对另一个实例是不起作用的,另外,用MethodType()
函数需要导入模块。
2.如何为类绑定方法?
说明:直接用类名.方法名 = 方法名
语句,可以为类绑定方法。
eg:
class Student(object):
pass
def set_age(self, age):
self.age = age
Student.set_age = set_age #核心语句
s = Student()
s.set_age(20)
print(s.age)
结果:
20
通常情况下,上面的set_score
方法可以直接定义在class
中,但动态绑定允许我们在程序运行的过程中动态给class
加上功能,这在静态语言中很难实现。
3.使用__slots__
但是,如果我们想要限制实例的属性怎么办?比如,只允许对Student
实例添加name
和age
属性。
为了达到限制的目的,Python允许在定义class
的时候,定义一个特殊的__slots__
变量,来限制该class
实例能添加的属性
class Student(object):
__slots__ = ('name', 'age')
def __init__(self, name):
self.name = name
s = Student('ZhangSan')
s.age = 18
print(s.age)
s.score = 100
print(s.score)
# 结果:
18
Traceback (most recent call last):
File "D:\python\temp.py", line 11, in <module>
s.score = 100
AttributeError: 'Student' object has no attribute 'score'
需要注意两点:
(1)如果设置了__slots__
,无论是类的内部也不能设置其以外的属性。
(2) __slots__
定义的属性仅对当前类实例起作用,对继承的子类是不起作用的。除非在子类中也定义__slots__
,这样,子类实例允许定义的属性就是自身的__slots__
加上父类的__slots__
。
二、使用@property装饰器
在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改,比如成绩属性score
可以赋值200分
,这明显不和逻辑。当然我们可以想java一样定义set
和get
方法,但是这样比较繁琐,没有直接用属性这么直接简单。
那么问题来了,有没有既能检查参数,又可以用类似属性这样简单的方式来访问类的变量呢?
对于追求完美的Python程序员来说,这是必须要做到的!而Python内置的@property
装饰器就是负责把一个方法变成属性调用的:
class Person(object):
def __init__(self, name, age):
self._name = name
self._age = age
# 访问器 - getter方法
@property
def name(self):
return self._name
# 访问器 - getter方法
@property
def age(self):
return self._age
# 修改器 - setter方法
@age.setter
def age(self, age):
self._age = age
def play(self):
if self._age <= 16:
print('%s正在玩飞行棋.' % self._name)
else:
print('%s正在玩斗地主.' % self._name)
def main():
person = Person('王大锤', 12)
person.play()
person.age = 22
person.play()
if __name__ == '__main__':
main()
# 结果:
王大锤正在玩飞行棋.
王大锤正在玩斗地主.
把一个getter
方法变成属性,只需要加上@property
就可以了,此时,@property
本身又创建了另一个装饰器@age.setter
,负责把一个setter
方法变成属性赋值。
你可以在想,什么时候属性用公有的、受保护的、私有的?
(1)如果对属性能够任意的赋值,没有审核条件,就设置为公有
(2)如果对属性的赋值有条件限制,就用受保护的
(3)如果该属性只是在类的内部使用,就设置为私有的
由此可见,一般用@property
装饰器都是用于受保护类型的属性
三、多重继承
MixIn:
在设计类的继承关系时,通常,主线都是单一继承下来的。但是,如果需要“混入”额外的功能,通过多重继承就可以实现,这种多继承设计通常称之为MixIn。
一般我们将其主要继承的类为原名,其他的类加上MixIn
后缀,让其够加清洗的明确是使用了多继承,当然,你不加也完全没关系。下面举一个狗多继承的例子:
class Dog(Mammal, RunnableMixIn, CarnivorousMixIn):
pass
另外说明一下,于Python允许使用多重继承,因此,MixIn就是一种常见的设计。
只允许单一继承的语言(如Java)不能使用MixIn的设计。
四、使用枚举类
当我们需要定义很多常量时,我们需要一个个的设置,很麻烦,这个时候我们可以用枚举类去简化代码:
from enum import Enum
e = Enum('money', ('one', 'five', 'ten'))
print(e, type(e))
for data in e:
print(data.name, data.value)
# 结果:
<enum 'money'> <class 'enum.EnumMeta'>
one 1
five 2
ten 3
value
属性则是自动赋给成员的int常量,默认从1
开始计数。
当然,如果需要更精确地控制枚举类型,可以从Enum派生出自定义类:
from enum import Enum,unique
@unique
class myEnum(Enum):
one = 0
five = 'five'
ten = 10
for data in myEnum:
print(data.name, data.value)
# 结果:
one 0
five five
ten 10
@unique
装饰器可以帮助我们检查保证没有重复值。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/84738.html