Python中__set__和__setattr__之间的区别是什么?应该在何时使用?

时间:2012-05-22 17:44:19

标签: python attributes getter-setter

正如标题所说。

来自Java im以前:

private int A;

public void setA(int A) {
    this.A = A;
}

public int getA() {
    return this.A
}

如何在Python中执行此操作(如果需要)。 如果__setattr____set__中的一个用于此目的,那么另一个用于什么?

编辑: 我觉得我需要澄清一下。我知道在Python中,一个doe不会在需要之前创建setter和getter。

让我们说我想做这样的事情:

public void setA(int A) {
    update_stuff(A);
    and_calculate_some_thing(A);
    this.A = A;
}

实现此目的的“pythonic”方式是什么?

4 个答案:

答案 0 :(得分:14)

在python中,像这样的东西应该使用property来实现(然后只有当它们做了一些有用的事情时)。

class Foo(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        return self._x

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

在这个例子中,最好这样做(正如Edward所指出的那样):

class Foo(object):
     def __init__(self):
         self.x = None

因为我们的getter / setter方法实际上并没有做任何事情......但是,当setter / getter实际上做的不仅仅是分配/返回属性的值时,属性变得非常有用。

它也可以使用__setattr__ / __getattr__来实现(但它不应该以这种方式实现,因为如果你的类有超过1个属性,它会很快变得很麻烦。我也会猜测这样做会比使用属性慢:

class Foo(object):
    def __init__(self):
        self._x = None
    def __setattr__(self,attr,obj):
        if(attr == 'x'):
            object.__setattr__(self,'_x',obj)
        else:
            object.__setattr__(self,attr,obj)

     def __getattr__(self,attr):
         if(attr == 'x'):
             return object.__getattr__(self,'_x')
         else:
             return object.__getattr__(self,attr)

__setattr____getattr__实际做的事而言...... 当您执行以下操作时,__setattr__ / __getattr__就会被调用:

myclassinstance = MyClass()
myclassinstance.x = 'foo'  #translates to MyClass.__setattr__(myclassinstance,'x','foo')
bar = myclassinstance.x    #translates to bar=MyClass.__getattr__(myclassinstance,'x')

至于__get____set__previous posts已经很好地讨论了这个问题。

请注意,在python 中没有私有变量这样的东西。一般来说,在一个班级成员的前缀下加一个下划线,你不应该惹它(除非你知道你当然在做什么)。如果它以2个下划线为前缀,它将调用名称修改,这使得在类外部访问更加困难。这用于防止继承中的命名空间冲突(这些变量通常也不会被搞乱)。

答案 1 :(得分:8)

如果getter / setter真的那么简单,那么你甚至不应该为它们烦恼:只使用一个实例变量。如果你确实需要一个有趣的getter / setter,那么你应该切换到一个属性,就像mgilson所描述的那样。请注意,您可以从实例变量更改为属性,而无需使用代码注意差异的任何内容。即,从:

开始
class Foo(object):
    def __init__(self):
        self.x = None

只有改变基于属性的访问者mgilson描述了当你得到/设置属性时,你需要发生一些有趣的事情。

答案 2 :(得分:7)

指定描述符时,

__set__()用于描述符。绑定到对象的属性时使用__setattr__()。除非您正在创建描述符,否则不会使用__set__()

答案 3 :(得分:4)

假设您class Master的属性xclass Slave,并且您希望在向x分配内容时执行一些代码,如同{ {1}}。这段代码在哪里?它可以在班级some_master.x = foo中,在这种情况下,您使用Master。它也可以在类__setattr__中,以便它可以控制所分配的内容。在这种情况下,您将Slave设为descriptor并使用Slave

示例:

__set__

与此相比:

>>> class Master(object):
...     def __setattr__(self, name, val):
...         print "run code in Master: %s" % val
... 
>>> a = Master()
>>> a.x = 123
run code in Master: 123

要回答哪一个更pythonic,我不会说。如果您需要实际执行某事,请将其作为一项功能。明确的>隐式的。

>>> class Slave(object):
...     def __set__(self, obj, val):
...         print "run code in Slave: %s" % val
... 
>>> class Master2(object):
...     x = Slave()
... 
>>> b = Master2()
>>> b.x = 345
run code in Slave: 345