Are there pythonic
ways to maintain state (for purposes of optimisation, for example) without going fully object-oriented?
To illustrate my question better, here's an example of a pattern I use frequently in JavaScript:
var someFunc = (function () {
var foo = some_expensive_initialization_operation();
return someFunc (bar) {
// do something with foo and bar
}
}());
Externally this is just a function like any other, with no need to initialise objects or anything like that, but the closure allows computing values a single time that I then essentially use as constants.
An example of this in Python is when optimising regular expressions - it's useful to use re.compile
and stored the compiled version for match
and search
operations.
The only ways I know of to do this in Python are by setting a variable in the module scope:
compiled_regex = compile_my_regex()
def try_match(m): # In reality I wouldn't wrap it as pointlessly as this
return compiled_regex.match(m)
Or by creating a class:
class MatcherContainer(object):
def __init__(self):
self.compiled_regex = compile_my_regex()
def try_match(self, m):
self.compiled_regex.match(m)
my_matcher = MatcherContainer()
The former approach is ad-hoc and it's not very clear that the function and the variable declared above it are associated with each other. It also sits pollutes the module's namespace a bit, which I'm not too happy with.
The latter approach seems verbose and a bit heavy on the boilerplate.
The only other way I can think of to deal with this is to factor any functions like this out into separate files (modules) and just import the functions, so that everything's clean.
Any advice from more experienced Pythoners on how to deal with this? Or do you just not worry about it and get on with solving the problem?
Explicit is better than implicit.
" – Wafturetry_match
to__call__
, which lets you use it (after construction) exactly like a function. But, as in @glglgl's answer, your javascript code actually translates directly into Python. – KursksomeFunc
in the outer scope. – Pannereturn someFunc (bar) {}
spurious? also ifsomeFunc(bar)
is an actuall call, won't it cause stack overflow? – Nabalavar foo = some_expensive_initialization_operation();
is called when this block is first evaluated - note that the outer function is called with()
immediately after its closing brace. This means that as the interpreter continues, what's been assigned in the outer namespace tosomeFunc
is the innersomeFunc
function, which here takes a single argument. Since it contains a reference tofoo
,foo
is not garbage collected - this is the purpose of a 'closure'. – Panne