奇怪的Python OOP函数调用错误

时间:2016-01-19 00:13:40

标签: python oop object instance

我在下面创建了一些面向对象的Python代码,其中创建了一个用户实例(称为Ben)。函数正常工作但是,我发现当最后一行更改为ben.check_money = 100时,不会抛出任何错误。我知道这不是正确的语法。但是,添加正确的函数回调会引发列出的错误:TypeError: 'int' object is not callable

原始代码:

class User:

    def __init__(self):
        self.money = 200
        self.score = 0
        print('Created ')

    def increase_money(self, amount):
        self.money += amount

    def decrease_money(self, amount):
        self.money -= amount

    def check_money(self):
        print(self.money)


ben = User()

ben.check_money() # No error is thrown here

修改后的代码1;

class User:

    def __init__(self):
        self.money = 200
        self.score = 0
        print('Created ')

    def increase_money(self, amount):
        self.money += amount

    def decrease_money(self, amount):
        self.money -= amount

    def check_money(self):
        print(self.money)


**ben = User()
ben.check_money = 100 # No error thrown here
ben.check_money() # Error is thrown here**

修改后的代码2;

class User:

    def __init__(self):
        self.money = 200
        self.score = 0
        print('Created ')

    def increase_money(self, amount):
        self.money += amount

    def decrease_money(self, amount):
        self.money -= amount

    def check_money(self):
        print(self.money)


**ben = User()
ben.check_money = 100 # No error thrown here
ben.check_money # No Error is thrown here**

我的问题是;为什么错误只发生在某些情况下,具体取决于您之前的调用方式?可以假设它应该为修改代码1和修改代码2抛出错误。

3 个答案:

答案 0 :(得分:4)

执行ben.check_money = 100时,使用整数check_money替换ben对象上曾被称为100的函数。将整数作为函数调用不起作用:

>>> 100()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable

在将ben.check_money()设置为100后运行时会出现类似的错误。

但是,如果您只是访问ben.check_money,那么您不会要求Python 运行 check_money,只需将其还给您,即可获得整数值。

答案 1 :(得分:3)

执行此操作ben.check_money=100时,您为ben.check_money属性分配了一个整数100。而且这个属性遮蔽了方法ben.check_money()。现在ben只有属性check_money。因此,如果您调用ben.check_money,则实际上正在调用属性,即int 100ben.check_money()正在调用方法,但该方法现在已被遮蔽。

执行此操作的正确方法可能是编写setter()方法:

class User:

    def __init__(self):
        self.money = 200
        self.score = 0
        print('Created ')

    def increase_money(self, amount):
        self.money += amount

    def decrease_money(self, amount):
        self.money -= amount

    def set_money(self,amount):
        self.money = amount

    def check_money(self):
        print(self.money)


**ben = User()
ben.set_money(100)
ben.check_money() 

答案 2 :(得分:2)

Python是动态语言,这意味着您可以随时添加,删除或替换任何您想要的任何对象,除非采取措施

例如

>>> class Fuu:
    def show(self):
        print("This is Esparta")


>>> y=Fuu()
>>> y.show()
This is Esparta
>>> y.show
<bound method Fuu.show of <__main__.Fuu object at 0x000000000357CC50>>
>>> y.show = 10
>>> y.show
10
>>> y.a
Traceback (most recent call last):
  File "<pyshell#51>", line 1, in <module>
    y.a
AttributeError: 'Fuu' object has no attribute 'a'
>>> y.a=42
>>> y.a
42
>>> def buu():
    print("42 is the ultimate answer")

>>> y.fun = buu
>>> y.fun()
42 is the ultimate answer
>>>     

在此示例中,类Fuu仅定义了1个属性/方法show,但您可以添加其他内容,例如afun,或替换现有的showcheck_money {1}}在示例中显示的任何时间。在您的代码中,您正在做的是替换原始;方法的整数,而python什么也没说,因为它本质上允许这种方式不同于更多静态的lenguajes