Объект int не вызывается - PullRequest
3 голосов
/ 24 апреля 2010

Я пытаюсь определить просто 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 ]

19 голосов
/ 24 апреля 2010

Вы используете numerator в качестве имени метода (def numerator(...)) и имени переменной-члена (self.numerator = n). Используйте set_numerator и set_denominator для имен методов, и это будет работать.

Кстати, в Python 2.6 есть встроенный класс дроби .

9 голосов
/ 24 апреля 2010

Вы не можете перегрузить имя numerator, чтобы ссылаться как на переменную-член, так и на метод. Когда вы устанавливаете self.numerator = n, вы перезаписываете ссылку на метод, и поэтому, когда вы вызываете f.numerator(2), он пытается выполнить вызов метода для переменной-члена, которая является int, а Python не позволь тебе сделать это. Это все равно что сказать x = 2; x(4) - это просто не имеет никакого смысла.

Вы должны переименовать методы установки в set_numerator и set_denominator, чтобы устранить этот конфликт имен.

7 голосов
/ 24 апреля 2010
  • Вы используете numerator как имя метода и имя для атрибута экземпляра. Поскольку методы хранятся в классе, при поиске этого атрибута вы получаете число, а не метод. (Python будет искать атрибуты в экземпляре, прежде чем смотреть на класс.)

    То есть, в строке, где вы говорите f.numerator(2), он ищет f.numerator и находит, что это 0, затем пытается вызвать это 0, что, очевидно, не должно работать.

  • Если у вас есть практическая цель для этого кода, вы можете использовать модуль stdlib fractions: http://docs.python.org/library/fractions.html

    • Это новое в Python 2.6. Если бы мне нужно было представить дроби, но я использовал более раннюю версию Python, я бы, вероятно, использовал тип sympy Rational.
  • Более практичное значение по умолчанию для denominator, вероятно, 1. (Таким образом, Fraction(5) будет пять, а не какая-то неопределенная операция, стремящаяся к бесконечности.)

  • Вместо метода prints было бы более типично определить __str__ и просто напечатать ваш объект.

  • Ваши методы просто получают и устанавливают атрибут. В Python мы обычно не используем геттеры и сеттеры - мы просто позволяем пользователям устанавливать наши атрибуты.

    • Вы пришли из Java-фона, где одним из основных правил всегда является использование методов получения и установки, а не предоставление пользователям доступа к атрибутам. Обоснование этого правила заключается в том, что если в какой-то момент в будущем вам нужно будет сделать больше, чем просто получить и установить (вам нужно обработать данные), это потребует изменения API. Поскольку в Python у нас есть свойства, нам не нужно было бы изменять API в этом случае, поэтому мы можем безопасно избегать шаблонов и ошибок методов установки и получения.
  • Не повредило бы наследование 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...