int'对象不可调用
我正在尝试定义一个简单的 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 个回答
你在用
numerator
作为方法名和实例属性的名字。因为方法是存储在类里的,当你查找这个属性时,得到的是数字,而不是方法。(Python 会先在实例上查找属性,然后再查找类。)也就是说,当你写
f.numerator(2)
的时候,它查找f.numerator
,发现是0
,然后试图调用这个0
,这显然是行不通的。如果你有实际的需求,可以使用标准库中的
fractions
模块:http://docs.python.org/library/fractions.html- 这个模块在 Python 2.6 中新增。如果我需要表示分数,但使用的是早期版本的 Python,我可能会使用 sympy 的
Rational
类型。
- 这个模块在 Python 2.6 中新增。如果我需要表示分数,但使用的是早期版本的 Python,我可能会使用 sympy 的
对于
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
你不能把名字 numerator
同时用来指代成员变量和方法。当你写 self.numerator = n
的时候,其实是把方法的引用给覆盖掉了。所以当你调用 f.numerator(2)
时,它试图在一个成员变量上调用方法,而这个成员变量是一个 int
类型的数字,Python 是不允许这样做的。这就像你说 x = 2; x(4)
—— 这根本没有意义。
你应该把设置方法的名字改成 set_numerator
和 set_denominator
,这样就不会有名字冲突了。
你把 numerator
既当作方法名(比如 def numerator(...)
),又当作成员变量名(比如 self.numerator = n
)来用了。建议把方法名改成 set_numerator
和 set_denominator
,这样就能正常工作了。
顺便提一下,Python 2.6 里有一个内置的 分数类。