Python:没有类型对象不可调用

时间:2015-04-26 10:28:17

标签: python pygame

我在游戏中做游戏,而我正在尝试做的是让一个实体成为另一个实体。 当我调用目标函数时,我得到" TypeError:NoneType对象不可调用"在研究这个错误之后我理解的是,当你尝试使用没有任何函数的函数的返回值时,它会发生。 但是,我的功能不应该返回一些东西,我不会使用返回值,所以我有点想法。 我希望有人可以帮助我,这是我的代码: 目标函数

def target(self,x,y):
    target = self.world.getPointEntity(x,y)  
    if target != None and target.get_itarget():
        self.set_target(target)

调用目标函数

self.player.target(x,y)

如果您有任何疑问,请随时提出。

编辑:getPointEntity函数代码:

    def getPointEntity(self, x, y, searchRange=24):
        for entity in self.entities.itervalues():
            if entity != None:
                distance = entity.get_distance(x, y)
                if distance < searchRange:
                    return entity
        return None   

对于get_itarget函数,它只返回True或False,具体取决于作为合法目标的相应实体。 回溯指向与self.player.target()一致的行 完全追溯:

__Main2.py", line 971, in <module>
Game(1920,1080)    
__Main2.py", line 795, in __init__
self.run()
__Main2.py", line 910, in run
self.player.target(x,y)
TypeError: 'NoneType' object is not callable

编辑:方法目标属于玩家类的超类。

class Player(LivingEntity):
    def __init__(self, name, world, image, x, y, speedModifier, sizeradius, inv_image, filler, shadow, scx, scy, animseq, animn):
        LivingEntity.__init__(self, name, world, image, x, y, speedModifier, sizeradius, animseq, animn)
        self.inventory = None
        self.scx = scx
        self.scy = scy
        self.addInventory(inv_image, filler, shadow)

class LivingEntity(GameEntity):
    def __init__(self, name, world, images, x, y, speedModifier, sizeradius, animseq, animn, xshift=48, yshift=48):
        GameEntity.__init__(self, name, world, images, x, y, speedModifier, sizeradius, animseq, animn, xshift, yshift)
        self.target = None

    def set_target(self, target):
        self.target = target

    def target(self,x,y):
        target = self.world.getPointEntity(x,y)  
        if target != None and target.get_itarget():
            self.set_target(target)

我通过检查目标实体之外的目标实体来解决问题。我无法真正看到差异,但似乎有效。

2 个答案:

答案 0 :(得分:1)

LivingEntity类中,您有一个名为target的方法,LivingEntity类中用于引用LivingEntity.target方法的代码所使用的语法是{{1 }}。但在self.target方法中,您使用LivingEntity.set_target分配覆盖 self.target

完成该分配后,下次调用self.target = target方法时,Python会尝试使用target设置set_target来调用该调用,而不是调用self.target您希望它使用的方法。

因此您收到了错误消息,因为您告诉LivingEntity.targetset_target设置为self.target

答案 1 :(得分:1)

正如PM 2Ring指出的那样,set_target会覆盖LivingEntity.target字段。但问题在此之前就开始了:__init__方法在任何人有机会调用之前销毁target方法。

这是一个关于正在发生的事情的简要示例:

#!/usr/bin/env python3


class InitDestroysMethod(object):

    def __init__(self):
        self.target = None
        return

    def target(self):
        return "This is the InitDestroysMethod.target method."


def main():
    print("Class with __init__ and target method:")
    print("InitDestroysMethod.target:  ", end="")
    print(InitDestroysMethod.target)
    print("InitDestroysMethod.target():  ", end="")
    print(InitDestroysMethod.target(None))  # Bogus "self" argument.
    print()
    print("Instance with __init__ and target method:")
    print("InitDestroysMethod().target:  ", end="")
    print(InitDestroysMethod().target)
    print("InitDestroysMethod().target():  ", end="")
    print(InitDestroysMethod().target())
    return


if "__main__" == __name__:
    main()

以下是该计划的输出:

Class with __init__ and target method:
InitDestroysMethod.target:  <function target at 0x1266490>
InitDestroysMethod.target():  This is the InitDestroysMethod.target method.

Instance with __init__ and target method:
InitDestroysMethod().target:  None
InitDestroysMethod().target():  Traceback (most recent call last):
  File "./init_vs_method.py", line 30, in <module>
    main()
  File "./init_vs_method.py", line 25, in main
    print(InitDestroysMethod().target())
TypeError: 'NoneType' object is not callable

正如您所看到的,未实例化的类 具有target方法(技术上只是一个函数 - 当一个对象被实例化时,将有绑定方法,绑定到对象的self参数。只要为self参数提供参数,就可以像调用任何其他函数一样调用它。 (这个技巧只适用于这种情况,因为target实际上并没有使用self参数,但它让我证明有一个名为target的可调用函数。)

但是该类的实例已经受到__init__的影响。在这种情况下,__init__会将实例字典中target的值设置为Nonetarget的旧值是一个绑定方法,但是当您获得对新创建和初始化对象的引用时,该旧值早已被丢弃。

当您使用some_instance.target之类的字段时,搜索名为“target”的实体将在实例字典中开始。那本词典确实有一个名为“目标”的键。 具有一个名为“target”的函数没有区别---已经找到了名称,并且使用了它的值(None)。

然后,您尝试将None值称为函数或方法,并获得TypeError