В чем разница между 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