Python переопределяющий класс (не экземпляр) специальные методы

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

Я хочу смочь звонить __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__().

12
задан Stefan van den Akker 9 May 2014 в 20:55
поделиться

3 ответа

Специальный метод __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()

output:

Klass
instance
20
ответ дан 2 December 2019 в 07:20
поделиться

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

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

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

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

1
ответ дан 2 December 2019 в 07:20
поделиться

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

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

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?

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

0
ответ дан 2 December 2019 в 07:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: