2010-04-23 57 views
3

我试图定义一个简单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但这不是问题。

它可能是什么?

+0

作为初学者,你应该学习,这在Python没有必要在这些简单的情况下getter和setter方法。只有分子和分母的属性就好,并且被接受。如果你真的想明确getter和setter *函数*,你应该使用下划线来保护你的属性。无论哪种方式,你的名字冲突问题不会发生。 – Debilski 2010-04-23 23:48:15

回答

18

您正在使用numerator作为方法名称(def numerator(...))和成员变量名称(self.numerator = n)。方法名称使用set_numeratorset_denominator,它将起作用。

顺便说一句,Python 2.6有一个内置的fraction class

+0

明白了!所以,如果我的属性是“分子”,我不能有任何其他的方法与这个名字,对吧? (无论是“setter”还是“getter”或其他)额外的问题,当我尝试使用名称“print”作为我的打印方法时,出现语法错误,所以我不得不将它命名为'prints',这是因为' print'是在object中定义的?或者因为它是全球性的或是某种东西 – OscarRyz 2010-04-23 22:41:10

+0

关于分数班感谢。我只是在学习,我在Python,Ruby,Go,Java,Objective-C中用这个类来做某种'语言展示'。 – OscarRyz 2010-04-23 22:51:19

+1

@Oscar Reyes:在Python 2.x中,print是一个关键字(用于'print'语句),所以你不能用它来命名你的方法或变量。在Python 3.x中,'print'不再是关键字。 – interjay 2010-04-23 23:02:01

8

您不能重载名称numerator以引用成员变量和方法。当你设置self.numerator = n时,你覆盖了对该方法的引用,所以当你调用f.numerator(2)时,它试图对成员变量进行方法调用,这是一个int,Python不允许你这么做。这就像是说x = 2; x(4) - 它没有任何意义。

您应该将setter方法重命名为set_numeratorset_denominator以消除此命名冲突。

7
  • 您正在使用numerator作为实例属性的方法名称和名称。由于方法存储在类中,所以当您查找该属性时,您将获取数字,而不是方法。 (Python将查找在实例属性看课前。)

    这是说,你在哪里说f.numerator(2)行,它看起来了f.numerator,并认为它是0,然后试图调用0 ,这显然不应该起作用。

  • 如果您有此代码的任何实际的目的,你可以使用STDLIB fractions模块:http://docs.python.org/library/fractions.html

    • 这在Python 2.6是新的。如果我需要表示分数,但使用较早版本的Python,我可能会使用sympyRational类型。
  • denominator更实用的默认值可能是1。 (这样Fraction(5)将有五个,而不是一些不确定的操作无穷大趋向。)

  • prints方法相反,它会比较典型的定义__str__,只是打印您的对象。

  • 您的方法只是获取并设置属性。在Python中,我们通常不使用getter和setter,我们只是让用户设置我们的属性。

    • 你来自Java背景,其中一个基本规则总是使用getter和setter方法,而不是让用户访问属性。这条规则的基本原理是,如果在未来某个日子,您需要做的不仅仅是获取和设置(您需要处理数据),还需要API更改。由于在Python中我们有属性,因此我们不需要在该实例中进行API更改,因此我们可以安全地避免setter和getter的样板和粗俗。
  • 它不会伤害继承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 
+0

+1啊不,只是为了学习语法。其实这给了我一个好主意:http://stackoverflow.com/questions/2702450/implement-a-simple-class-in-your-favorite-language – OscarRyz 2010-04-23 23:43:13

+0

关于这些属性,它也被用来(在Java中)保持这些属性是私人的,所以子类不能访问它们(并且可能会调节它们)。我一直在想:Python能有私人成员吗?我到处都看到了__',但我认为这只是一个命名规则而已? – OscarRyz 2010-04-23 23:47:37

+0

@Oscar,请记住,编程语言(如自然语言)有时不适合直接进行直译。特别是,像使用直接访问属性(而不是getter和setter)的东西是在Python中实现它的正确方式,即使它在Java中是令人讨厌的。这会让你一直认为你的UML图在理论上不应该与实现语言有任何关系。 – 2010-04-23 23:49:12