面向对象高级编程
标签(空格分隔):面向对象
在此输入正文
使用 __slots__
在创建一个class后,在对其实例化之后对实例可以再绑定属性和方法。例如,
class Student():
pass
>>>a = Student()
>>>a.name = 'a' #绑定一个属性
#绑定一个方法
>>>def set_age(self, age):
self.age = age
>>>from types import MethodType
>>>s.set_age = MethodType(set_age, s)
>>>s.set_age(25)
>>>s.age
25
但是这是给其中一个实例进行的绑定,对其他实例不影响。
如果需要给class下所有实例进行绑定,需要对class进行操作。
>>> def set_score(self, score):
self.score = score
>>>Student.set_score = set_score
给class绑定方法之后,所有该class的实例都能使用,并且不管在绑定之前还是之后的实例都可以。
动态的绑定方法在静态语言中很难实现。
使用__slots__
(翻译:插槽)
为了限制实例的属性,比如只允许对Student的实例添加name
和age
属性。
class Student():
__slots__('name', 'age')
即在实例中扩展的属性,只能有name和age。在绑定其他属性时,会产生AttributeError
的错误。
注意!.__slots__
只对当前类的实例有效,但无法作用于继承的子类。
使用@property
比如
s = Student()
s.score = 999
这样的实例就把s的属性暴露了出来,并且没有办法对属性进行检查。所以需要使用set_score()
方法进行设置属性,并在方法中进行检查,如果有问题就可以抛出异常。
那么有没有既可以检查参数,又可以类似直接调用属性这样的简单的方法访问类的变量呢。
使用装饰器,可以给函数动态加上功能。
内置的@property装饰器负责把一个方法变成属性调用:
class Student(object):
@property
def score(self):
return self.score
@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError('Score must be an int')
if value<0 or value >100:
raise ValueError('score must between 0-100')
self.__score = value
把一个getter方法变成属性,只需要加上@property就可以,此时@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值。于是就有了一个可控的属性操作,如上例。
>>>a = Student()
>>>s.score = 60 #可以完成,实际应用的是s.set_score(60)
>>>s.score #实际应用s.get_score()
60
>>>s.score = 120 #使用s.set_score(120),经方法检查会报错
另:@property,除了创建一个@score.setter装饰器外,还创建了其他的装饰器,比如@score.delete等。可以利用help()方法查看。
多重继承
继承是面向对象变成的一个重要的方式,因为通过继承,子类就可以继承父类的功能。
如果按照‘哺乳动物’和‘鸟类’归类,可以设计出继承的类的层次。
如果按照‘能跑’和‘能飞’归类,可以设计出另一种继承的类的层次。
但是如果将两种分类都包含进来,就会导致层次越来越复杂。
使用多继承,就可以使用多种结构的内容。
class Animal(object):
pass
class Mammal(Animal):
pass
class Bird(Animal):
pass
class Dog(Mammal):
pass
class Parrot(Bird):
pass
现在给dog和parrot添加run和fly的功能。
class Runnable(object):
def run(self):
print('run.....')
class Flyable(object):
def fly(self):
print('fly.........')
然后使用多继承给dog和parrot增加功能:
class Dog(Mammal, Runnable):
pass
这样dog就同时继承了Mammal的功能和Runnable的功能。
MixIn
通常继承关系,都是从一条主线单一继承下来。但是如果在某一层要混入其他普遍的功能,就需要使用多继承的方法。比如dog方法,除了继承mammal
外还要继承Runnable
,这种设计就叫MixIn
类似,还可以定义肉食等等定义,从而使MixIn扩展功能。
MixIn的目的就是给一个类增加多个功能,这样,在设计类的时候,我们优先考虑通过多重继承来组合多个MixIn的功能,而不是设计多层次的复杂的继承关系。