|
Nah, write a little gadget: def f(F, *args):
f.reductor = F(*args)
return bool(f.reductor)
if f(dispatch_table.get, cls)):
rv = f.reductor(x)
elif f(getattr, x, "__reduce_ex__", None):
rv = f.reductor(4)
elif f(getattr, x, "__reduce__", None):
rv = f.reductor()
else:
raise Error("un(shallow)copyable object of type %s" % cls)
Same pattern works for re.match objects.Once you abstract the patterns you can drive towards data-driven code: K = (
(dispatch_table.get, (cls,), (x,)),
(getattr, (x, "__reduce_ex__", None), (4,)),
(getattr, (x, "__reduce__", None), ()),
)
for F, a, b in K:
reductor = F(*a)
if reductor:
rv = reductor(*b)
break
else:
raise Error("un(shallow)copyable object of type %s" % cls)
Syntax is the enemy, never substitute syntax for thought. |
At runtime, your second example is actually significantly less explicit because so much is hidden away in mutable state.