Rob Williscroft said:
But python has static variables.
def another( x ):
y = getattr( another, 'static', 10 )
another.static = x
return y
print another(1), another(2), another(4)
What about the following case:
def f():
f.static = getattr(f, 'static', 0)
f.static += 1
return f.static
print f(), f(), f() # prints 1 2 3
As opposed to C++, you now have a line of code that is always executed
in subsequent calls, for no good reason. This is worse than:
def f(static=[0]):
static[0] += 1
return static[0]
in the sense that you have a wasteful call ("getattr") that doesn't do
anything productive in subsequent calls. (You could change that to
f.static = getattr(f, 'static', 0) + 1, but the "getattr" is surely
inefficient compared to f.static += 1, and internally likely incurs
some conditional statement at some level.)
Maybe one can do instead:
def f():
global f
def f():
f.static += 1
return f.static
f.static = 0 # initialization
return f()
print f(), f(), f() # prints 1 2 3
The advantage is there is no more wasteful statements in subsequent
calls. No "if" conditional statement. The above is of course a toy
example to illustrate the case of a function that needs to perform
something special the first time it is called. (I am well aware of the
outside assignment like:
def f():
f.static += 1
return f.static
f.static = 0
mentioned in this thread, but I am talking about something more
general. Notice that in the latter case, f.static=0 is done before f()
is called, which may not be what one wants. E.g.: if f() is never
called, this assignment is wasteful. Not a problem in this case, for
if complicated initialization is needed, like requiring a timestamp,
it may not be a good idea.)
In code refactoring, the equivalent is to replace conditional
statements by polymorphism. In terms of codeblocks, what I mean is
dynamic hook-on and hook-off of codeblocks. If the underlying language
is powerful enough, one should be able to achieve runtime
restructuring of code, without performance impact for subsequent
calls.
regards,
Hung Jung