Bugs item #1066490, was opened at 2004-11-15 07:46 Message generated for change (Comment added) made by birkenfeld You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1066490&group_id=5470
Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: Type/class unification Group: Python 2.3 Status: Open Resolution: Invalid Priority: 5 Submitted By: Kevin Quick (kquick) Assigned to: Michael Hudson (mwh) Summary: special methods become static Initial Comment: This *may* be a duplicate of 729913, but there's either additional info here, or this is actually different. The issue is that any special method (e.g. __call__, __str__, etc.) defined for a new-style (i.e. object-based) class seems to be static (i.e. unchangeable) with some special lookup applied for that method, but this doesn't seem to be the case for regular methods. class A: def foo(self): return 1 def __call__(self): return 2 def bar(self): return 3 def adjust(self): self.foo = self.bar self.__call__ = self.bar a = A() print a.foo(), a() a.adjust() print a.foo(), a() Will print: 1 2 3 3 But if the A is turned into a new-style class by changing the first line: class A(object): then the printed results are: 1 2 3 2 To the best of my understanding of the migration from classic classes to new-style classes (and metaclassing), this shouldn't occur. I have also tried various name munging for the special method (e.g. setting _B__call__, using setattr, etc.), but I haven't found the special trick yet. The attached script shows the example in more detail. ---------------------------------------------------------------------- >Comment By: Reinhold Birkenfeld (birkenfeld) Date: 2005-06-26 22:55 Message: Logged In: YES user_id=1188172 It is not the case that the methods are unchangeable. See this example: class A(object): def __repr__(self): return 'repr' def new_repr(self): return 'new_repr' a = A() a.__repr__ = a.new_repr print a.__repr__() => prints "new_repr" print repr(a) => prints "repr" ---------------------------------------------------------------------- Comment By: Kevin Quick (kquick) Date: 2004-12-22 20:00 Message: Logged In: YES user_id=6133 Thanks for the clarifcation. However IMHO it is wrong to have different behavior for different methods. To wit, if I defined a method, it is a bound method, and ergo a "self" initial argument is automatically supplied. However, a __repr__, even though I define it, acts as an unbound method, with the self argument having a default of the current instance but overrideable if an argument is supplied on the call. This means that the argument evaluation/passing is different for these types of builtins as opposed to other methods, both of which I have defined myself. This just doesn't seem right to me, which is why I'm re-opening this bug report... sorry to be annoying, but this definitely seems inconsistent and a better explanation. My current workaround is to do the following: class foo: def __str__(self): return my_str() def my_str(self): return 'something' So that I can do "foo.my_str = lambda self: return 'something else'". When what I should be able to do is: class foo: def __str__(self): return 'something' ... foo.__str__ = lambda self: return 'something else' ---------------------------------------------------------------------- Comment By: Michael Hudson (mwh) Date: 2004-11-16 09:22 Message: Logged In: YES user_id=6656 Oh, sorry, I think I got that a bit wrong. The issue is more with bound/unbound methods -- given class O(object): def __repr__(self): ... should O.__repr__ be a bound method (O is an instance of type) or an unbound method so O.__repr__(O()) does what you expect? Python chooses the latter, but this means that you can't implement the builtin function repr as def repr(o): return o.__repr__() Hope this helps, a little at least. ---------------------------------------------------------------------- Comment By: Kevin Quick (kquick) Date: 2004-11-15 15:29 Message: Logged In: YES user_id=6133 OK, I didn't find anything documenting this change anywhere (obviously). I read Guido's description of new-classes (www.python.org/2.2/descrintro.py) and the various documentation, but either I overlooked it therein or it's talked about somewhere else. I'm curious as to why special methods are treated specially in regards to this lookup. Specifically for your example, why wouldn't you just use the __repr__ attribute of o if it exists, instead of o's class, just like it does for non-special methods? Can you briefly explain this or provide me with a reference? Leaving this closed is OK with me since it's apparently known and expected... I'd just like to understand it a bit better. Sorry for the bandwidth, and Thanks! ---------------------------------------------------------------------- Comment By: Michael Hudson (mwh) Date: 2004-11-15 08:16 Message: Logged In: YES user_id=6656 The change you are observing is that special methods are now only looked up on the *class* of the object concerned. This, or something like this is actually unavoidable -- in >>> repr(o) what do you do if both o and the type of o define a __repr__ method? There are articles on new-style classes out there that should explain this in more depth. It probably could/should be documented better in the core -- there are bugs open to that effect already. Closing. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1066490&group_id=5470 _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com