1

我试图了解 @property 装饰器的工作原理。

这里我使用方法 y 作为字段 x 的属性,

在attribute-self.x有了属性之后,是不是意味着我们不能显式地设置值了。。

我认为最后一条语句-> cx = 2 一旦你在变量上设置了属性方法就不起作用了?

class C(object):
    def __init__(self):
        self.x = 0
        self.list = [1,2,3,4,10]
    @property
    def y(self):
        print 'getting'
        self.x = sum(self.list) 
        return self.x

    @y.setter
    def y(self, value):
        print 'setting'
        self.x = value

if __name__ == '__main__':
    c = C()
    print 'Value of c.y=',c.y
    print '-'*80
    c.y = 50
    print '-'*80
    print c.y
    print '-'*80
    if c.y >5:
        print 'Hi'
4

5 回答 5

3

您始终可以显式设置 x。

class Foo(object):
    def __init__(self):
        self.x = 1
        self.lst = [1,2,3]

    @property
    def y(self):
        self.x = sum(self.lst)
        return self.x

    @y.setter
    def y(self,value):
        self.x = value


f = Foo()
print f.y #6
print f.x #6
f.x = 3
print f.x #3
print f.y #6
print f.x #6

问题是在这个例子中,调用 getter ( y) 也设置了属性的值,所以如果你正在做所有的更改 via x,你将永远不会看到更改,因为查看的行为会更改值.xyyx

您可能会尝试绕过该限制的一种方法是:

class Foo(object):
    def __init__(self):
        self.x = None
        self.lst = [1,2,3]

    @property
    def y(self):
        return sum(self.lst) if self.x is None else self.x

    @y.setter
    def y(self,value):
        self.x = value

现在,如果您为x(or y) 显式设置一个值,该值将一直存在,直到您将其设置回,如果您真的想要None,您甚至可以在另一个装饰有的函数中执行此操作。@y.deleter

于 2013-05-16T20:08:50.337 回答
2

私有实例变量的支持有限通过名称修饰在 Python 中

为了避免暴露x,你需要两个前导下划线,即__x

于 2013-05-16T20:13:34.223 回答
0

您不能禁止使用属性装饰器直接更改属性,但我认为您可以这样做

class A(object):
    def __init__(self):
        self.x = 0
    @property
    def x(self):
        return self.__dict__['x']
    @x.setter
    def x(self, value):
        self.__dict__['x']=value

这将允许您实现您所描述的行为

于 2013-05-16T20:15:08.063 回答
0

Python 不提供任何阻止调用者访问变量的功能。换句话说,Python 中没有“私有”。按照惯例,带有下划线前缀的变量或方法不适合外部使用。例如,

class C(object):
    def __init__(self):
        self._x = 0
        self.list = [1,2,3,4,10]
.
.
.

如果我真的想访问,我仍然可以访问_x,没有什么能阻止我设置它。

>>> c = C()
>>> c._x
10
>>> c._x = 20
>>> c._x
20

但是,按照惯例,下划线告诉我我正在做一些危险且不明智的事情。这取决于我,程序员,来确定我这样做是否破坏了任何东西。

这是在创建 Python 时做出的有意识的设计决定。这个想法是,使用您的课程的人应对他们所做的事情负责;如果他们滥用它并且它坏了,那是他们的错。你用下划线警告他们。我认为聪明的程序员可以绕过您尝试将它们锁定的想法可能在决定中发挥了作用(例如反射库或直接与编译的字节码交互),但不要让我这么认为。

稍微相关一点,如果变量(包括其他导入的模块、函数等)是模块的成员,则下划线实际上会做一些事情。以下划线开头的成员不会被 . 导入import *。例如,

一个.py

_a = 10
b = 50

命令提示符:

>>> from a import *
>>> b
50
>>> _a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name '_a' is not defined

在您的特定示例中,x它的设置器相对没用,因为您在调用 getter 时都会覆盖它的值。

于 2013-05-17T01:51:48.857 回答
-4

类 Foo(object): def init (self): self.x = None self.lst = [1,2,3]

@property
def y(self):
    return sum(self.lst) if self.x is None else self.x

@y.setter
def y(self,value):
    self.x = value
于 2013-05-16T20:19:02.397 回答