3

I'm trying to define a simply Fraction class

And I'm getting this error:

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

The code follows:

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()

I thought it was because I had numerator(self) and numerator(self, n) but now I know Python doesn't have method overloading ( function overloading ) so I renamed to get_numerator but that's not the problems.

What could it be?

1
  • As a beginner, you should learn, that in Python there is no need for getter and setter methods in these simple cases. Having just attributes for the numerator and denominator is just fine and accepted. And if you really want to be explicit about getter and setter functions, you should make your attributes protected with an underscore. Either way, your name-clashing problem won’t occur.
    – Debilski
    Commented Apr 23, 2010 at 23:48

3 Answers 3

18

You're using numerator as both a method name (def numerator(...)) and member variable name (self.numerator = n). Use set_numerator and set_denominator for the method names and it will work.

By the way, Python 2.6 has a built-in fraction class.

4
  • Got it!, so, if my attribute is numerator I can't have any other method with that name, right? ( either a "setter" or "getter" or any other ) Extra question, I had a syntax error when I tried to use the name "print" for my print method, so I had to name it prints is this because print is defined in object? or because it is global or something?
    – OscarRyz
    Commented Apr 23, 2010 at 22:41
  • About the fraction class thanks. I'm just learning, I'm doing some sort of language showcase with this class in Python, Ruby, Go, Java, Objective-C.
    – OscarRyz
    Commented Apr 23, 2010 at 22:51
  • 1
    @Oscar Reyes: In Python 2.x print is a keyword (used for the print statement), so you can't use it to name your methods or variables. In Python 3.x print is not a keyword anymore.
    – interjay
    Commented Apr 23, 2010 at 23:02
  • Better than renaming the setter to set_numerator would be to use properties instead. Getters and setters are unpythonic.
    – Aran-Fey
    Commented Jun 10, 2018 at 9:23
8

You can't overload the name numerator to refer to both the member variable and the method. When you set self.numerator = n, you're overwriting the reference to the method, and so when you call f.numerator(2), it's trying to do a method call on the member variable, which is an int, and Python doesn't let you do that. It's like saying x = 2; x(4) -- it just doesn't make any sense.

You should rename the setter methods to set_numerator and set_denominator to remove this naming conflict.

7
  • You are using numerator as both a method name and a name for an instance attribute. Since methods are stored on the class, when you lookup that attribute you get the number, not the method. (Python will look up attributes on the instance before looking at the class.)

    That is to say that on the line where you say f.numerator(2), it looks up f.numerator and finds that it is 0, then tries to call that 0, which obviously shouldn't work.

  • If you have any practical purpose for this code, you can use the stdlib fractions module: http://docs.python.org/library/fractions.html

    • This is new in Python 2.6. If I needed to represent fractions but was using an earlier version of Python, I'd probably use sympy's Rational type.
  • A more practical default value for denominator is probably 1. (That way Fraction(5) would be five, not some undefined operation tending towards infinity.)

  • Rather than a prints method, it would be more typical to define __str__ and just print your object.

  • Your methods are just getting and setting an attribute. In Python, we generally do not use getters and setters—we just let users set our attributes.

    • You're coming from a Java background, where one of the basic rules is always to use getter and setter methods rather than let users access attributes. The rationale for this rule is that if, at some future date, you needed to do more than just get and set (you needed to process the data), it would require an API change. Since in Python we have properties, we would not need an API change in that instance so we can safely avoid the boilerplate and cruft of setters and getters.
  • It wouldn't hurt to inherit numbers.Rational (Python 2.6 and up), which lets your class automatically do several things numbers are expected to. You will have to implement everything it needs you to, but then it will automatically make a lot more work. Check out Check out http://docs.python.org/library/numbers.html to learn more.


Spoiler alert:

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
5
  • +1 Ahh no , just to learn the syntax. Actually this gave me a good idea: stackoverflow.com/questions/2702450/…
    – OscarRyz
    Commented Apr 23, 2010 at 23:43
  • About the properties, it is also used ( in Java ) to keep the attributes private, so subclasses can't accesses them ( and probably temper them ). I have always wondered: Can Python have private members? I see __ everywhere, but I think that's just a naming convention isn't ?
    – OscarRyz
    Commented Apr 23, 2010 at 23:47
  • @Oscar, Keep in mind that programming languages (like natural languages) sometimes do not lend themselves to direct literal translation. In particular, things like using direct access to attributes (rather than getters and setters) is the right way to do it in Python even though it would be anathema in Java. This takes you all the way back to thinks like your UML diagrams which theoretically weren't supposed to have anything to do with the implementation language. Commented Apr 23, 2010 at 23:49
  • @Oscar, Private attributes do not exist in Python. The convention for an attribute that is not part of a public API is to use a single leading underscore, like _foo. Double leading underscore (and no more than one trailing underscore) like __foo name-mangles the attribute; some people use them for fake private attributes, but it doesn't effectively provide that. I don't use or like __foo, which makes my code harder to subclass, test, and maintain, and it isn't too widely likely among Python people. Commented Apr 23, 2010 at 23:51
  • In Python, properties (docs.python.org/library/functions.html#property) can be used to provide read-only attributes and sometimes are, but for the most part this is seen as misguided: if you don't want a user to modify an attribute, say not to in your documentation. It probably wouldn't make sense to anyway! If your use does anyhow, that isn't your fault; if it wasn't this, a sufficiently dumb user would find a way to use your code wrong anyhow. Trying to control what the user of your code does with it is a losing proposition. Besides, we're all consenting adults here. Commented Apr 23, 2010 at 23:55

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.