473,387 Members | 1,536 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Unexpected __metaclass__ method behavior

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
Dec 30 '07 #1
5 1201


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
Dec 30 '07 #2

<an***********@wangnick.dewrote in message
news:22**********************************@i29g2000 prf.googlegroups.com...
| 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

Dec 30 '07 #3
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
Dec 31 '07 #4
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

Dec 31 '07 #5
an***********@wangnick.de 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.
Jan 6 '08 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Paul Morrow | last post by:
Thinking about decorators, and looking at what we are already doing in our Python code, it seems that __metaclass__, __author__, __version__, etc. are all examples of decorators. So we already...
16
by: He Shiming | last post by:
Hi, I'm having a little bit of trouble regarding pointer casting in my program. I don't understand why the following two cases produce different results. Case 1: IInterface *pInterface = new...
6
by: Samuel M. Smith | last post by:
I have been playing around with a subclass of dict wrt a recipe for setting dict items using attribute syntax. The dict class has some read only attributes that generate an exception if I try to...
9
by: Joel Hedlund | last post by:
Hi! I need some input on my use of metaclasses since I'm not sure I'm using them in a pythonic and graceful manner. I'm very grateful for any tips, pointers and RTFMs I can get from you guys. ...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.