3

There are (at least) three different ways to track state information for functions in python (examples presented without any meaningful way to use the state information, obviously):

OOP Classes:

class foo:
    def __init__(self, start):
        self.state = start
    # whatever needs to be done with the state information

nonlocal variables (Python 3):

def foo(start):
    state = start
    def bar():
        nonlocal state
        # whatever needs to be done with the state information
    return bar

or function attributes:

def foo(start):
    def bar(bar.state):
        # whatever needs to be done with the state information
    bar.state = start
    return bar

I understand how each method works, but what I've not been able to reason is why (aside from familiarity) you would ever choose one method over another. Following the Zen of Python, classes would seem to be the most elegant technique, as it removes the need to nest function definitions. However, at the same time, classes might introduce more complexity than is needed.

What should one be considering when weighing which method to use in a program?

DrMag
  • 39
  • 1
  • 3
  • 4
    I would always choose a class, because of the way it is used, rather than the way it is implemented. When I instantiate a class, I expect that the instance may keep some state information. That is what class instances do. When I call a function I generally expect that it returns the same result whenever it is called with the same arguments, so if it keeps a state, that will be unexpected and may cause bugs in my (caller's) code, although even that behaviour is not completely wrong if well documented. – zvone May 23 '18 at 20:07
  • 2
    The question is probably too broad, but as a general rule, you should probably have a solid, concrete reason *not* to use a class before worrying about the other two. (And function attributes are almost an accident of whatever implementation you are using, rather than something to be intentionally used.) – chepner May 23 '18 at 20:08
  • BTW don't worry about *"classes might introduce more complexity than is needed"*. Most complexity comes from lack of clarity in my experience. – zvone May 23 '18 at 20:10
  • 1
    Keep in mind that your function `bar` is defined anew every time you *call* `foo`. – chepner May 23 '18 at 20:10
  • Agree that a class is the most clear. I find `nonlocal` very hard to reason about. In addition your use of a function attribute looks like a poor man's class. A better use of a function attribute is documentation: https://stackoverflow.com/questions/338101/python-function-attributes-uses-and-abuses – HFBrowning May 23 '18 at 20:12
  • I think function attributes are cute, but they aren't popular. Partly, that's for the reason given by zvone, and partly it's because they're obscure, so many people don't even realise that they're possible (apart from `.__doc__` and `.__name__`). I sometimes use them for state that doesn't affect the return value, eg tracking how many times the function gets called. I once thought they'd be ok for a memoizing cache, but they're slow (lookup time for the global function name, then lookup of the attribute). – PM 2Ring May 23 '18 at 21:33

0 Answers0