[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