Is there a way to loop through and execute all of the functions in a Python class?
def assignOrder(order):
@decorator
def do_assignment(to_func):
to_func.order = order
return to_func
return do_assignment
class Foo():
@assignOrder(1)
def bar(self):
print "bar"
@assignOrder(2)
def foo(self):
print "foo"
#don't decorate functions you don't want called
def __init__(self):
#don't call this one either!
self.egg = 2
x = Foo()
functions = sorted(
#get a list of fields that have the order set
[
getattr(x, field) for field in dir(x)
if hasattr(getattr(x, field), "order")
],
#sort them by their order
key = (lambda field: field.order)
)
for func in functions:
func()
That funny @assignOrder(1)
line above def bar(self)
triggers this to happen:
Foo.bar = assignOrder(1)(Foo.bar)
assignOrder(1)
returns a function that takes another function, changes it (adding the field order
and setting it to 1
) and returns it. This function is then called on the function it decorates (its order
field gets thus set); the result replaces the original function.
It's a fancier, more readable and more maintainable way of saying:
def bar(self):
print "bar"
Foo.bar.order = 1
No. You can access Foo.__dict__
, and call each value in turn (catching errors for non-callable members), but the order is not preserved.
for callable in Foo.__dict__.values():
try:
callable()
except TypeError:
pass
This assumes none of the functions take parameters, as in your example.
Since Python stores the methods (and other attributes) of a class in a dictionary, which is fundamentally unordered, this is impossible.
If you don't care about order, use the class's __dict__
:
x = Foo()
results = []
for name, method in Foo.__dict__.iteritems():
if callable(method):
results.append(method(x))
This also works if the function takes extra parameters - just put them after the instance of the class.