2

Pythonとpygletを使用したゲームでは、イベントをそのメンバーに下方に伝播するグループがあります。

class Group(EventDispatcher):
    def __init__(self):
        self.members = []
    def add(self, member):
        self.members.append(member)
        self.push_handlers(member)
    def remove(self, member):
        self.members.remove(member)
        # and then what???
Group.register_event('on_event')

メンバーへdelのすべての参照を削除して削除した場合、グループ内のハンドラーはオブジェクトがガベージコレクションされるのを防ぎますか?ハンドラーは消えますか(weakref)?そうでない場合、どうすればハンドラーをクリーンアップできますか?

編集:何が起こるかを確認するためにテストセッションを実行しました:

>>> from pyglet.event import EventDispatcher
>>> class Group(EventDispatcher):
...  pass
... 
>>> Group.register_event_type('on_tick')
'on_tick'
>>> g = Group()
>>> class Members:
...  def on_tick(self):
...   print('tick')
... 
>>> m = Members()
>>> g.push_handlers(m)
>>> g.dispatch_event('on_tick')
tick
>>> del m
>>> g.dispatch_event('on_tick')
tick
>>> class B:
...  def on_tick(self):
...   print(self.x)
... 
>>> m = B()
>>> g.push_handlers(m)
>>> g.dispatch_event('on_tick')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.2/site-packages/pyglet/event.py", line 355, in dispatch_event
    if handler(*args):
  File "<stdin>", line 3, in on_tick
AttributeError: 'B' object has no attribute 'x'
>>> m.x = 3
>>> g.dispatch_event('on_tick')
3
tick
>>> del m
>>> g.dispatch_event('on_tick')
3
tick

したがって、EventDispatcherはまだハンドラーへの参照を保持していると思います。したがって、問題は、ハンドラーをどのようにクリーンアップするかということです。

4

1 に答える 1

1

EventDispatcher.remove_handlersは、push_handlersの反対です。したがって、remove_handlers(m)を呼び出してからdel mを呼び出すと、mをガベージコレクションできます。

于 2012-09-20T05:09:16.517 に答える