主題: 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
 
沒有留言:
張貼留言