Целта на този въпрос е да се определи дали мога или не да обвия настройката на атрибут на обект, без просто да напиша сетер и след това да обвия сетера.
Опитвам се да внедря модел на наблюдател и не искам да пиша повече код, отколкото трябва (така че, разбира се, ще напиша голям дълъг въпрос за StackOverflow, хаха - смятам, че дългосрочната печалба си заслужава).
Започнах да експериментирам, опитвайки се да обвия obj.__setattr__
с функция, но тя не направи това, което очаквах, така че сега се чудя дали мога дори да обвия присвояването или промяната на атрибут на обект, ако не напиша просто сетер.
Ето какво опитах:
class A(object):
pass
def wrapper(obj, func):
def inner(*args, **kwargs):
print "called it"
return func(*args, **kwargs)
return inner
Stick = A()
Stick.__setattr__ = wrapper(Stick, Stick.__setattr__)
Stick.x = 14 #does not print "called it"
Ако просто напиша сетер, това ще направи лесно закачане, нещо като:
class A(object):
def __init__(self, x):
self.x = x
def set_x(self, new_x):
self.x = x
Но бих искал да мога да внедря модела Observer по такъв начин, че когато obj.x
се промени по някаква причина, слушателят се актуализира. Ако obj.x
е int
например, бих могъл или да го настроя направо, или да използвам obj.x += some_int
, за да го настроя, и затова се чудя дали има начин да обвия всяка/всички настройки на obj.x
, без например да пиша obj.set_x()
, obj.add_to_x()
, obj.subtract_from_x()
, obj.times_x()
и т.н.
РЕДАКТИРАНЕ: Благодаря, че ме насочихте към свойствата, но не виждам как може да ми помогне да обвия това по начина, който прилагам досега.
Например, ако имам обект като такъв:
class Foo(object):
def __init__(self, ex):
self._x = ex
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
...това е добре и виждам, че мога да променя функцията @x.setter
wraps директно, но се надявах да създам нещо, което мога да използвам по следния (въображаем псевдокод) начин:
A.x.setter = observing_function(A, A.x.setter)
... така че когато A.x
се промени, observing_function
се извиква и прави това, което ще прави.
Ако изобщо дава информация за отговора -- работя върху „табло с резултати“, за да покажа резултата и живота на централен герой във видео игра. Вместо постоянно да проверявам по време на всеки цикъл или настройка отново и отново (което правя сега, което изглежда прекомерно), аз просто искам действително да се задейства, когато резултатът/животът на героя се промени, а обвивката изглеждаше най-добрият начин да се направи това .
Надявах се да избегна това:
def add_to_score(self, pts):
self.score += pts
scoreboard_object.text = self.score
...защото това за мен е ужасно, въпреки че ще работи. Също така изглежда като много код само за установяване на модел на наблюдател за две променливи: P
Но това е причината, поради която бих предпочел да обвия сетера след факта. Имам два различни обекта, които не е задължително да имат твърдо кодирани данни един за друг; просто обект на играч с атрибут self.score
и обект на табло с атрибут self.text
и въпреки че писането на „лепилото“ между тях, разбира се, е необходимо, надявах се писането на методи за set_score
и set_text
да не е от решаващо значение само за прилагане на Модел на наблюдател.
Ако в крайна сметка не мога да пропусна писането на сетер (или сетери), тогава предполагам, че ще продължа и ще го направя по този начин; Просто се надявах да го избегна.
И макар че сега това е много конкретен пример, аз също питам в общ смисъл, защото изглежда наистина удобно да можете просто да наблюдавате атрибут за промени, вместо да кодирате около всеки атрибут, за да сте готови за може би гледане на някои промени на друг обект. :/