关于python类和装饰器
当我学习python的“属性”时,出乎意料的是,输出与预期不一样。下面的代码说明:关于python类和装饰器,python,properties,decorator,init,Python,Properties,Decorator,Init,当我学习python的“属性”时,出乎意料的是,输出与预期不一样。下面的代码说明: class HideX(object): def __init__(self,x): self.x = x def get_x(self): return ~self.__x def set_x(self,x): assert isinstance(x,int),\ '"x" must be an integer!'
class HideX(object):
def __init__(self,x):
self.x = x
def get_x(self):
return ~self.__x
def set_x(self,x):
assert isinstance(x,int),\
'"x" must be an integer!'
self.__x = ~x
x = property(get_x, set_x)
inst = HideX(20)
#inst.x = 20#
当它执行inst=HideX(20)
时。我想它会调用\uuuu init\uuuu(self,x)
,因此将执行指令self.x=x
。问题出现了。我认为它不会调用x=property(get\u x,set\u x)
,因为self.x
在类的主体中(它在类的顶部)。我一直认为
只有在课外(如#…#所示),我们才能访问x=property(get\u x,set\u x)
我错了吗?你能理解我的意思吗
解决:
经过反复测试,我惊奇地发现,当我们执行inst=HideX(20)
时,代码x=property(get\ux,set\ux)
将首先被调用,而不是“init(self,x)”。完全超出我的预期!!!(在java中,当我们创建一个实例时,类的init()将首先被调用,我想,也许我错了)
(1) 你能给我解释一下内在机制吗?我是新手,谢谢你的耐心
以下代码是我从中复制的段:
class HideXX(object):
def __init__(self, x):
self.x = x
@property
def x():
def fget(self):
return ~self.__x
def fset(self,x):
assert isinstance(x,int),\
'"x" must be an integer!'
self.__x = ~x
return locals()
#x = property(**x())
inst = HideXX(1)
但它不能正确运行
错误代码为:
File "<string>", line 21, in <module>
File "<string>", line 4, in __init__
AttributeError: can't set attribute
文件“”,第21行,在
文件“”,第4行,在_init中__
AttributeError:无法设置属性
(2) 这本书错了吗??当我删除@property并添加代码“x=property(**x())”时,它可以工作
你能给我解释一下原因吗?非常感谢您的第一个问题,答案很简单,x是类的属性(不是类的对象/实例),它将在定义类时(而不是创建其对象时)进行计算 举个例子来说明这一点-
>>> class CA:
... y = print("Hello")
... def __init__(self):
... print("Blah")
...
Hello
>>> c = CA()
Blah
正如您可以看到的,y
的值是在定义类时计算出来的,这与类中的所有函数相同,它们是在定义类时定义的,但只有在调用函数时才会计算
另外,使用@property与属性(**x())
不同,当您使用后者时,**x()
解析为-
{'fget': <function HideXX.x.<locals>.fget at 0x00943B28>, 'fset': <function HideXX.x.<locals>.fset at 0x00943CD8>}
{'fget':,'fset':}
然后这些位置参数用于设置属性
x
的getter
和setter
,而@property
注释用于定义属性x的getter。感谢您的耐心等待。你的第一个答案对我很有帮助,第二个答案也很清楚。但是上面的示例(@property def x():…)是从名为《Python编程,第二版》的书中复制的。这本书错了吗?还是我做错了什么?比如说你犯了错误?这是直接从书中抄来的吗?是的,我从422页抄来的,网络上有pdf[是的,我认为这本书有点错误,在第二种情况下,因为我们使用的是装饰器
而不是静态类变量,所以我们必须执行HideXX.x=10
或将HideXX.x
设置为某个任意数,然后我们才能为其创建实例。此外,如果您认为答案已经回答了您的问题,那么当然,请记住接受它们(通过点击答案左侧的勾号)。这将有助于社区。