【问题标题】:Strange Python OOP function call error奇怪的 Python OOP 函数调用错误
【发布时间】:2016-04-24 07:33:57
【问题描述】:

我在下面创建了一些面向对象的 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 都抛出错误。

【问题讨论】:

    标签: python oop object instance


    【解决方案1】:

    当您执行ben.check_money = 100 时,您将在ben 对象上以前调用的函数check_money 替换为整数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,只是为了将其返回给您,因此您可以取回整数值。

    【讨论】:

      【解决方案2】:

      当您这样做ben.check_money=100 时,您将一个整数100 分配给了 ben.check_money 属性。而这个属性隐藏了方法 ben.check_money()。现在本只有属性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() 
      

      【讨论】:

        【解决方案3】:

        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,或替换现有的,如 show,如所示这个例子。在您的代码中,您正在做的是将原来的 check_money 方法替换为整数,而 python 什么也没说,因为它本质上允许这样做,而不像更静态的 lenguajes

        【讨论】:

          猜你喜欢
          • 2015-10-23
          • 1970-01-01
          • 1970-01-01
          • 2017-11-11
          • 2016-02-02
          • 1970-01-01
          • 2019-03-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多