Специальные методы класса переопределения (не экземпляра) Python - PullRequest
11 голосов
/ 23 марта 2010

Как мне переопределить специальный метод класса?

Я хочу иметь возможность вызывать метод __str__() класса без создания экземпляра.Пример:

class Foo:
    def __str__(self):
        return 'Bar'

class StaticFoo:
    @staticmethod
    def __str__():
        return 'StaticBar'

class ClassFoo:
    @classmethod
    def __str__(cls):
        return 'ClassBar'

if __name__ == '__main__':
    print(Foo)
    print(Foo())
    print(StaticFoo)
    print(StaticFoo())
    print(ClassFoo)
    print(ClassFoo())

производит:

<class '__main__.Foo'>
Bar
<class '__main__.StaticFoo'>
StaticBar
<class '__main__.ClassFoo'>
ClassBar

должно быть:

Bar
Bar
StaticBar
StaticBar
ClassBar
ClassBar

Даже если я использую @staticmethod или @classmethod __str__все еще использует встроенное определение Python для __str__.Он работает только тогда, когда он Foo().__str__() вместо Foo.__str__().

Ответы [ 3 ]

19 голосов
/ 23 марта 2010

Специальный метод __str__, определенный в классе, работает только для экземпляров этого класса, чтобы иметь различное поведение для объектов класса, вам придется делать это в метаклассе этого класса, например (python 2.5)

class Meta(type):
    def __str__(self):
        return "Klass"

class A(object):
    __metaclass__ = Meta

    def __str__(self):
        return "instance"

print A
print A()

вывод:

Klass
instance
1 голос
/ 23 марта 2010

Почему вы хотите злоупотреблять значением __str__? Это имя метода (например, многие имена более сложных методов ) является особенным в Python и представляет собой метод экземпляра со значением "вернуть строковое представление этого экземпляра класса".

Если вам нужна функция, которая просто возвращает статическую строку, лучше иметь ее как отдельную функцию, а не внутри класса.

Если вам нужен конструктор, который возвращает новую строку, назовите ее как-нибудь еще, чтобы не загромождать специальное имя __str__.

Если вам нужен метод для печати представления класса, вам не следует использовать имя __str__ для этого. Это имя - поскольку имя в стиле дандер подразумевает - ожидается, что будет иметь особое поведение, как определено в документации Python . Выберите какое-нибудь (не простое) имя, которое вы можете придать своему особому значению, и не забудьте сделать его методом класса.

0 голосов
/ 23 марта 2010

Я точно не знаю, что вы пытаетесь сделать.Позвольте мне добавить немного случайной информации.

Сначала добавьте этот класс:

class FooNew(object):
def __str__(self):
    return 'Fubar'

Напечатайте это вместо:

if __name__ == '__main__':
    print "You are calling type for an old style class"
    print(Foo)
    print(type.__str__(Foo))
    print(Foo())
    print("But my Python 2.6 didn't match your output for print(Foo)")
    print("You are calling object.str() for a new style class")
    print(FooNew)
    print(object.__str__(FooNew))
    print(FooNew())
    print("Why do you want to change this?")

Чтобы получить это:

You are calling type for an old style class
__main__.Foo
<class __main__.Foo at 0xb73c9f5c>
Bar
But my Python 2.6 didn't match your output for print(Foo)
You are calling object.str() for a new style class
<class '__main__.FooNew'>
<class '__main__.FooNew'>
Fubar
Why do you want to change this?

Вы абсолютно уверены, что не хотите вызывать метод класса?

...