Python:回调问题

2024-10-02 10:34:31 发布

您现在位置:Python中文网/ 问答频道 /正文

所以我在做一个游戏,所有的对象都来自一个GameObject类,看起来像这样

class GameObject(pygame.sprite.DirtySprite):
    actions = dict()

    def __init__(self):
        pygame.sprite.DirtySprite.__init__(self)
        self.rect  = None
        self.state = None

    def update(self):
        if callable(self.__class__.actions[self.state]):
        #If this key has a function for its element...
            self.__class__.actions[self.state](self)

现在,我遇到了另一个继承问题。观察下面的类,以及从中派生出来的两个类

^{pr2}$

除了None之外,Bullet.actions(一个静态成员)的每个元素都是Bullet中的一个函数。{< CD3}}不是自己创建的;如果是C++,它就是抽象类。因此,Bullet的子类在Bullet.actions的每一帧中搜索,根据它们的状态(它们是否在移动,是否刚刚被击中等等)来决定下一步要做什么。但是,由于Bullet.actions的元素是Bulletown方法,所以它的子类执行这些方法,而不是它们自己的扩展版本(调用父方法)。我不想因为内存使用的原因而重复这段回调语句。所以,我要问这个;如何让一个子类的实例在它的父字典中查找满是回调方法,如果存在,执行它们自己的版本,如果不存在,则执行其父类的版本?


Tags: 方法self版本noneactionsinitdef子类
3条回答

为什么不使用python内置机制进行继承呢?在

实例函数actions对于派生类B是相同的。当被调用时,它得到实例self,然后就像在实例本身上调用函数一样:Python的继承机制调用B的方法,如果它在那里或者回退到A的实现。在

EDIT:l4mpi建议指出,这将每次创建映射,因此我将action_映射更改为一个属性。在

class A():
    def actions(self, action):
        if not hasattr(self, "actions_map"):
            self.actions_map = {
                   "IDLE"   : self.idle,
                   "FIRED"  : self.fired,
                   "MOVING" : self.move,
                   "RESET"  : self.reset,
                  }
        return self.actions_map[action]

    def idle(self):
        print "A idle"
        pass

    def fired(self):
        print "A fired"

    def move(self):
        print "A move"

    def reset(self):
        print "A reset"

class B(A):       
    def fired(self):
        print "B fired"


a = A()
b = B()

a.actions("FIRED")()
b.actions("FIRED")()
b.actions("MOVING")()

>> A fired
>> B fired
>> A move

一种可能的解决方案是存储函数名而不是直接引用,并使用^{}检索正确的引用:

actions = {
           STATES.IDLE   : None          ,
           STATES.FIRED  : 'start_moving',
           STATES.MOVING : 'move'        ,
           STATES.RESET  : 'reset'       ,
          }

[...]

def update(self):
    method_name = self.__class__.actions[self.state]
    if method_name and callable(getattr(self, method_name)):
        getattr(self, method_name)(self)

对于加速,可以在初始化对象时预先计算此表:

^{pr2}$

请注意,由于__init__中的代码使用^{},因此可以将其放在Bullet.__init__中,并仅由其他类扩展。正如您已经调用了超级构造函数一样,不需要更改扩展类,甚至不需要对它们进行注释。在

扩展BoppreH的答案,您可以通过在类创建时用正确的方法填充activity dict来消除getattr查找,方法如下:

def generateActions(cls):
    cls.actions = {}
    for a, f in cls.genactions.items():
        cls.actions[a] = getattr(cls, f) if f else lambda *_: None
    return cls

注意,actions是用一个不做任何操作的lambda填充的,如果一个操作的给定值是None,这意味着您可以去掉update中的if callable(...)语句。在

现在只需将decorator添加到类中:

^{pr2}$

相关问题 更多 >

    热门问题