Static method object not callable

E

Edward Diener

This simple code example gives me the message, "TypeError: 'staticmethod'
object is not callable".

class X(object):
def Y(x):
print x
Y = staticmethod(Y)
ad = { 1 : Y }
def Z(self):
self.ad[1](3)
x = X()
x.Z()
print "Done."

I know there must be a way to have a class attribute reference a static
method, and then call that static method through the reference, so if anyone
can correct this it would be appreciated.
 
P

Paul Morrow

Edward said:
This simple code example gives me the message, "TypeError: 'staticmethod'
object is not callable".

class X(object):
def Y(x):
print x
Y = staticmethod(Y)
ad = { 1 : Y }
def Z(self):
self.ad[1](3)
x = X()
x.Z()
print "Done."

I know there must be a way to have a class attribute reference a static
method, and then call that static method through the reference, so if anyone
can correct this it would be appreciated.

Here are two alternatives.

class X(object):
def Y(x):
print x
Y = staticmethod(Y)
ad = { 1 : 'Y' }
def Z(self):
getattr(self, self.ad[1])(3)
x = X()
x.Z()
print "Done."


class X(object):
def Y(x):
print x
Y = staticmethod(Y)
def __init__(self):
self.ad = { 1 : self.Y }
def Z(self):
self.ad[1](3)
x = X()
x.Z()
print "Done."
 
E

Edward Diener

Paul said:
Edward said:
This simple code example gives me the message, "TypeError:
'staticmethod' object is not callable".

class X(object):
def Y(x):
print x
Y = staticmethod(Y)
ad = { 1 : Y }
def Z(self):
self.ad[1](3)
x = X()
x.Z()
print "Done."

I know there must be a way to have a class attribute reference a
static method, and then call that static method through the
reference, so if anyone can correct this it would be appreciated.

Here are two alternatives. snip...

Neither alternative is satisfactory. Surely there must be some means of
directly specifying a reference to a static method in a class attribute in
Python, and calling it from an instance method through the class attribute.
 
S

Shalabh Chaturvedi

Edward said:
This simple code example gives me the message, "TypeError: 'staticmethod'
object is not callable".

class X(object):
def Y(x):
print x
Y = staticmethod(Y)
ad = { 1 : Y }
def Z(self):
self.ad[1](3)
x = X()
x.Z()
print "Done."

I know there must be a way to have a class attribute reference a static
method, and then call that static method through the reference, so if
anyone can correct this it would be appreciated.

A staticmethod has to be accessed from the class or an instance. But you can
put the 'bare' function in your dictionary before you make a staticmethod
out of it:

class X(object):
def Y(x):
print x
ad = { 1 : Y }
Y = staticmethod(Y)
def Z(self):
self.ad[1](3)
x = X()
x.Z()
print "Done."

This prints:

3
Done.

HTH,
Shalabh
 
B

Bengt Richter

Paul said:
Edward said:
This simple code example gives me the message, "TypeError:
'staticmethod' object is not callable".

class X(object):
def Y(x):
print x
Y = staticmethod(Y)
ad = { 1 : Y }
def Z(self):
self.ad[1](3)
x = X()
x.Z()
print "Done."

I know there must be a way to have a class attribute reference a
static method, and then call that static method through the
reference, so if anyone can correct this it would be appreciated. By 'reference' are you referring to the Y in ad?

Here are two alternatives. snip...

Neither alternative is satisfactory. Surely there must be some means of
directly specifying a reference to a static method in a class attribute in
Python, and calling it from an instance method through the class attribute.
I'm not sure what you really want, but a staticmethod object is UIAM a descriptor
and when descriptors are retrieved as attributes of something, their __get__ methods
are called. That's why getattr was part of the other alternatives. Alternatively,
you can call the __get__ method directly, and in the case of staticmethod, that
will get you back the unadorned function in question, which you can then call. E.g.,
... def Y(x):
... print x
... Y = staticmethod(Y)
... ad = { 1 : Y }
... def Z(self):
... self.ad[1].__get__(self, type(self))(3)
... 3

(BTW, for staticmethod.__get__, probably any argument(s)
other than None or None,None will work)

Maybe this will clarify a little:

A function also works like a descriptor, and has a __get__ method, which is called
to create a bound method when the function is retrieved as an attribute of an
object instance. Note that Z is a function with one argument (self).

When retrieving Z as attribute of the class, the __get__ method gets
the arguments __get__(None, X), which gets you the unbound method.
<unbound method X.Z>

If we bypass the attribute access mechanism, we get the function itself:
<function Z at 0x009062B0>

If we do the getattr mechanics manually, calling the __get__ of the function,
we see the method results corresponding to X.Z and x.Z respectively:
>>> X.__dict__['Z'].__get__(None, X)
>>> X.__dict__['Z'].__get__(x, X)
<bound method X.Z of <__main__.X object at 0x009011D0>>

We can make a hokey descriptor object to show this: ... def __get__(*args): print args
... ... attr = Desc()
... (<__main__.Desc object at 0x009015D0>, <__main__.C object at 0x00901950>, <class '__main__.C'>)

So the __get__ args are the self of the decriptor instance itself (handy for carrying baggage like
a function), and here either None,C or c,C for C.attr and c.attr repectively.

Y is a staticmethod object though, not a plain function.
The __get__ method of a staticmethod object returns the same thing
(the original function) for either kind of call.
So when retrieved as an attribute of something, you get the function in question:
<function Y at 0x008FDF70>

Bypassing attribute mechanism:
<staticmethod object at 0x00901110>

Doing it manually bound-method style or unbound-method style:
>>> X.__dict__['Y'].__get__(x, X)
>>> X.__dict__['Y'].__get__(None, X)
<function Y at 0x008FDF70>

Calling the retrieved function:
>>> X.__dict__['Y'].__get__(x, X)(123)
123

Of course, 456

or 789

I still don't know what you are really trying to do with that
Z method and the ad dict ;-)

Regards,
Bengt Richter
 
J

Jp Calderone

Edward said:
This simple code example gives me the message, "TypeError: 'staticmethod'
object is not callable".

[snip]

I know there must be a way to have a class attribute reference a static
method, and then call that static method through the reference, so if anyone
can correct this it would be appreciated.

class X(object):
def Y(x):
print x
Y = staticmethod(Y)
def Z(self):
self.ad[1](3)
X.ad = {1: X.Y}

Jp
 
E

Edward Diener

Bengt said:
Paul said:
Edward Diener wrote:
This simple code example gives me the message, "TypeError:
'staticmethod' object is not callable".

class X(object):
def Y(x):
print x
Y = staticmethod(Y)
ad = { 1 : Y }
def Z(self):
self.ad[1](3)
x = X()
x.Z()
print "Done."

I know there must be a way to have a class attribute reference a
static method, and then call that static method through the
reference, so if anyone can correct this it would be appreciated. By 'reference' are you referring to the Y in ad?
Yes. I understand now why it won't work but I think this is a limitation of
Python. Evidently, if I set up my class attribute 'ad' to be "ad = { 1 :
X.Y }", then calling static method X.Y through "self.ad[1](3)" would work.
But Python does not allow me to say 'X.Y' from within a class attribute of X
because X has not been fully defined as a class at that time. As one person
answered, I can say "X.ad = { 1 : X.Y }" after the definition of class X and
that works fine. But that is very kludgy to me, forcing me to wait until the
definition of X is finished in order to create my ad class attribute.

I thank you very much for the explanation of _get_ and how static methods
work in Python. It still feels unnatural not to be able to reference a class
attribute of a class in another class attribute of the same class from
within the class definition.
 
B

Bengt Richter

Bengt said:
Paul Morrow wrote:
Edward Diener wrote:
This simple code example gives me the message, "TypeError:
'staticmethod' object is not callable".

class X(object):
def Y(x):
print x
Y = staticmethod(Y)
ad = { 1 : Y }
def Z(self):
self.ad[1](3)
x = X()
x.Z()
print "Done."

I know there must be a way to have a class attribute reference a
static method, and then call that static method through the
reference, so if anyone can correct this it would be appreciated.
By 'reference' are you referring to the Y in ad?
Yes. I understand now why it won't work but I think this is a limitation of
Python. Evidently, if I set up my class attribute 'ad' to be "ad = { 1 :
X.Y }", then calling static method X.Y through "self.ad[1](3)" would work.
But Python does not allow me to say 'X.Y' from within a class attribute of X
because X has not been fully defined as a class at that time. As one person
answered, I can say "X.ad = { 1 : X.Y }" after the definition of class X and
that works fine. But that is very kludgy to me, forcing me to wait until the
definition of X is finished in order to create my ad class attribute.

I thank you very much for the explanation of _get_ and how static methods
work in Python. It still feels unnatural not to be able to reference a class
attribute of a class in another class attribute of the same class from
within the class definition.
Ok, got a couple things done. Reward time = play with python a little ;-)

Since ad is an attribute, you could give *it* some magic, if you wanted
to get your effect. Taking a cue from staticmethod and property etc, we'll
call it dienerize, and you use it to dienerize a dict class variable, analogous
to method = staticmethod(method). Then dict values that are descriptors will be
called to see what reading them as attributes would produce. Non-descriptor dict
values just come through plain. I added a 2:'ordinary' example in the dict, and
3:Z to refer to an ordinary method, which is a function-valued class variable, but
functions all have __get__ methods, so they become transformed when they are
accessed as attributes (or the equivalent magic). I had do move the ad definition
so the Z name reference was valid.

I'm living with your capitalized method names through gritted teeth ;-)
Also added X.W to help show some effects. Don't take this as gospel, it's
the first time I tried this twist on a descriptor ;-)

----< diener.py >--------------------
#diener.py
class dienerize(dict):
def __getitem__(self, key):
value = dict.__getitem__(self, key)
if not hasattr(value, '__get__'): return value
return value.__get__(*self.getargs)
def __get__(self, *getargs):
self.getargs = getargs
return self # which should act like magic dict

class X(object):
def Y(x):
print x
Y = staticmethod(Y)
def Z(self):
self.ad[1](3)
ad = { 1 : Y, 2: 'ordinary', 3: Z }
ad = dienerize(ad)
def W(self, *args):
for i,arg in enumerate(args):
self.ad[1]('arg %2s: %r'%(i,arg)) # use Y for printing ;-)
x = X()
x.Z()
x.W(1,2,3)
x.W(X.Y, X.__dict__['Y'], x.ad[2], X.ad[2])
x.W(X.ad, X.__dict__['ad'], x.ad[1], X.ad[1])
x.W(x.ad[1], x.ad[2], x.ad[3]) # note that 3:Z becomes bound
x.W(x.ad[3],' ^--x.ad[3]',X.ad[3],' ^--X.ad[3]', x.__class__.__dict__['Z'],
" ^--x.__class__.__dict__['Z']")
print "Done."
-------------------------------------

Running it:

[22:18] C:\pywk\sovm>diener.py
3
arg 0: 1
arg 1: 2
arg 2: 3
arg 0: <function Y at 0x008FDEB0>
arg 1: <staticmethod object at 0x009013B0>
arg 2: 'ordinary'
arg 3: 'ordinary'
arg 0: {1: <staticmethod object at 0x009013B0>, 2: 'ordinary', 3: <function Z at 0x008FDEF0>}
arg 1: {1: <staticmethod object at 0x009013B0>, 2: 'ordinary', 3: <function Z at 0x008FDEF0>}
arg 2: <function Y at 0x008FDEB0>
arg 3: <function Y at 0x008FDEB0>
arg 0: <function Y at 0x008FDEB0>
arg 1: 'ordinary'
arg 2: <bound method X.Z of <__main__.X object at 0x00901390>>
arg 0: <bound method X.Z of <__main__.X object at 0x00901390>>
arg 1: ' ^--x.ad[3]'
arg 2: <unbound method X.Z>
arg 3: ' ^--X.ad[3]'
arg 4: <function Z at 0x008FDEF0>
arg 5: " ^--x.__class__.__dict__['Z']"
Done.

Since you now know why the original "didn't work" I figure you will know
why this one appears to ;-)

Gotta go.

Regards,
Bengt Richter
 
Joined
Oct 14, 2006
Messages
2
Reaction score
0
Here's a fix that seemed the most elegant to me.

Code:
>>> class X(object):
	def prt(text):
		print text
	Y = staticmethod(prt)
	ad = {1:prt}
	def Z(self):
		self.ad[1]("Testing, testing...")

		
>>> test = X()
>>> test.Z()
Testing, testing...

This makes two separate objects, a static method and an ordinary method. The 'prt' object can be called as a normal function while you're still inside the class definition. However, 'prt' will work differently outside the definition, since it will then be treated as a method, expecting a 'self' argument. You would need to use the static method 'Y' outside the definition in order to get back to the original behavior.

Code:
>>> test.prt()		# Automatically fills in 'test' as the argument
<__main__.X object at 0x01176910>
>>> print test 		# This is what the 'prt' method would then do...
<__main__.X object at 0x01176910>
>>> test.Y('Spam and eggs')
Spam and eggs
 
Last edited:

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

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top