关于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!'

当我学习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!'
        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
设置为某个任意数,然后我们才能为其创建实例。此外,如果您认为答案已经回答了您的问题,那么当然,请记住接受它们(通过点击答案左侧的勾号)。这将有助于社区。