14

正如标题所说。

来自 Java 我曾经:

private int A;

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

public int getA() {
    return this.A
}

我如何在 Python 中做到这一点(如果需要)。如果其中一个__setattr__or__set__用于此目的,那么另一个用于什么?

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

可以说我想做这样的事情:

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

实现这个的“pythonic”方式是什么?

4

4 回答 4

19

在 python 中,应该使用 a 来实现这样的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

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

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__以前的帖子已经很好地讨论了这一点。

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

于 2012-05-22T17:49:35.427 回答
8

__set__()当描述符被分配给时在描述符中使用。__setattr__()在绑定到对象的属性时使用。除非您正在创建描述符,否则您不会使用__set__().

于 2012-05-22T17:50:08.253 回答
8

如果 getter/setter 真的像那样微不足道,那么您甚至不应该打扰它们:只需使用实例变量即可。如果您确实需要做一些有趣的事情的 getter/setter,那么您应该切换到一个属性,如 mgilson 所述。请注意,您可以从实例变量更改为属性,而无需任何使用您的代码注意到差异的东西。即,开始:

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

如果/当事实证明您在获取/设置属性时需要发生一些有趣的事情时,只更改 mgilson 描述的基于属性的访问器。

于 2012-05-22T17:52:06.003 回答
5

假设您有class Master一个属性xclass Slave并且您希望在将某些内容分配给xas时执行一些代码some_master.x = foo。此代码将位于何处?它可以在类Master中,在这种情况下您使用__setattr__. 它也可以在 classSlave中,以便它可以控制分配的内容。在这种情况下,您创建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

与此相比:

>>> 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

要回答哪个更pythonic的问题,我不会说。如果您需要实际做某事,请将其设为函数。显式 > 隐式。

 def update_param(a):
     update_stuff(a)
     and_calculate_some_thing(a)
     self.a = a
于 2012-05-22T18:16:42.197 回答