[Python-projects] Variables defined in "if" statements
Maarten ter Huurne
maarten at treewalker.org
Sat Feb 21 19:54:20 CET 2009
On Saturday 21 February 2009, Mads Kiilerich wrote:
> Yes, a warning for conditionally defined variables would be useful.
> (However, conditionally defined variables is bad programming style
> anyway (IMHO), so if a variable only is defined with a value in one
> branch and not in the other (and used later outside the branch) then the
> variable should be set to None before the branch. That would be how I
> would remove such a warning. And that might leave the program just as
> wrong as before, just without a warning ...)
So issue a warning for the definition instead of the use of the variable?
That could be an option. The warning should only be issued if the variable
is used after the branch though:
def f(x):
a = x + 1
if x:
b = g(x)
a = b if b else x
return a
In this example "b" is defined inside an "if" branch, but because it is not
used afterwards there is no problem.
But what is the usage is also conditional?
def f(x, y):
if x < y:
a = x
b = x * x
if b < y:
return a
else:
return b
If x and y are integers, the code above will never use "a" when it is not
defined. However, figuring that out is too much to expect from an automated
checker. Or for a human checker who is not very alert, for that matter. So I
think it deserves a warning anyway.
> Regarding checking for actual use of undefined variables ... Obviously
> there are some constructs where it can't be statically decided if a
> undeclared variable is used, but just as obviously it is possible to
> write an "automatic" checker for any given case where it
> should/shouldn't have warned about use of undeclared variables. I think
> the current implementation is a fair tradeoff between correctness and
> complexity/speed, but it would also be very nice with a more correct
> check.
My guess is that the current implementation is more likely a compromise
based on the limited amount of time the developers could spend on writing
the checkers. ;)
> I think that checking if a variable is defined is one (fundamental and
> important, but still just one) property that it could be nice if pylint
> could handle perfectly. In a perfect world it would also be able to
> trace any other properties, assertions and invariants - where full type
> inference just is a minor part ...
Some fundamental properties such as termination of an arbitrary program on a
given input are undecidable. So the perfect static code checker cannot even
exist in theory.
Let's assume we have a function that can perfectly check whether a variable
is initialized or not:
init(P, I, V) = when running program P on input I, does P initialize the
variable named V if it terminates?
Now create the following program Q:
def init(P, I, V):
# ...implementation of init()...
if not init(input, input, 'a'):
a = 83
And run Q with itself as input. Whatever init() says program Q will do
regarding initialization of "a", it does the opposite. It is only possible
to implement init() such that it does not terminate on certain input, which
would be correct but would also make it a useless as a static code checker.
In Java, the situation where a given algorithm cannot guarantee that a
variable is initialized before use is considered an error in the program.
The algorithm is stated here:
http://java.sun.com/docs/books/jls/third_edition/html/defAssign.html
When programming in Java, it is pretty rare to come across a situation where
the algorithm refuses your code while the code is correct. In other words,
there are few false positives on this check. And for most of the false
positives, there exists an alternative implementation that is accepted by
the algorithm and is more readable.
Would it be useful to try and define "definite assignment" for Python?
Bye,
Maarten
More information about the Python-Projects
mailing list