使用__slots__
为了达到限制实例的属性的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制class实例能添加的属性。
class Student(object): __slots__ = ('name', 'age') def set_age(self, age): self.age = age class GraduateStudent(Student): pass s = Student() s.name = 'A' s.score = 32 gs = GraduateStudent() gs.name = 'B' gs.score = 20
由于’score’没有被放到__slots__中,所以不能绑定score属性,但是__slots__定义的属性今对当前类实例起作用,对继承的子类是不起作用的。
除非在子类中也定义__slots__,这样,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__。
使用@property
在绑定属性时,如果我们直接把属性暴露出去,虽然写起来简单,但是,没办法检查参数,导致可以把成绩随便更改。
有没有既能检查参数,又可以用类似属性这样简单的方式来访问类的变量呢?Python内置的@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 integer!') if value < 0 or value > 100: raise ValueError('score must between 0 ~ 100!') self._score = value s = Student() s.score = 'nasm' s.score = -1 s.score = 80
@property还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性
class Student(object): @property def birth(self): return self.__birth @birth.setter def birth(self, vaule): self.__birth = vaule @property def age(self): return 2015 - self.__birth s = Student() s.birth = 32 print(s.age)
多重继承
class Animal(object): pass # 大类: class Mammal(Animal): pass class Bird(Animal): pass # 能力: class Runnable(object): def run(self): print('Running...') class Flyable(object): def fly(self): print('Flying...') # 各种动物: class Dog(Mammal, Runnable): pass class Bat(Mammal): pass class Parrot(Bird): pass class Ostrich(Bird): pass
MixIn
在设计类的继承关系时,通常,主线都是单一继承下来的,例如,Ostrich继承自Bird。但是,如果需要“混入”额外的功能,通过多重继承就可以实现,比如,让Ostrich除了继承自Bird外,再同时继承Runnable。这种设计通常称之为MixIn。
为了更好地看出继承关系,我们把Runnable和Flyable改为RunnableMixIn和FlyableMixIn。类似的,你还可以定义出肉食动物CarnivorousMixIn和植食动物HerbivoresMixIn,让某个动物同时拥有好几个MixIn
class Dog(Mammal, RunnableMixIn, CarnivorousMixIn): pass
使用枚举类
from enum import Enum Month= Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')) for name, member in Month.__members__.items(): print(name, '=>', member, ',', member.value)
如果需要更精确地空值枚举类型,可以从从Enum派生出自定义类
from enum, unique @unique class Weekday(Enum): Sun = 0 # Sun的value被设定为0 Mon = 1 Tue = 2 Wed = 3 Thu = 4 Fri = 5 Sat = 6
使用元类
metaclass(元类):先定义类。然后创建实例
# metaclass是类的模板,所以必须从`type`类型派生: class ListMetaclass(type): def __new__(cls, name, bases, attrs): attrs['add'] = lambda self, value: self.append(value) return type.__new__(cls, name, bases, attrs)
class MyList(list, metaclass=ListMetaclass): pass