1

尽管我可能对该property()函数的作用感到非常困惑,但我正在尝试使用它来创建一个只读属性。理想情况下,我希望能够直接引用该属性,但不允许分配给它。在实验时,我得到了这个非常奇怪的行为:

>>> class Boo(object):
...     def __init__(self, x):
...             self.__x = x
...     def getx(self):
...             return self.__x
...     x = property(getx)
... 
>>> b = Boo(1)
>>> b.__x = 2
>>> b.getx()
1
>>> b.__x
2

我想补充一点,当我使用xand_x作为属性名称时,重新分配属性会导致 getter 返回更改后的值,即b.getx()and b.x/b._x都给了我2

我意识到我正在使用x作为属性名称,但是当我尝试以下操作时,我得到了AttributeError一个__init__()

>>> class Boo(object):
...     def __init__(self, x):
...             self.__x = x
...     def getx(self):
...             return self.__x
...     __x = property(getx)
... 
>>> b = Boo(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __init__
AttributeError: can't set attribute
4

5 回答 5

4

这里的问题与 无关property,而是与双下划线属性有关,这些属性受制于所谓的"Private name mangling"

>>> b = Boo(1)
>>> '__x' in dir(b)
False
>>> '_Boo__x' in dir(b)
True

所以,当你这样做时:

>>> b.__x = 2

您没有更改getx函数正在查看的属性的值,而是创建了一个属性。

如果您只是为不以两个下划线开头的属性使用名称,例如,_x一切都会按您的预期工作。

作为一般规则,“advisory private”使用单下划线——例如,“这个对象的用户可能不应该关心这个值”,只有当你真正需要修改时才使用双下划线(因为复杂的继承问题很少出现)。

如果你想要“真正的私有”,比如 C++ 或 Java,该怎么办?你不能拥有它。如果您足够好地隐藏或保护属性,那么有人只会对getx方法或x属性进行修补。因此,Python 没有提供隐藏属性的方法。

于 2013-07-04T00:17:10.693 回答
1

您的问题是使用双下划线属性名称会破坏 name。因此,当您在类定义内部处理时,__x在类外部它实际上看起来像_Boo__x. 那是,

_ +(类名)+(双下划线属性名)

展示,

>>> b = Boo(1)
>>> b.__x = 2
>>> b.getx()
1
>>> b.x            # NOTE: same as calling getx
1
>>> b.__x          # why didn't x return 2 if we changed it?
2
>>> b._Boo__x      # because it's actually saved in this attribute
1
>>> b._Boo__x = 3  # setting it here then works
>>> b.x
3
>>> b.getx()
3
于 2013-07-04T00:19:20.300 回答
1

真的只是想评论(而不是回答)您的问题。我想你会发现以下信息:

>>> b = Boo(1)
>>> print b.__dict__
{'_Boo__X': 1}
>>> b.__x = 2
>>> print b.__dict__
{'__x': 2, '_Boo__X': 1}

可能会提供有关行为的提示(我理解得不够好,无法解释)。

于 2013-07-04T00:53:33.020 回答
0

这是因为您没有定义 setx 函数。

#!/usr/bin/python

class Boo(object):

        def __init__(self, initialize_x):
                self.x = initialize_x

        def getx(self):
                print
                print '\t\tgetx: returning the value of x', self.__x
                print
                return self.__x

        def setx(self, new_x):
                print
                print '\t\tsetx: setting x to new value',new_x
                print
                self.__x = new_x

        x = property(getx, setx)

print '1  ########'
print
print '\tinitializing Boo object with a default x of 20'
print
o = Boo(20)
print '\treading the value of x through property o.x'
t = o.x
print

print '2  ########'
print
print '\tsetting x\'s value through the property o.x'
o.x = 100
print


print '3  ########'
print
print '\treading the value of x through the property o.x'
t = o.x

运行时产生:

1  ########

    initializing Boo object with a default x of 20


        setx: setting x to new value 20

    reading the value of x through property o.x

        getx: returning the value of x 20


2  ########

    setting x's value through the property o.x

        setx: setting x to new value 100


3  ########

    reading the value of x through the property o.x

        getx: returning the value of x 100
于 2013-07-04T00:52:58.367 回答
-1

property用作装饰器。方便计算数据。

可能是为了让只读属性更好地使用魔法函数__set____get__

于 2013-07-04T00:17:03.523 回答