Python overriding class (not instance) special methods

17,006

Solution 1

Special method __str__ defined in a class works only for the instances of that class, to have the different behavior for class objects you will have to do it in a metaclass of that class e.g. (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

Solution 2

Why do you want to abuse the meaning of __str__? That method name (like many dunder method names) is special in Python, being an instance method with the meaning "return a string representation of this instance of the class".

If you want a function that just returns a static string, it would be better to have that as a separate function not inside a class.

If you want a constructor that returns a new string, name it something else so it's not clobbering the special __str__ name.

If you want a method for printing a representation of the class, you should not use the name __str__ for that. That name is – as the dunder-style name implies – expected to have particular behaviour as defined in the Python documentation. Choose some (non-dunder) name which you can give your special meaning, and don't forget to make it a class method.

Share:
17,006
André
Author by

André

Updated on June 24, 2022

Comments

  • André
    André almost 2 years

    How do I override a class special method?

    I want to be able to call the __str__() method of the class without creating an instance. Example:

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

    produces:

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

    should be:

    Bar
    Bar
    StaticBar
    StaticBar
    ClassBar
    ClassBar
    

    Even if I use the @staticmethod or @classmethod the __str__ is still using the built-in Python definition for __str__. It's only working when it's Foo().__str__() instead of Foo.__str__().

    • user1066101
      user1066101 about 14 years
      -1: "call the __str__() method of the class without creating an instance". Breaks every understanding anyone has of what an object is. Please do not do this. It makes the program absolutely violate our most fundamental expectations.
    • Dan Homerick
      Dan Homerick almost 14 years
      I disagree. If you call str(MyClass) then there's no reason you would expect it to behave as though you just called str(myClassObject). That is, there are no fundamental expectations to begin with. I suspect he wants to create a static class and never intends to create any instances of it.
  • André
    André about 14 years
    I had to use the new py3 syntax of class C(metaclass=M): ... but it works!
  • timgeb
    timgeb about 6 years
    "That method is reserved for the meaning "return a string representation of this instance"" <- the class is an instance itself, namely of type, so there's no conceptual problem with wanting to have a nice printout for a class. class A(object): pass; isinstance(A, type) -> True.
  • bignose
    bignose about 6 years
    @timgeb: I've updated the answer to account for that, thanks.