Python 3.x 修饰符意外地改变了Python中的构造函数行为
下面,我展示了一个更复杂代码的简化示例,但它完全代表了我遇到的问题 第1部分:这很好,没有问题:Python 3.x 修饰符意外地改变了Python中的构造函数行为,python-3.x,python-decorators,Python 3.x,Python Decorators,下面,我展示了一个更复杂代码的简化示例,但它完全代表了我遇到的问题 第1部分:这很好,没有问题: class Animal(): def __init__(self, animal_name = "no name given"): self.set_name(animal_name) def get_name(self): return self._animal_name def set_n
class Animal():
def __init__(self, animal_name = "no name given"):
self.set_name(animal_name)
def get_name(self):
return self._animal_name
def set_name(self, animal_name):
self._animal_name = animal_name
class Dog(Animal):
def __init__(self, dog_breed = "no breed", dog_name = "no name given"):
self._dog_breed = dog_breed
super().__init__(dog_name)
def get_breed(self):
print(self._dog_breed)
x = Dog('Greyhound', 'Rich')
第2部分:引入getter和setter装饰器后,代码停止工作:
class Animal():
def __init__(self, animal_name = "no name given"):
#THE LINE BELOW SEEMS TO CAUSE AN ISSUE
self.name(animal_name)
@property
def name(self):
return self._animal_name
@name.setter
def name(self, animal_name):
self._animal_name = animal_name
class Dog(Animal):
def __init__(self, dog_breed = "no breed", dog_name = "no name given"):
self._dog_breed = dog_breed
super().__init__(dog_name)
def get_breed(self):
print(self._dog_breed)
x = Dog('Greyhound', 'Rich')
输出:AttributeError:“Dog”对象没有属性“\u animal\u name”
当我在第2部分中保留decorators,但将Animal类中的构造函数更改为:
class Animal():
def __init__(self, animal_name = "no name given"):
self._animal_name=animal_name
它起作用了
我只是好奇为什么它在上面第2部分的例子中不起作用?简短回答: 线路
self.name(animal_name)
可分为两部分:
tmp = self.name
tmp(animal_name)
首先,self.name
调用getter,结果作为函数处理。getter使用返回self.\u animal\u name
并且由于从未调用setter,因此会发生相应的错误
长答案:
让我们学习以下课程:
class Animal:
def __init__(self, animal_name):
self.name(animal_name)
@property
def name(self):
return self._animal_name
@name.setter
def name(self, animal_name):
self._animal_name = animal_name
要了解线路是什么
self.name(animal_name)
事实上,你首先需要了解装饰师
代码
@dec
def func(a, b, ...):
[...]
相当于
def func_impl(a, b, ...):
[...]
func = dec(func_impl)
self.get_name()(animal_name)
(除非您不能直接调用func_impl
)。有关更多信息,请参见
这意味着您可以从上面编写Animal
类,而无需使用decorator:
class Animal:
def __init__(self, animal_name):
self.name(animal_name)
def get_name(self):
return self._animal_name
name = property(get_name)
def set_name(self, animal_name):
self._animal_name = animal_name
name = name.setter(set_name)
为了理解这段代码,您需要理解内置的属性
,它是一个类。有关详细信息,请参阅
行name=property(get\u name)
创建类型为property
的对象。检索属性值时,将调用get\u name
行name=name.setter(set\u name)
首先调用name.setter(set\u name)
,创建属性的副本,然后用此副本覆盖name
。为副本赋值时,调用set\u name
总之,name
是一个类型为property
的对象,它使用get\u name
作为getter,使用set\u name
作为setter
这有什么帮助?
您需要了解这一点:name
不是一个函数。这是一种财产。它是不可调用的
有问题的路线
self.name(animal_name)
实际上相当于
def func_impl(a, b, ...):
[...]
func = dec(func_impl)
self.get_name()(animal_name)
这解释了错误消息:构造函数调用getter,getter尝试使用
返回self.\u animal\u name
。但是由于setter还没有被调用,self.\u animal\u name
还没有被设置。如果您使用self.name=animal\u name
而不是self.name(animal\u name)
,它会起作用吗?是的,这就解决了问题。因此,当我使用decorators时,我需要将类中的getter和setter方法视为一个属性,即使在类构造函数中也是如此:我现在就知道了。非常感谢。