英文:
Question about extending a property in a sub class
问题
I am working through the O'Reilly Python Cookbook.
I have a question about the following code, to do with extending a property in a sub class:
class Person:
def __init__(self, name):
self.name = name
# Getter function
@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
@name.deleter
def name(self):
raise AttributeError("Can't delete attribute")
class SubPerson(Person):
@property
def name(self):
print('Getting 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)
I'm confused about:
super(SubPerson, SubPerson).name.__set__(self, value)
With super(SubPerson, SubPerson)
, it seems to be accessing the method as a class variable. Why can't it access the method as an instance variable instead?
Also, how does __set__
and @name.setter
relate to one another? Aren't they effectively the same thing?
Could the same line be written as:
super(SubPerson, SubPerson).name.settr(self, value)
英文:
I am working through the O Reilly Python Cookbook.
I have a question about the following code, to do with extending a property in a sub class:
class Person:
def __init__(self, name):
self.name = name
# Getter function
@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
@name.deleter
def name(self):
raise AttributeError("Can't delete attribute")
class SubPerson(Person):
@property
def name(self):
print('Getting 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)
I'm confused about:
super(SubPerson, SubPerson).name.__set__(self, value)
With super(SubPerson,SubPerson) it seems to be accessing the method as a class variable, why cant it access the method as an instance variable instead?
Also, how does set and @name.setter relate to one another? Aren't they effectively the same thing?
Could the same line be written as:
super(SubPerson, SubPerson).name.settr(self,value)
答案1
得分: 1
第一个问题涉及到 super(SubPerson, SubPerson)
。这只是一种访问实际的 property 对象的技巧,该对象是类的属性之一。在这里需要的是 Person.name
,因为一旦我们有了它,就可以使用属性的设置器和删除器函数。使用 super().name
或任何实例类型的访问存在问题,因为 super()
不会返回一个对象,而是返回一个代理。代理上的属性名称只会提供对获取器的访问。
第二个问题涉及到 @name.setter
。事实上,property
作为初始装饰器将 name
定义为一个属性对象。属性的 setter
属性也是一个装饰器,它在其对象上设置了设置器函数并返回该对象。这意味着它只能在类定义时使用。实际上,@name.setter
块大致相当于在类定义后的以下代码:
def foo(self, value):
...
SubPerson.name = SubPerson.name.setter(foo)
您想要使用的方法是属性的 fset
属性。这意味着设置器部分可以这样编写:
@name.setter
def name(self, value):
print('Setting name to', value)
super(SubPerson, SubPerson).name.fset(self, value)
英文:
There are two questions here.
First is about super(SubPerson, SubPerson)
. It is just a trick to access the actual property object which is an attribute of the class. What is wanted here is Person.name
, because once we have it, we can use the setter and deleter functions of the property. The problem with super().name
or with any instance type access is that super()
does not return an object but a proxy. And the property name on the proxy will only give access to the getter.
The latter is about @name.setter
. In fact property
as the initial decorator defines name
as a property object. The setter
attribute of a property is also a decorator that sets the setter function on its object and returns the object. That means that it is only intented to be used at class definition time. In fact the @name.setter
bloc is roughly equivalent to the following code after the class definition:
def foo(self, value):
...
SubPerson.name = SubPerson.name.setter(foo)
The method that you wanted to use is the fset
attribute of the property. That means that the setter part could have been written as :
@name.setter
def name(self, value):
print('Setting name to', value)
super(SubPerson, SubPerson).name.fset(self, value)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论