一、使用__slots__
限制某个类的实例的属性
给类的实例绑定属性和方法
class Student(object): pass s = Student() s1 = Student() s.name = 'Michael' # 动态绑定属性 print(s.name) def set_age(self, age): self.age = age from types import MethodType s.set_age = MethodType(set_age, s) # 给实例绑定一个方法,只对该实例起作用 s.set_age(23) # s1.set_age(20) #实例s1没有绑定方法
给所有实例都绑定方法
# 给所有实例都绑定方法 def set_score(self, score): self.score = score Student.set_score = set_score # 给class类绑定方法 s1.set_score(99) s.set_score(98)
使用
__slots__
限制实例的属性class Student(object): __slots__ = ('name','age') # 用tuple定义允许绑定的属性名称 s = Student() s.name = 'GuLuyu' s.age = 23 s.score = 99.9 #AttributeError: 'Student' object has no attribute 'score'
使用
__slots__
定义的属性仅对当前类实例起作用,对继承的子类是不起作用的,除非在子类中也定义__slots__
,子类实例允许定义的属性就是自身的__slots__
加上父类的__slots__
。
二、使用@property
对属性的限制
class Student(object): def get_score(self): return self.score def set_score(self,value): if not isinstance(value, int): raise ValueError('must be an integer!') if value < 0 or value > 100: raise ValueError('must between 0~100') self.score = value s = Student() s.set_score(100) s.get_score() s.set_score(-5)
可以用Python内置的
@property
装饰器把一个方法变成属性调用。把一个getter方法变成属性,只需要加上@property
就可以,此时,@property
本身又创建了另一个装饰器@score.setter
,把一个setter方法变成属性赋值。class Student(object): @property def score(self): return self._score # 属性的方法名不要跟实例变量名重名score\_score @score.setter def score(self, value): if not isinstance(value, int): raise ValueError('must be an integer!') if value < 0 or value > 100: raise ValueError('must between 0~100') self._score = value s = Student() s.score = 96 print(s.score)
三、多重继承
通过多重继承,一个子类就可以同时获得多个父类的所有功能。
class Runnable(object): def run(self): print('Running...') class Flyable(object): def fly(self): print('Flying...') class Animal(object): pass class Mammal(Animal): pass class Bird(Animal): pass class Dog(Mammal, Runnable): pass class Bat(Mammal, Flyable): # 蝙蝠 pass class Parrot(Bird, Flyable): # 鸵鸟 pass class Ostrich(Bird, Runnable): # 鹦鹉 pass
类层次设计
Mixln即
Mix-in
,常被译为“混入”,是一种编程模式,在Python等面向对象语言中,通常它是实现了某种功能单元的类,用于被其他子类继承,将功能组合到子类中。利用Python的多重继承,子类可以继承不同功能的 Mixin类,按需动态组合使用。当多个类都实现了同一种功能时,这时应该考虑将该功能抽离成Mixin类。上例中,为了更好地看出继承关系,可以把Runnable和Flyable改为RunnableMixIn和FlyableMixIn。
只允许单一继承的语言(如Java)不能使用MixIn的设计。
四、枚举类
枚举类型定义一个class类型,然后,每个常量都是class的一个唯一实例。Python提供了
Enum
类来实现这个功能: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)
value
属性则是自动赋给成员的int
常量,默认从1
开始计数如果需要更精确地控制枚举类型,可以从
Enum
派生出自定义类:from enum import Enum, unique @unique #@unique装饰器可以帮助我们检查保证没有重复值 class Weekday(Enum): Sun = 0 # Sun的value被设定为0 Mon = 1 Tue = 2 Wed = 3 Thu = 4 Fri = 5 Sat = 6 print(Weekday.Mon) print(Weekday.Tue.value)
既可以用成员名称引用枚举常量,又可以直接根据value的值获得枚举常量。
五、元类
type()
函数既可以返回一个对象的类型,又可以创建出新的类型,比如,我们可以通过type()
函数创建出Hello
类,而无需通过class Hello(object)...
的定义:def fn(self, name='world'): # 先定义函数 print('Hello, %s.' % name) Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class h = Hello() # Hello, world. h.hello() print(type(Hello))
要创建一个class对象,
type()
函数依次传入3个参数:- class的名称;
- 继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;
- class的方法名称与函数绑定,这里我们把函数
fn
绑定到方法名hello
上。
metaclass
,直译为元类,简单的解释就是:当我们定义了类以后,就可以根据这个类创建出实例,所以:先定义类,然后创建实例。
真叫人头大