[Tutor] variable existence q
Steven D'Aprano
steve at pearwood.info
Sun Aug 16 11:24:15 CEST 2015
On Sat, Aug 15, 2015 at 03:38:31PM -0700, Clayton Kirkwood wrote:
> top_directory = "/users/Clayton/Pictures"
> target_directory = top_directory #directory we are checking
> filetypes = ('jpg', 'png', 'avi', 'mp4', 'mov', 'bmp')
>
> imports...
>
> def override_defaults():
> with open( user_preferences ) as f:
> for line in f.readline():
> llist = line.split()
> if llist[0] == '#': #comment line to ignore
> continue
> elif llist[0] == 'top_directory':
> if len(llist) == 1:
> pass
> else:
> top_directory = llist[1]
This line tells the compiler that top_directory must be a local
variable, since you assign to it within a function. As a local variable,
it only gets set on *some* paths through the function, so you get an
error, same as this:
def example(n):
if n % 2 == 0:
td = "test"
else:
pass
return td # fails half the time
Python uses a simple rule to decide whether or not a variable is a local
or not. If the variable is assigned to *anywhere* in the function, it is
treated as local. Even if the line is never actually executed! (For this
purpose, "del" is treated as a de facto assignment too.) So you can even
do this:
x = 23
def test():
return x
# code below here is never executed
if False:
# and even if it were, code inside this block is never executed
x = 42 # makes x a local variable
and calling test() will now give an UnboundLocalError.
To tell Python not to treat it as a local, you need to declare it
global. Same with target_directory. So one solution is to put this as
the first line of your function:
global top_directory, target_directory
(Technically, you can put it anywhere inside the function, yes, even
after the return statement, and it will have the same effect. But don't
do that. Always put it at the start.)
Another solution is to write the function like this:
def override_defaults():
top = top_directory
target = target_directory
with open( user_preferences ) as f:
for line in f: # no need for f.readlines
line = line.strip() # ignore leading and trailing whitespace
words = line.split()
if words[0].startswith('#'): #comment line to ignore
continue
elif words[0] == 'top_directory':
top = words[1]
[ ... ]
return (top, file_types, target)
--
Steve
More information about the Tutor
mailing list