Skip to content Skip to sidebar Skip to footer

Is There A Way To Loop Through And Execute All Of The Functions In A Python Class?

I have class Foo(): function bar(): pass function foobar(): pass Rather than executing each function one by one as follows: x = Foo() x.bar() x.foobar()

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?"