Python類與物件技巧(2):拓展子類屬性
阿新 • • 發佈:2018-11-12
更多的時候,我們需要拓展父類中property的功能。
class Person: def __init__(self, name): self.name = name # Getter funtion @property def name(self): return self._name # Setter function @name.setter def name(self, value): if not isinstance(value, str): raise TypeError('Expected a string') self._name = value #Deleter function @name.deleter def name(self): raise AttributeError("Can't delete attribute") class SubPerson(Person): @property def name(self): print('Getting parent class name') return super().name @name.setter def name(self, value): print('Setting name to', value) super(SubPerson, SubPerson).name.__set__(self, value) @name.deleter def name(self): print('Deleting name') super(SubPerson, SubPerson).name.__delete__(self) p = SubPerson('ziheng') # >>> Setting name to ziheng print(p.name) # >>> Getting parent class name # ziheng p.name = 'chunxu' # >>> Setting name to chunxu
在子類中擴充套件一個property可能會引起很多不易察覺的問題。 因為property其實是 getter、setter 和 deleter 方法的集合,而不是單個方法。 因此,當擴充套件property的時候,需要先確定是否要重新定義所有方法還是隻修改其中一個。 在該例子中,所有的property方法都被重新定義。 在每個方法中,使用了 super() 來呼叫父類的實現。
在 setter 函式中使用 super(SubPerson, SubPerson).name.__set__(self, value) 的語句是沒有錯的。 為了委託給之前定義的setter方法,需要將控制權傳遞給之前定義的name屬性的 __set__() 方法。 不過,獲取這個方法的唯一途徑是使用類變數而不是例項變數來訪問它。 這也是為什麼要使用 super(SubPerson, SubPerson) 的原因。
如果只想重定義其中一個方法,那隻使用 @property 本身是不夠的。
錯誤程式碼例項;
class SubPerson(Person): @property # Doesn't work def name(self): print('Getting name') return super().name s = SubPerson('ziheng') # >>> Traceback (most recent call last): # File "<stdin>", line 1, in <module> # File "****.py", line 5, in __init__ # self.name = name # AttributeError: can't set attribute
正確程式碼例項:
class SubPerson(Person):
@Person.name.getter
def name(self):
print('Getting name')
return super().name
s = SubPerson('ziheng')
print(s.name)
# >>> Getting name
# 'ziheng'
博文參考《python3-cookbook》