python - 关于 python 类 __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!'
        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 位于类的主体中(它位于类的顶部)。我一直以为 只有在类的外部(如 #..# 所示)我们才能访问 x = property(get_x, set_x) ,我错了吗?你能明白我的意思吗?

已解决: 经过反复测试,我惊奇地发现,当我们执行inst = HideX(20)时,代码x = property(get_x, set_x) 首先会被调用,而不是'init(self,x)'。完全出乎我的意料!!!(在java中,当我们创建一个实例时,我认为类将首先被​​调用,也许我错了)

(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)这本书有错吗?当我删除 @property 并添加代码 'x = property(**x())' 时它起作用了!!!

你能帮我解释一下原因吗?非常感谢

最佳答案

对于你的第一个问题,答案很简单,x是类的一个属性(而不是类的对象/实例),它将在类定义时(而不是创建其对象时)进行评估。

展示这一点的示例 -

>>> class CA:
...     y = print("Hello")
...     def __init__(self):
...             print("Blah")
...
Hello
>>> c = CA()
Blah

正如你所看到的,y的值是在类定义时计算的,它与类中的所有函数相同,它们在类定义时定义,但仅对它们求值当函数被调用时。

此外,使用 @property 与 property(**x()) 不同,当您执行后者时,**x() 解析为 -

{'fget': <function HideXX.x.<locals>.fget at 0x00943B28>, 'fset': <function HideXX.x.<locals>.fset at 0x00943CD8>}

然后这些位置参数用于设置属性 xgettersetter ,而 @property 注解用于定义属性 x 的 getter。

关于python - 关于 python 类 __init__ 和装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31129887/

相关文章:

python - sklearn (scikit-learn) 逻辑回归包——为分类设置训练系数。

grails - Grails MissingPropertyException

arrays - 如何将自定义属性添加到PowerShell数组?

asp.net-mvc-3 - DropDownListFor 和导航属性

python - odoo 12 中many2many 字段的更改行为

Python:将 JSON 添加到现有 JSON

c# - 遵循 O/C 原则在类层次结构的中间添加一个方法

python - python自动设置getter、setter和deleter

python - 在另一个装饰器之前使用 PyQt 4's ' pyqtSlot' 装饰器的奇怪行为

python - 如何使用 ElementTree 在父元素的文本之间插入 XML 元素