多态
我们编写一个名为 Animal 的 class, 有一个 run() 方法可以直接打印:
class Animal(object): def run(self): print(‘Animal is running...‘)
要理解多态的好处,我们还需要再编写一个函数,这个函数接受一个 Animal 类型的变量:
def run_twice(animal): animal.run() animal.run()
当我们传入Animal的实例时,run_twice()就打印出:
>>> run_twice(Animal()) Animal is running... Animal is running...
如果我们再定义一个Tortoise类型,从 Animal 派生:
class Tortoise(Animal): def run(self): print(‘Tortoise is running slowly...‘)
当我们调用run_twice()时,传入Tortoise的实例:
>>> run_twice(Tortoise()) Tortoise is running slowly... Tortoise is running slowly...
多态的好处就是,当我们需要传入 Tortoise 时,我们只需要接收 Animal 类型就可以了,因为 Tortoise 是 Animal 类型,然后,按照 Animal 类型进行操作即可。由于 Animal 类型有 run() 方法,因此,传入的任意类型,只要是 Animal 类或者子类,就会自动调用实际类型的 run() 方法,这就是多态的意思。
类成员
普通字段(data attributes): Data attributes are pieces of data held by a specific instance of a class.
静态字段(class attributes): Python also supports class attributes, which are variables owned by the class itself.
普通对象只能由对象访问,静态字段应该由类访问,静态字段在代码加载时已经创建。
普通方法 (instance method)
静态方法(static method)
与普通方法的不同:
1)去掉 self
2)使用 @staticmethod 装饰器
3)静态方法由类调用,其实就是函数,只是与这个类相关
类方法(class method)
类方法是一种特殊的静态方法,也由类调用,与静态方法不同:
1)自动传入一个 cls 参数,cls 为函数名
class Province: @classmethod def f2(cls): print(cls) hn = Province(‘henan‘) hn.f2()
输出为:<class ‘__main__.Province‘>
Class methods are methods that are not bound to an object, but to a class!
>>> class Pizza(object): ... radius = 42 ... @classmethod ... def get_radius(cls): ... return cls.radius ... >>> >>> Pizza.get_radius <bound method type.get_radius of <class ‘__main__.Pizza‘>> >>> Pizza().get_radius <bound method type.get_radius of <class ‘__main__.Pizza‘>> >>> Pizza.get_radius is Pizza().get_radius True >>> Pizza.get_radius() 42
对象名加 () 执行 __call__
类名加 () 执行 __init__
静态方法与类方法的对比:
#!/usr/bin/env python class Smoothie(object): YOGURT = 1 STRAWBERRY = 2 BANANA = 4 MANGO = 8 @staticmethod def blend(*mixes): return sum(mixes) / len(mixes) @staticmethod def eternal_sunshine(): return Smoothie.blend(Smoothie.YOGURT, Smoothie.STRAWBERRY, Smoothie.BANANA) @staticmethod def mango_lassi(): return Smoothie.blend(Smoothie.YOGURT, Smoothie.MANGO)
使用静态方法,需要 hardcode class 的名字,而使用类方法:
#!/usr/bin/env python class Smoothie(object): YOGURT = 1 STRAWBERRY = 2 BANANA = 4 MANGO = 8 @staticmethod def blend(*mixes): return sum(mixes) / len(mixes) @classmethod def eternal_sunshine(cls): return cls.blend(cls.YOGURT, cls.STRAWBERRY, cls.BANANA) @classmethod def mango_lassi(cls): return cls.blend(cls.YOGURT, cls.MANGO)
合理使用类方法的第一个好处:当需要改类的名字时,类的方法不需要改动。
另一个好处就是,当我们再创建一个 subclass 时,
class BetterSmoothie(Smoothie): YOGURT = ‘yogurt‘ STRAWBERRY = ‘strawberry‘ BANANA = ‘banana‘ MANGO = ‘mango‘ @staticmethod def blend(*mixes): return ‘, ‘.join(mixes)
我们更新了静态方法 blend, 从 Smoothie 继承的类方法 eternal_sunshine() 和 mango_lassi() 会自动使用新的 blend 方法。
属性:
class Pager: def __init__(self, all_count): self.all_count = all_count @property def all_pager(self): a1, a2 = divmod(self.all_count, 10) if a2 == 0: return a1 else: return a1 + 1 @all_pager.setter def all_pager(self, value): print(value) @all_pager.deleter def all_pager(self): print(‘del all_pager‘)
对一个普通方法使用装饰器 @property 就相当于构造了一个动态字段,构造的属性只能取值,不能赋值,除非使用 @func_name.setter 装饰器再构造一个函数,使用 @func_name.deleter 装饰器使属性可删除,这样属性就具有完整的字段属性。
一个例子:
class Celsius: def __init__(self, temperature = 0): self.set_temperature(temperature) def to_fahrenheit(self): return (self.get_temperature() * 1.8) + 32 # new update def get_temperature(self): return self._temperature def set_temperature(self, value): if value < -273: raise ValueError("Temperature below -273 is not possible") self._temperature = value
在 instance variable 前加一个 ‘_’ 意思是指明该字段应为私有字段,但是从外部依然可以访问。
class Celsius: def __init__(self, temperature = 0): self.temperature = temperature def to_fahrenheit(self): return (self.temperature * 1.8) + 32 def get_temperature(self): print("Getting value") return self._temperature def set_temperature(self, value): if value < -273: raise ValueError("Temperature below -273 is not possible") print("Setting value") self._temperature = value temperature = property(fget=get_temperature, fset=set_temperature)
最后一行的意思是,property attaches some code (get_temperature and set_temperature) to the member attribute accesses (temperature). 当试图获取对象的 temperature 字段时会自动执行 get_temperature 方法 instead of a dictionary (__dict__) look-up.
Super 方法
class C1: def f1(self): # print(‘c1.f1‘) return 123 class C2(C1): def f1(self): # 主动执行 C2 的父类的 f1 方法 # super(C2,self) 相当于实例化了 C1 class ret = super(C2,self).f1() print(‘c2.f1‘) return ret
super 方法可以主动执行父类的同名方法。