B
Bruno Desthuilliers
Joe Goldthwaite a écrit :
The first obvious simplification is to replace this with:
def getValue(trend, param, per):
meth = getattr(trend, param)
return meth(per)
The main difference is that it will raise (instead of returning None) if
param is not the name of a method of trend.
The second simplification is to either get rid of getValue() (which is
mostly useless).
Note that this is not strictly equivalent:
class Parent(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return "<%s %s>" % (self.__class__.__name__, self.name)
def dothis(self):
return "parent.dothis %s" % self
class Child(Parent):
def dothis(self):
return "Child.dothis %s" % self
class OtherChild(Parent): pass
def dothat(obj):
return "dothat %s" % obj
p = Parent('p')
c1 = Child('c1')
c2 = Child('c2')
c2.dothis = dothat.__get__(c2, type(c2))
o1 = OtherChild('o1');
o2 = OtherChild('o2');
o2.dothis = dothat.__get__(o2, type(o2))
for obj in p, c1, c2, o1, o2:
print "obj : %s" % obj
print "direct call :"
print obj.dothis()
print "via obj.__class__.__dict__ :"
try:
print obj.__class__.__dict__["dothis"](obj)
except KeyError, e:
print "oops - key error: %s" % e
print
=>
obj : <Parent p>
direct call :
parent.dothis <Parent p>
via obj.__class__.__dict__ :
parent.dothis <Parent p>
obj : <Child c1>
direct call :
Child.dothis <Child c1>
via obj.__class__.__dict__ :
Child.dothis <Child c1>
obj : <Child c2>
direct call :
dothat <Child c2>
via obj.__class__.__dict__ :
Child.dothis <Child c2>
obj : <OtherChild o1>
direct call :
parent.dothis <OtherChild o1>
via obj.__class__.__dict__ :
oops - key error: 'dothis'
obj : <OtherChild o2>
direct call :
dothat <OtherChild o2>
via obj.__class__.__dict__ :
oops - key error: 'dothis'
IOW, direct access to obj.__class__.__dict__ bypasses both inheritence
and per-instance overriding.
Err... It actually means *more* lookup and function calls - and still
fails to behave correctly wrt/ polymorphic dispatch.
Hi everyone,
I'm a developer who's been using python for a couple of years. I wrote a
fairly large application using it but I was learning the language at the
same time so it most of the code kind of sucks.
I've learned a lot since then and I've been going through my code trying to
organize it better and make better use of Python's features. I'm still not
an expert by any definition but I'm slowly getting better.
I've been working on a trend class that takes twelve monthly numbers and
returns a period to date, quarter to date, year to date and quarterly year
to date numbers for a specific period. This worked but I ended up with a lot
of code like this;
def getValue(trend, param, per):
if param == 'Ptd':
return trend.Ptd(per)
elif param == 'Qtd':
return trend.Qtd(per)
elif param == 'Ytd':
return trend.Ytd(per)
elif param == 'YtdQ':
return trend.YtdQ(per)
The first obvious simplification is to replace this with:
def getValue(trend, param, per):
meth = getattr(trend, param)
return meth(per)
The main difference is that it will raise (instead of returning None) if
param is not the name of a method of trend.
The second simplification is to either get rid of getValue() (which is
mostly useless).
The code gets kind of wordy
indeed
so I started trying to figure out how to call
them dynamically since the param type is the same as the method the
retrieves it. I came up with this;
def getValue(trend, param, per):
return trend.__class__.__dict__[param](trend, per)
Note that this is not strictly equivalent:
class Parent(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return "<%s %s>" % (self.__class__.__name__, self.name)
def dothis(self):
return "parent.dothis %s" % self
class Child(Parent):
def dothis(self):
return "Child.dothis %s" % self
class OtherChild(Parent): pass
def dothat(obj):
return "dothat %s" % obj
p = Parent('p')
c1 = Child('c1')
c2 = Child('c2')
c2.dothis = dothat.__get__(c2, type(c2))
o1 = OtherChild('o1');
o2 = OtherChild('o2');
o2.dothis = dothat.__get__(o2, type(o2))
for obj in p, c1, c2, o1, o2:
print "obj : %s" % obj
print "direct call :"
print obj.dothis()
print "via obj.__class__.__dict__ :"
try:
print obj.__class__.__dict__["dothis"](obj)
except KeyError, e:
print "oops - key error: %s" % e
=>
obj : <Parent p>
direct call :
parent.dothis <Parent p>
via obj.__class__.__dict__ :
parent.dothis <Parent p>
obj : <Child c1>
direct call :
Child.dothis <Child c1>
via obj.__class__.__dict__ :
Child.dothis <Child c1>
obj : <Child c2>
direct call :
dothat <Child c2>
via obj.__class__.__dict__ :
Child.dothis <Child c2>
obj : <OtherChild o1>
direct call :
parent.dothis <OtherChild o1>
via obj.__class__.__dict__ :
oops - key error: 'dothis'
obj : <OtherChild o2>
direct call :
dothat <OtherChild o2>
via obj.__class__.__dict__ :
oops - key error: 'dothis'
IOW, direct access to obj.__class__.__dict__ bypasses both inheritence
and per-instance overriding.
That worked but it seems like the above line would have to do lots more
object look ups at runtime so I didn't think it would be very efficient. I
thought maybe I could add a caller method to the trend class and I came up
with this;
class trend:
...
...
...
def caller(self, param, *args):
return self.__class__.__dict__[param](self, *args)
This simplified the getValue function to this;
def getValue(trend, param, per):
return trend.caller(param, per)
Err... It actually means *more* lookup and function calls - and still
fails to behave correctly wrt/ polymorphic dispatch.