我才刚刚开始学习python中的OOP主题,并且遇到了一些麻烦的主题,例如装饰器/属性以及python中所有“私有”方法的技巧。
可以肯定地说,使用 @property 就像使用属性一样,但是在幕后有一个函数可以执行某些操作吗? (例如,检查输入)
另外,使用 @ is_barking.setter 就像重载其他语言(例如C ++)的赋值运算符一样吗?因为我还可以检查输入内容之类的东西
这是代码:
class Dog():
def __init__(self,name):
self.name = name
@property
def is_barking(self):
try:
return self._is_barking
except AttributeError as error:
self._is_barking = False
return self._is_barking
@is_barking.setter
def is_barking(self,value):
self._is_barking = value
def main():
rexi = Dog("rexi")
print(rexi.is_barking)
rexi.is_barking = True
print(rexi.is_barking)
main()
>> False
>> True
非常感谢您!
答案 0 :(得分:1)
是的,这是种正确的。设置器使您可以仅拦截对该属性名称的分配 。
它不会超载分配,descriptor protocol在运行时可以轻松实现,property
对象是 data 描述符对象;他们可以截获它们所属的类的实例的所有属性访问(获取,设置和删除),因此可以否决任何这些操作。这与C ++赋值重载不同,后者在编译时(IIRC)处理并在整个实例上运行,而不仅仅是实例上的属性。
真正发生的是,属性分配是由在object.__setattr__
special method中为其实例分配了属性的类对象处理的。该类将检查给定的属性名称是否被类中的对象 覆盖,该对象是使用__set__
或__delete__
方法的描述符对象。
因此,可以通过__setattr__
特殊方法将 general 属性分配挂钩,Python将属性设置委托给实例的父类型:
# foo.attr = bar -> Python essentially calls __setattr__ on the class
type(foo).__setattr__(foo, "attr", bar)
,然后在通常的简单情况下变成
foo.__dict__["attr"] = bar
但实际上,在type(foo)
及其父类上搜索了数据描述符 first 。如果存在这样的对象,那么它的任务是处理属性设置:
obj = None
for cls in reversed(type(foo).__mro__):
if "attr" in cls.__dict__:
obj = cls.__dict__["attr"]
break
if hasattr(obj, "__set__") or hasattr(obj, "__delete__"): # data descriptor?
try:
obj.__set__(foo, bar)
except AttributeError:
raise AttributeError("can't set attribute")
else:
foo.__dict__["attr"] = bar
property
对象实现__set__
,此实现将调用您的setter(如果已设置)。