gpt4 book ai didi

Python - 我可以在不编写 getter/setter 的情况下包装属性赋值吗

转载 作者:太空宇宙 更新时间:2023-11-03 11:52:23 25 4
gpt4 key购买 nike

这个问题的目的是确定我是否可以包装对象的属性设置,只需编写一个 setter 然后包装 setter。

我正在尝试实现一个观察者模式,我不想编写比我需要的更多的代码(所以我当然会写一个很长的 StackOverflow 问题,哈 - 我认为长期返回是值得的它)。

我开始尝试用一个函数包装 obj.__setattr__ 但它没有达到我预期的效果,所以现在我想知道我是否可以包装赋值或更改一个对象的属性,如果我不只是写一个 setter。

这是我尝试过的:

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"

如果我只写一个 setter,它会成为一个简单的钩子(Hook),比如:

class A(object):
def __init__(self, x):
self.x = x

def set_x(self, new_x):
self.x = x

但我希望能够以这样一种方式实现观察者模式,即每当 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

但是就是为什么我更愿意在事后包装 setter。我有两个不同的对象,它们不一定需要彼此硬编码数据;只是一个带有 self.score 属性的玩家对象和一个带有 self.text 属性的记分牌对象,虽然在它们之间编写“胶水”当然是必要的,我我希望为 set_scoreset_text 编写方法不会仅仅对实现观察者模式至关重要。

如果最终我不能跳过编写一个(或多个)setter,那么我想我会继续这样做;我只是希望避免它。

虽然现在这是一个非常具体的例子,但我也在一般意义上问,因为能够只观察一个属性的变化而不是围绕每个属性编码以准备好看起来真的很方便也许在观察其他物体的一些变化。 :/

最佳答案

特殊方法、描述符和所有其他处理属性访问的方法只适用于类。您不能在对象上覆盖它们。

使用事件(或发布/订阅或我们现在所说的任何东西)系统。让角色负责发出事件,而不是具体记住谁需要它们。

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 的情况下包装属性赋值吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22738545/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com