
我正在尝试实现一个Observer模式,我不想编写超出我需要的代码(所以当然我会写一个很长的StackOverflow问题,哈哈 – 我认为长期收益是值得的).
我开始尝试用一个函数包装obj .__ setattr__,但它没有按照我的预期做到,所以现在我想知道如果我不写一个,我是否可以包装赋值或改变一个对象的属性二传手.
这是我试过的:
class A(object): passdef wrapper(obj,func): def inner(*args,**kwargs): print "called it" return func(*args,**kwargs) return innerStick = A()Stick.__setattr__ = wrapper(Stick,Stick.__setattr__)Stick.x = 14 #does not print "called it"
如果我只是写一个setter它会使一个简单的钩子,如:
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包装,但我希望创建一些我可以使用以下(虚构的伪代码)方式的东西:
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的方法不是至关重要的只是为了实现Observer模式.
如果最终我不能跳过写一个二传手(或者二传手),那么我想我会继续这样做;我只是希望避免它.
虽然现在这是一个非常具体的例子,但我也在一般意义上提出要求,因为能够仅仅观察变化的属性而不是围绕每个属性进行编码以准备观看某些属性似乎非常方便其他一些对象的变化. :/
解决方法 使用属性访问的特殊方法,描述符和所有其他方法仅适用于类.您无法在对象上覆盖它们.使用事件(或pub / sub或我们现在称之为的任何系统)系统.让角色负责发出事件,但不是为了记住具体想要他们的人.
class scoreChanged(Event): ...class Character(ListenerMixin): @property def score(self): return self._score @score.setter def score(self,new): old = self._score self._score = new self.fire_event(scoreChanged(self,old,new))protag = Character()scoreboard = scoreboard()scoreboard.Listen_event(protag,scoreChanged,scoreboard.on_score_change)protag.score += 10
对象必然会在某处纠缠,但它变成了一个实现细节,而不是代码的主要部分.特别是,记分板不必是全局的,即使记分板不存在,角色仍然可以正常工作.
在this question上有一些实现和现有库的例子,但是如果你正在编写一个游戏,你可能已经在使用一个内置的库.我知道pyglet会这样做.
总结以上是内存溢出为你收集整理的Python – 我可以在不编写getter / setter的情况下包装属性赋值全部内容,希望文章能够帮你解决Python – 我可以在不编写getter / setter的情况下包装属性赋值所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)