В чем разница между set и setattr в Python и когда следует использовать?

как говорится в названии.

исходя из Java im используется для:

private int A;

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

public int getA() {
    return this.A
}

как это сделать (если мне нужно) в Python. И если один из __setattr__ или __set__ используется для этого, для чего используется другой?

изменить: Я чувствую, что должен прояснить. Я знаю, что в Python один doe не создает сеттеров и геттеров, прежде чем они понадобятся.

допустим, я хочу сделать что-то вроде этого:

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

что такое "подходящие для Python" способ осуществления это?

4 ответов


в 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

в этом примере было бы лучше просто сделать (как указал Эдвард):

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

поскольку наши методы геттера / сеттера на самом деле ничего не делают ... Однако свойства становятся очень полезными, когда сеттер / геттер фактически делает что-то большее, чем просто назначает / возвращает атрибут значение.

он также может быть реализован с помощью __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 подчеркивания, он вызовет искажение имен, что затрудняет доступ за пределами класса. Это используется для предотвращения столкновений пространств имен в наследовании (и те переменные, как правило,также не следует возиться).


Если геттер / сеттер действительно так тривиальны, то вы даже не должны беспокоиться о них: просто используйте переменную экземпляра. Если вам нужен геттер / сеттер, который делает что-то интересное, вы должны переключиться на свойство, как описано mgilson. Обратите внимание, что вы можете перейти от переменной экземпляра к свойству без использования кода, замечающего разницу. То есть, начните с:

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

и только изменение на основе свойств аксессоров mgilson описано, если / когда оказывается, что вам нужно что-то интересное, когда вы получаете/устанавливаете атрибут.


__set__() используется в дескрипторах, когда дескриптор присваивается. __setattr__() используется при привязке к атрибуту объекта. Если вы не создаете дескриптор, вы не будете использовать __set__().


Предположим, у вас есть class Master С атрибутом x что это class Slave и вы хотите, чтобы какой-то код выполнялся, когда вы назначаете что-то x а в some_master.x = foo. Где будет расположен этот код? Это может быть в классе Master в этом случае вы используете __setattr__. Он также может быть в классе Slave, так что он имеет контроль над тем, что назначается. В этом случае вы делаете Slave a дескриптор и использовать __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

чтобы ответить на вопрос, который из них более питонический, я бы не сказал ни того, ни другого. Если вам нужно на самом деле do что-то, сделайте это функцией. Явное > неявное.

 def update_param(a):
     update_stuff(a)
     and_calculate_some_thing(a)
     self.a = a