Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Unexpected __metaclass__ method behavior

Reply
Thread Tools

Unexpected __metaclass__ method behavior

 
 
anne.nospam01@wangnick.de
Guest
Posts: n/a
 
      12-30-2007
Dear fellow Pythonians,

I just stumbled upon the following unexpected behavior:

class TestType(type):
def Foo(self): return 'TestType Foo'
class Test(object):
__metaclass__ = TestType
def Foo(self): return 'Test Foo'
t = Test()
print t.Foo()
print Test.Foo()

This will produce:
Test Foo
Traceback (most recent call last):
File "test.py", line 8, in <module>
print Test.Foo()
TypeError: unbound method Foo() must be called with Test instance as
first argument (got nothing instead)

I can imagine why this is happening, and that there is no easy
solution, but it is not what I was expecting.

Anybody willing to explain the details of what's exactly going on
during the method lookup of Test.Foo?

Kind regards,
Sebastian
 
Reply With Quote
 
 
 
 
Michele Simionato
Guest
Posts: n/a
 
      12-30-2007


anne.nospa...@wangnick.de wrote:
> Dear fellow Pythonians,
>
> I just stumbled upon the following unexpected behavior:
>
> class TestType(type):
> def Foo(self): return 'TestType Foo'
> class Test(object):
> __metaclass__ = TestType
> def Foo(self): return 'Test Foo'
> t = Test()
> print t.Foo()
> print Test.Foo()
>
> This will produce:
> Test Foo
> Traceback (most recent call last):
> File "test.py", line 8, in <module>
> print Test.Foo()
> TypeError: unbound method Foo() must be called with Test instance as
> first argument (got nothing instead)
>
> I can imagine why this is happening, and that there is no easy
> solution, but it is not what I was expecting.
>
> Anybody willing to explain the details of what's exactly going on
> during the method lookup of Test.Foo?


The regular method is checked for *before* the metaclass method.
You must use

type(Test).Foo(Test)

to call the method. It is clear that it must be that way: when you do
(for instance)
SomeClass.__init__ you do not expect to have type.__init__(SomeClass)
called.
Notice that *all* classes have a metaclass, by default "type" for new-
style
classes and "ClassType" for old-style ones.

Michele Simionato
 
Reply With Quote
 
 
 
 
Terry Reedy
Guest
Posts: n/a
 
      12-30-2007

<> wrote in message
news:2273796e-87c6-4100-a5b5-...
| Dear fellow Pythonians,
|
| I just stumbled upon the following unexpected behavior:
|
| class TestType(type):
| def Foo(self): return 'TestType Foo'
| class Test(object):
| __metaclass__ = TestType
| def Foo(self): return 'Test Foo'
| t = Test()
| print t.Foo()
| print Test.Foo()
|
| This will produce:
| Test Foo
| Traceback (most recent call last):
| File "test.py", line 8, in <module>
| print Test.Foo()
| TypeError: unbound method Foo() must be called with Test instance as
| first argument (got nothing instead)
|
| I can imagine why this is happening, and that there is no easy
| solution, but it is not what I was expecting.

Regardless of which Foo you expect to be called, both require an instance
argument to be bound to the paramenter 'self'.

print Test.Foo(t) # will print same as t.Foo()

tjr



 
Reply With Quote
 
anne.nospam01@wangnick.de
Guest
Posts: n/a
 
      12-31-2007
Well, you see, I have some database functions that deal with "things"
which are either classes or instances thereof. I though polymorphism
would be a nice way to handle them identically, like:

def do(thing): thing.Foo()
do(t)
do(Test)

But never mind, I now understand that Test.__dict__ can contain only
one entry for 'Foo', and that this must be matched.

Kind regards,
Sebastian
 
Reply With Quote
 
Arnaud Delobelle
Guest
Posts: n/a
 
      12-31-2007
On Dec 31, 12:06*pm, anne.nospa...@wangnick.de wrote:
> Well, you see, I have some database functions that deal with "things"
> which are either classes or instances thereof. I though polymorphism
> would be a nice way to handle them identically, like:
>
> def do(thing): thing.Foo()
> do(t)
> do(Test)
>
> But never mind, I now understand that Test.__dict__ can contain only
> one entry for 'Foo', and that this must be matched.
>
> Kind regards,
> Sebastian


Of course you can do this. The trick is *not* to use metaclasses!

class Bar(object):
def foo(self): return 'instance foo'
@classmethod
def classfoo(cls): return 'class foo'

def do(x):
if isinstance(x, type):
return x.classfoo()
else:
return x.foo()

Then:

>>> bar = Bar()
>>> do(bar)

'instance foo'
>>> do(Bar)

'class foo'

HTH

--
Arnaud



 
Reply With Quote
 
Bruno Desthuilliers
Guest
Posts: n/a
 
      01-06-2008
a écrit :
> Well, you see, I have some database functions that deal with "things"
> which are either classes or instances thereof. I though polymorphism
> would be a nice way to handle them identically, like:
>
> def do(thing): thing.Foo()
> do(t)
> do(Test)
>
> But never mind, I now understand that Test.__dict__ can contain only
> one entry for 'Foo', and that this must be matched.


You may want to have a look at FormEncode's "declarative" API, with
particular attention to the 'classinstancemethod' stuff.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Is this a good use of __metaclass__? Joel Hedlund Python 9 05-09-2006 08:41 AM
__metaclass__ and __author__ are already decorators Paul Morrow Python 10 08-22-2004 08:44 AM
runtime inheritance (e.g. __new__, __metaclass__) H Jansen Python 3 07-28-2004 07:24 PM
__slots__, setattr, __metaclass__ Roman Yakovenko Python 1 01-12-2004 03:41 PM
Understanding and working with __metaclass__ David M. Wilson Python 4 12-09-2003 07:19 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57