int'对象不可调用

3 投票
3 回答
53162 浏览
提问于 2025-04-15 21:57

我正在尝试定义一个简单的 Fraction 类。

但是我遇到了这个错误:

python fraction.py 
Traceback (most recent call last):
File "fraction.py", line 20, in <module>
   f.numerator(2)
TypeError: 'int' object is not callable

以下是代码:

class Fraction(object):
    def __init__( self,  n=0, d=0 ):
       self.numerator = n
       self.denominator = d
    def get_numerator(self):
        return self.numerator
    def get_denominator(self):
         return self.denominator

    def numerator(self, n):
         self.numerator = n
    def denominator( self, d ):
         self.denominator = d

    def prints( self ):
          print "%d/%d" %(self.numerator, self.denominator)

if __name__ == "__main__":
    f = Fraction()
    f.numerator(2)
    f.denominator(5)
    f.prints()

我原以为是因为我有 numerator(self)numerator(self, n) 这两个方法,但现在我知道 Python 不支持方法重载(也就是函数重载),所以我把它改名为 get_numerator,但这并不是问题所在。

那可能是什么原因呢?

3 个回答

7
  • 你在用 numerator 作为方法名和实例属性的名字。因为方法是存储在类里的,当你查找这个属性时,得到的是数字,而不是方法。(Python 会先在实例上查找属性,然后再查找类。)

    也就是说,当你写 f.numerator(2) 的时候,它查找 f.numerator,发现是 0,然后试图调用这个 0,这显然是行不通的。

  • 如果你有实际的需求,可以使用标准库中的 fractions 模块:http://docs.python.org/library/fractions.html

    • 这个模块在 Python 2.6 中新增。如果我需要表示分数,但使用的是早期版本的 Python,我可能会使用 sympyRational 类型。
  • 对于 denominator,更合适的默认值可能是 1。(这样 Fraction(5) 就表示五,而不是某种趋向于无穷大的未定义操作。)

  • 与其定义一个 prints 方法,不如定义 __str__ 方法,这样你就可以直接打印你的对象。

  • 你的方法只是用来获取和设置属性。在 Python 中,我们一般不使用 getter 和 setter——我们直接让用户设置属性。

    • 你可能是从 Java 背景过来的,在 Java 中有个基本规则是总是使用 getter 和 setter 方法,而不是让用户直接访问属性。这个规则的理由是,如果将来你需要做的不仅仅是获取和设置(比如需要处理数据),就需要修改 API。但在 Python 中,我们有属性,所以在这种情况下不需要修改 API,因此可以安全地避免使用 getter 和 setter 的繁琐代码。
  • 继承 numbers.Rational(Python 2.6 及以上)也不错,这样你的类可以自动完成一些数字应该具备的功能。你需要实现它所需的所有内容,但这样会省去很多工作。想了解更多,可以查看 http://docs.python.org/library/numbers.html


剧透警告:

class Fraction(object):
    """Don't forget the docstring....."""

    def __init__(self, numerator=0, denominator=1):
        self.numerator = numerator
        self.denominator = denominator

    def __str__(self):
        return "%d / %d" % (self.numerator, self.denominator)

    # I probably want to implement a lot of arithmetic and stuff!

if __name__ == "__main__":
    f = Fraction(2, 5)
    # If I wanted to change the numerator or denominator at this point, 
    # I'd just do `f.numerator = 4` or whatever.
    print f
8

你不能把名字 numerator 同时用来指代成员变量和方法。当你写 self.numerator = n 的时候,其实是把方法的引用给覆盖掉了。所以当你调用 f.numerator(2) 时,它试图在一个成员变量上调用方法,而这个成员变量是一个 int 类型的数字,Python 是不允许这样做的。这就像你说 x = 2; x(4) —— 这根本没有意义。

你应该把设置方法的名字改成 set_numeratorset_denominator,这样就不会有名字冲突了。

18

你把 numerator 既当作方法名(比如 def numerator(...)),又当作成员变量名(比如 self.numerator = n)来用了。建议把方法名改成 set_numeratorset_denominator,这样就能正常工作了。

顺便提一下,Python 2.6 里有一个内置的 分数类

撰写回答