Hi! I am curious why the following will not work in Python: class foo(object): def bar(self): print self.attr class duck(object): attr = 3.14 foo.bar(duck()) Is it a design decision that duck-typing self does not work or is there a technical reason? From a practical standpoint it seems that being able to duck-type self has merit, for example in unit testing complex classes. - Sebastian
On Wed, Feb 18, 2009 at 2:32 PM, Sebastian Rittau <srittau@jroger.in-berlin.de> wrote:
Hi!
I am curious why the following will not work in Python:
class foo(object): def bar(self): print self.attr
class duck(object): attr = 3.14
foo.bar(duck())
Is it a design decision that duck-typing self does not work or is there a technical reason? From a practical standpoint it seems that being able to duck-type self has merit, for example in unit testing complex classes.
Works for me in 3.0: Python 3.1a0 (py3k:69082, Jan 28 2009, 19:22:10) [MSC v.1500 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information.
class Foo(object): ... def bar(self): ... print(self.attr) ... class Duck(object): ... attr = 3.14 ... Foo.bar(Duck()) 3.14
Steve -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy
Steven Bethard wrote:
Is it a design decision that duck-typing self does not work or is there a technical reason? From a practical standpoint it seems that being able to duck-type self has merit, for example in unit testing complex classes.
Works for me in 3.0:
class Foo(object): ... def bar(self): ... print(self.attr) ... Foo.bar <unbound method Foo.bar> class Duck(object): ... attr = "python" ... Foo.bar(Duck()) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unbound method bar() must be called with Foo instance as first argument (got Duck instance instead) Foo.bar.im_func <function bar at 0x7f6ec83a01b8> Foo.bar.im_func(Duck())
class Foo(object): ... def bar(self): ... print(self.attr) ... Foo.bar <function bar at 0x7f0f747666b0> class Duck(object): ... attr = "python" ... Foo.bar(Duck())
It works in 3.0 because we have lifted some restrictions (and increased speed as a neat side effect). In Python 2.x the type checking speed with negligible, but Python 3's abc system with the new __instancecheck__() and __subclasscheck__() hooks are a real speed drain. In 2.x a class objects wrap their functions in a method wrapper. The method wrapper does the type check. You can get around the type check by using the im_func attribute of the method wrapper. Python 2.5.2 (r252:60911, Oct 5 2008, 19:29:17) [GCC 4.3.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. python In 3.0 the unbound method wrapper is gone and class objects return the pure function. Without the type checking of the unbound method wrapper the restriction is gone. Python 3.0.1 (r301:69655, Feb 15 2009, 23:28:13) [GCC 4.3.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. python HTH Christian
Christian Heimes wrote:
In 2.x a class objects wrap their functions in a method wrapper. The method wrapper does the type check. You can get around the type check by using the im_func attribute of the method wrapper.
You could probably also create a decorator that gives you something behaving like an unbound method but without the type check (implementation details left to the reader). -- Greg
Sebastian Rittau wrote:
Is it a design decision that duck-typing self does not work or is there a technical reason?
There's no technical reason as far as user-defined classes are concerned. I think it was introduced to help catch errors due to making inherited method calls to the wrong class, which can easily happen if you change the base class of a class and forget to update all of the inherited calls to match. I believe this type check has been removed in 3.0, so duck-typing of self is possible there. -- Greg
On Wed, Feb 18, 2009 at 11:32:09PM +0100, Sebastian Rittau wrote:
I am curious why the following will not work in Python:
class foo(object): def bar(self): print self.attr
class duck(object): attr = 3.14
foo.bar(duck())
Thanks to everybody who has responded on-list or in private. Actually Guido blogged about this design decision (among other things) in his latest post to the "The History of Python" blog: <http://tinyurl.com/c6qya5>. - Sebastian
participants (4)
-
Christian Heimes
-
Greg Ewing
-
Sebastian Rittau
-
Steven Bethard