views:

314

answers:

3

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

+1  A: 

Why do you want to abuse the meaning of __str__? That method is reserved for the meaning "return a string representation of this instance".

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 reserved __str__ name.

bignose
+2  A: 

special method __str__ of a class works only for the instances of it, to have the different behavior for class objects you will have to do it in a metaclass 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
Anurag Uniyal
I had to use the new py3 syntax of class C(metaclass=M): ...but it works!
André
A: 

I'm not sure what you are trying to do, exactly. Let me just add a bit of random information.

First, add this class:

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

Print this instead:

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?")

To get 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?

Are you absolutely sure you don't want to call a classmethod?

Charles Merriam