469,590 Members | 2,446 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,590 developers. It's quick & easy.

substitution __str__ method of an instance

I couldn't substitute __str__ method of an instance. Though I managed
to substitute ordinary method of an instance:

from types import MethodType

class Foo(object):
pass

class Printer(object):

def __call__(self, obj_self):
return 'printed'

f = Foo()

f.printer = MethodType(Printer(), f, Foo)
print f.printer() # works fine - I get: 'printed'

print f # get: <__main__.Foo object at 0x00D69C10>
f.__str__ = MethodType(Printer(), f, Foo)
print f # still get: <__main__.Foo object at 0x00D69C10>. Why?
Foo.__str__ = MethodType(Printer(), None, Foo)
print f # works fine - I get: 'printed'
How can I substitute __str__ method of an instance?
Oct 23 '08 #1
7 1260
netimen wrote:
I couldn't substitute __str__ method of an instance. Though I managed
to substitute ordinary method of an instance:

from types import MethodType

class Foo(object):
pass

class Printer(object):

def __call__(self, obj_self):
return 'printed'

f = Foo()

f.printer = MethodType(Printer(), f, Foo)
print f.printer() # works fine - I get: 'printed'

print f # get: <__main__.Foo object at 0x00D69C10>
f.__str__ = MethodType(Printer(), f, Foo)
print f # still get: <__main__.Foo object at 0x00D69C10>. Why?
Foo.__str__ = MethodType(Printer(), None, Foo)
print f # works fine - I get: 'printed'
How can I substitute __str__ method of an instance?
You can't. Special methods are only looked up on classes.

Diez
Oct 23 '08 #2
netimen wrote:
How can I substitute __str__ method of an instance?
It's not possible. For performance and other reasons most __*__ methods
are looked up on the type only.

Christian

Oct 23 '08 #3
Christian Heimes wrote:
netimen wrote:
>How can I substitute __str__ method of an instance?

It's not possible. For performance and other reasons most __*__ methods
are looked up on the type only.
Is that documented somewhere? I *know* it is that way, yet I'd like to have
place to read up on it (and point to when this question pops up)

Diez
Oct 23 '08 #4
netimen a écrit :
I couldn't substitute __str__ method of an instance. Though I managed
to substitute ordinary method of an instance:

from types import MethodType

class Foo(object):
pass

class Printer(object):

def __call__(self, obj_self):
return 'printed'

f = Foo()

f.printer = MethodType(Printer(), f, Foo)
print f.printer() # works fine - I get: 'printed'

print f # get: <__main__.Foo object at 0x00D69C10>
f.__str__ = MethodType(Printer(), f, Foo)
print f # still get: <__main__.Foo object at 0x00D69C10>. Why?
Foo.__str__ = MethodType(Printer(), None, Foo)
print f # works fine - I get: 'printed'
How can I substitute __str__ method of an instance?
Now that others told you you couldn't do so, there's eventually a
workaround - that is, if you have the hand on class Foo:

class Foo(object):
def __str__(self):
printer = getattr(self, 'printer', super(Foo, self).__str__)
return printer()

HTH
Oct 23 '08 #5
Diez B. Roggisch a écrit :
Christian Heimes wrote:
>netimen wrote:
>>How can I substitute __str__ method of an instance?
It's not possible. For performance and other reasons most __*__ methods
are looked up on the type only.

Is that documented somewhere? I *know* it is that way, yet I'd like to have
place to read up on it (and point to when this question pops up)
http://docs.python.org/reference/dat...-style-classes

Oct 23 '08 #6
On Thu, 23 Oct 2008 10:55:56 +0200, Christian Heimes wrote:
netimen wrote:
>How can I substitute __str__ method of an instance?

It's not possible. For performance and other reasons most __*__ methods
are looked up on the type only.

Christian
However, you can dispatch back to the instance if you really must:
class MyObj(object):
def __init__(self):
self.__str__ = lambda self: "I'm an object!"
def __str__(self):
return self.__str__(self)
But honestly, this sounds like a bad idea. If instances of the one class
have such radically different methods that they need to be treated like
this, I question whether they actually belong in the same class.


--
Steven
Oct 23 '08 #7
Steven D'Aprano <st***@REMOVE-THIS-cybersource.com.auwrote:
However, you can dispatch back to the instance if you really must:
class MyObj(object):
def __init__(self):
self.__str__ = lambda self: "I'm an object!"
def __str__(self):
return self.__str__(self)
But honestly, this sounds like a bad idea. If instances of the one
class
have such radically different methods that they need to be treated
like
this, I question whether they actually belong in the same class.
Another option would be to just change the class of the object:
>>class C(object):
pass
>>c = C()
print c
<__main__.C object at 0x01180C70>
>>def wrapstr(instance, fn=None):
if fn is None:
def fn(self): return "I'm an object"
Wrapper = type(instance.__class__.__name__, (instance.__class__,),
{'__str__':fn})
instance.__class__ = Wrapper

>>wrapstr(c)
print c
I'm an object
>>isinstance(c, C)
True
>>type(c)
<class '__main__.C'>
>>wrapstr(c, lambda s: "object %s at %s" % (type(s).__name__, id(s)))
print c
object C at 18353264

(I'll leave enhancing wrapstr so that it avoids multiple levels of
wrapping as an exercise for anyone who actually wants to use it.)

--
Duncan Booth http://kupuguy.blogspot.com
Oct 24 '08 #8

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

15 posts views Thread by Jim Newton | last post: by
15 posts views Thread by Jan Danielsson | last post: by
7 posts views Thread by Jeffrey E. Forcier | last post: by
1 post views Thread by kollareddy | last post: by
5 posts views Thread by Mike Krell | last post: by
5 posts views Thread by Konstantinos Pachopoulos | last post: by
6 posts views Thread by netimen | last post: by
4 posts views Thread by guiromero | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.