关于 python class __init__ 和装饰器
About python class __init__ and Decorators
当我学习 python 的 'property' 时,令我惊讶的是,输出与下面所示的 expected.The 代码不同:
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)
。我想它会调用 __init__(self,x)
所以指令 self.x = x
会被执行。出现问题。我认为它不会调用 x = property(get_x, set_x)
因为 self.x
在 class 的正文中(它在 class 的顶部)。我一直认为
只有在 class 之外(如 #..# 所示)我们才能访问 x = property(get_x, set_x)
我错了吗?你能明白我的意思吗?
已解决:
经过反复测试,我惊奇地发现,当我们执行inst = HideX(20)
时,代码x = property(get_x, set_x)
将首先被调用,而不是'init(self,x)'。完全出乎我的意料!!!(在java中,当我们创建一个实例,我认为 class 的 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
(2)书错了吗??当我删除 @属性 并添加代码 'x = property(**x())' 时,它起作用了!!!
你能帮我解释一下原因吗?非常感谢
对于你的第一个问题,答案很简单,x是class的一个属性(不是class的object/instance),当class 被定义(不是在创建它的对象时)。
一个例子来说明这一点 -
>>> class CA:
... y = print("Hello")
... def __init__(self):
... print("Blah")
...
Hello
>>> c = CA()
Blah
正如您所见,y
的值是在定义 class 时计算的,它与 class 中的所有函数相同,它们在 class 已定义,但仅在调用函数时才对其求值。
此外,使用 @属性 与 property(**x())
不同,当您使用后者时,**x()
解析为 -
{'fget': <function HideXX.x.<locals>.fget at 0x00943B28>, 'fset': <function HideXX.x.<locals>.fset at 0x00943CD8>}
然后这些位置参数用于为 属性 x
设置 getter
和 setter
,而 @property
注释用于为 属性 x.
定义 getter
当我学习 python 的 'property' 时,令我惊讶的是,输出与下面所示的 expected.The 代码不同:
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)
。我想它会调用 __init__(self,x)
所以指令 self.x = x
会被执行。出现问题。我认为它不会调用 x = property(get_x, set_x)
因为 self.x
在 class 的正文中(它在 class 的顶部)。我一直认为
只有在 class 之外(如 #..# 所示)我们才能访问 x = property(get_x, set_x)
我错了吗?你能明白我的意思吗?
已解决:
经过反复测试,我惊奇地发现,当我们执行inst = HideX(20)
时,代码x = property(get_x, set_x)
将首先被调用,而不是'init(self,x)'。完全出乎我的意料!!!(在java中,当我们创建一个实例,我认为 class 的 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
(2)书错了吗??当我删除 @属性 并添加代码 'x = property(**x())' 时,它起作用了!!!
你能帮我解释一下原因吗?非常感谢
对于你的第一个问题,答案很简单,x是class的一个属性(不是class的object/instance),当class 被定义(不是在创建它的对象时)。
一个例子来说明这一点 -
>>> class CA:
... y = print("Hello")
... def __init__(self):
... print("Blah")
...
Hello
>>> c = CA()
Blah
正如您所见,y
的值是在定义 class 时计算的,它与 class 中的所有函数相同,它们在 class 已定义,但仅在调用函数时才对其求值。
此外,使用 @属性 与 property(**x())
不同,当您使用后者时,**x()
解析为 -
{'fget': <function HideXX.x.<locals>.fget at 0x00943B28>, 'fset': <function HideXX.x.<locals>.fset at 0x00943CD8>}
然后这些位置参数用于为 属性 x
设置 getter
和 setter
,而 @property
注释用于为 属性 x.