主題: property繼承的寫法
假設我們有一個擁有name property的class A:
class A(object): def __init__(self): print ("A init") @property def name(self): print ("A name getter") @name.setter def name(self, x): print ("A name setter")我們想要對A的name property繼承,並且改寫。 改寫的方式想要繼承A原本的一些code再附加新的class的一些code,可以這樣寫:
class B(A): def __init__(self): print ("B init") @property def name(self): super(B, B).name.fget(self) print ("B name getter") @name.setter def name(self, x): super(B, B).name.fset(self, x) print ("B name setter")
或者把fget和fset換成__get__和__set__
class B(A): def __init__(self): print ("B init") @property def name(self): super(B, B).name.__get__(self) print ("B name getter") @name.setter def name(self, x): super(B, B).name.__set__(self, x) print ("B name setter")
為什麼可以這樣? 有興趣的人可以去研究一下 property這個class
還有一點要注意, 其實這樣的寫法是"定義B的自己版本name property", 換句話說,
B.name和A.name是兩個不同的版本。
也就是如果B只有定義getter或是setter,那麼這個property也只會剩下getter或是setter的能力:
#!/usr/bin/python class A(object): def __init__(self): print ("A init") @property def name(self): print ("A name getter") @name.setter def name(self, x): print ("A name setter") class B(A): def __init__(self): print ("B init") @property def name(self): super(B, B).name.__get__(self) print ("B name getter") b = B() b.name b.name = 3
結果:
B init A name getter B name getter Traceback (most recent call last): File "./property.py", line 25, inb.name = 3 AttributeError: can't set attribute Shell 已返回1
結論:
1. child class要改寫parent class的property最好全部都改寫,除非你知道你在做什麼,你真的想閹割parent class的setter or getter or deleter ?
2. child class若要呼叫parent class的class method(memer data), 那就要用 super(B, B).name的寫法
3. property class有實作"descriptor protocol"(__get__, __set__, __delete__這三個function),
property class的__get__會去呼叫 property class的instance method: fget
property class的__set__會去呼叫 property class的instance method: fset
property class的__delete__會去呼叫 property class的instance method: fdel
沒有留言:
張貼留言