Is There A Way To Loop Through And Execute All Of The Functions In A Python Class?
Solution 1:
defassignOrder(order):
@decoratordefdo_assignment(to_func):
to_func.order = order
return to_func
return do_assignment
classFoo():
@assignOrder(1)defbar(self):
print"bar" @assignOrder(2)deffoo(self):
print"foo"#don't decorate functions you don't want calleddef__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 indir(x)
ifhasattr(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:
defbar(self):
print"bar"
Foo.bar.order = 1
Solution 2:
No. You can access Foo.__dict__
, and call each value in turn (catching errors for non-callable members), but the order is not preserved.
forcallablein Foo.__dict__.values():
try:
callable()
except TypeError:
pass
This assumes none of the functions take parameters, as in your example.
Solution 3:
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, methodin 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.
Solution 4:
So long as you're only interested in Python 3.x (and from the empty parentheses in your class statement I'll guess you might be), then there is actually a simple way to do this without decorators: Python 3 allows you to provide your own dictionary like object to use while the class is defined.
The following code is from PEP3115 except for the last couple of lines which I added to print out the methods in order:
# The custom dictionaryclassmember_table(dict):
def__init__(self):
self.member_names = []
def__setitem__(self, key, value):
# if the key is not already defined, add to the# list of keys.if key notin self:
self.member_names.append(key)
# Call superclassdict.__setitem__(self, key, value)
# The metaclassclassOrderedClass(type):
# The prepare function @classmethoddef__prepare__(metacls, name, bases): # No keywords in this casereturn member_table()
# The metaclass invocationdef__new__(cls, name, bases, classdict):
# Note that we replace the classdict with a regular# dict before passing it to the superclass, so that we# don't continue to record member names after the class# has been created.
result = type.__new__(cls, name, bases, dict(classdict))
result.member_names = classdict.member_names
return result
classMyClass(metaclass=OrderedClass):
# method1 goes in array element 0defmethod1(self):
pass# method2 goes in array element 1defmethod2(self):
pass
x = MyClass()
print([name for name in x.member_names ifhasattr(getattr(x, name), '__call__')])
Solution 5:
There is probably one of the shortest methods (the class name is C):
for func infilter(lambda x: callable(x), C.__dict__.values()):
pass# here func is the next function, you can execute it here
The filter expression returns all functions of the class C.
OR in one line:
[func()forfuncinfilter(lambda x: callable(x), C.__dict__.values())]
You can order somehow the functions, for example, by lexicographical order of their names by little more complex expression.
Post a Comment for "Is There A Way To Loop Through And Execute All Of The Functions In A Python Class?"