Odd behavior with staticmethods

C

cmdrrickhunter

I'm getting rather inconsistent behavior with staticmethod.
@staticmethod has the same problems, but I'm demonstrating it with
staticmethod() because it shows things more clearly
--------------------------------------------------- def orig():
print "hi"
st = staticmethod(orig)
st2 = st
wrapped = [ orig ]
wrapped2 = [ st ]


Traceback (most recent call last):
File "<pyshell#9>", line 1, in -toplevel-
A.orig()
TypeError: unbound method orig() must be called with A instance as
first argument (got nothing instead)
A.st() # NORMAL - staticmethod, all good hi
A.st2() # NORMAL - copy of a static method, all good hi
A.wrapped[0]() # ODD - wrapping orig() in a list makes orig() work? hi
A.wrapped2[0]() # ODD - copying st works -- A.st2() -- but copying it to a list fails?

Traceback (most recent call last):
File "<pyshell#13>", line 1, in -toplevel-
A.wrapped2[0]()
TypeError: 'staticmethod' object is not callable
a = [ A.orig] # NORMAL - fails as expected
a[0]()

Traceback (most recent call last):
File "<pyshell#27>", line 1, in -toplevel-
a[0]()
TypeError: unbound method orig() must be called with A instance as
first argument (got nothing instead)
b = [ A.st ] # NORMAL - suceeds as expected
b[0]() hi

type(A.orig)
type(A.st)
type(A.st2)
type(A.wrapped[0])
type(A.wrapped2[0])
type(a[0])
type(b[0])
<type 'function'>

------------------------------------------------------------

So if the class definition is not finished, one can copy static methods
just fine. But if it finds its way into a container (in this case, a
list, but making it a member variable of a child object also breaks),
it gets an extra staticmethod wrapper, or something similar? Once the
class is done, this behavoir no longer occurs.

Can anyone please explain to me why this happens?
 
S

Scott David Daniels

I'm getting rather inconsistent behavior with staticmethod.
Not really.
def orig():
print "hi"
st = staticmethod(orig)
st2 = st
wrapped = [ orig ]
wrapped2 = [ st ] ....
>>>> A.wrapped[0]() # ODD - wrapping orig() in a list makes orig() work? > hi
>>>> A.wrapped2[0]() # ODD - copying st works -- A.st2() -- but copying
it to a list fails?
....

When you put orig in wrapped, it is _before_ the class is built,
so you are placing a simple function of no args in a list.

When you put st in wrapped2, it is also _before_ the class is built,
so you are placing staticmethod(a simple function of no args) in a list.

You really should be using new-style classes, some things just
work wrong in "classic classes" (this is not one of those things,
however).

When the class gets built, the staticmethod wrapper is used to determine
how to build A. The class construction gets handed the "namespace"
that was defined in the class suite, and it fumbles over the defined
names determining what conversions to apply (and looking for things
like "__metaclass__" and "__slots__"). For more on all of this read
the language reference, esp. the "Data Model" section, and probably that
on the difference between old-style and new-style classes.



--Scott David Daniels
(e-mail address removed)
 
C

cmdrrickhunter

ya know, I've searched for these "new classes" at least five times.
I've heard all the wonderful things about how they make your life into
a piece of chocolate with rainbows sprinkled in it. Never once have I
found a site that explains what syntax to use to make these new
classes.

Anyone have a URL?

I'm getting rather inconsistent behavior with staticmethod.
Not really.
def orig():
print "hi"
st = staticmethod(orig)
st2 = st
wrapped = [ orig ]
wrapped2 = [ st ] ...
A.wrapped[0]() # ODD - wrapping orig() in a list makes orig() work? hi
A.wrapped2[0]() # ODD - copying st works -- A.st2() -- but copying
it to a list fails?
...

When you put orig in wrapped, it is _before_ the class is built,
so you are placing a simple function of no args in a list.

When you put st in wrapped2, it is also _before_ the class is built,
so you are placing staticmethod(a simple function of no args) in a list.

You really should be using new-style classes, some things just
work wrong in "classic classes" (this is not one of those things,
however).

When the class gets built, the staticmethod wrapper is used to determine
how to build A. The class construction gets handed the "namespace"
that was defined in the class suite, and it fumbles over the defined
names determining what conversions to apply (and looking for things
like "__metaclass__" and "__slots__"). For more on all of this read
the language reference, esp. the "Data Model" section, and probably that
on the difference between old-style and new-style classes.



--Scott David Daniels
(e-mail address removed)
 
S

Scott David Daniels

ya know, I've searched for these "new classes" at least five times.
I've heard all the wonderful things about how they make your life into
a piece of chocolate with rainbows sprinkled in it. Never once have I
found a site that explains what syntax to use to make these new
classes.

http://www.python.org/doc/newstyle.html

From the docs for the upcoming 2.5:

http://docs.python.org/dev/ref/node33.html


As to how you make them:

class Whatever:
...
is an old-style class.

class Whenever(object):
...
is a new-style class.

class Whoever(SomeClass):
...
is an old-style class if SomeClass is an old-style class,
and a new-style class if SomeClass is a new-style class.

--Scott David Daniels
(e-mail address removed)
 
B

Bruno Desthuilliers

ya know, I've searched for these "new classes" at least five times.

Then go and buy yourself a pair of glasses. It's one of the entrie in
the "documentation" menu of python.org.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,151
Latest member
JaclynMarl
Top