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