简体   繁体   中英

Python Variables with Inconsistent Scope

New to python and I found some weird (as a non-python dev) behavior in the way it handles scopes.

I have a code that parses arguments and uses them via argparser.

Shortened basic version of what I am doing:

import ...

def parser():
    parser = argparse.ArgumentParser(description='Do stuff')
    parser.add_argument('-key', dest='key', action='store', required=True)
    parser.add_argument('-start_date', dest='start_date', action='store', required=True)
    parser.add_argument('-end_date', dest='end_date', action='store')
    return parser.parse_args()

args = get_parser()
client_id = args.key
distance_in_meters = 5000

sdate = args.start_date
start_date = datetime(int(sdate[0:4]),int(sdate[4:6]),int(sdate[6:8]),int(sdate[8:10]))
end_date = datetime(datetime.now().year,datetime.now().month,datetime.now().day,datetime.now().hour,datetime.now().minute)
if args.end_date:
    end_date = datetime(int(args.end_date[0:4]),int(args.end_date[4:6]),int(args.end_date[6:8]),int(args.end_date[8:10]))

def search():
    # print example for the sake of stack overflow
    print "Kicking off search."
    print "Client ID:", client_id
    print "Distance in Meters:", distance_in_meters
    print "Start Date:", start_date

    ...

search()

This will print everything before erroring out on print "Start Date:", start_date which is caused by UnboundLocalError: local variable 'start_date' referenced before assignment

This would normally make sense to me since I didn't set any global variables however,

  • why was it able to print the other variables?
  • why does changing the variable to sdate instead of start_date work?

I know that it is able to be printed because if I move

sdate = args.start_date
start_date = datetime(int(sdate[0:4]),int(sdate[4:6]),int(sdate[6:8]),int(sdate[8:10]))

and put it inside search(): it will print.

Based on this question: " What is the scope of variables in JavaScript? " my code should work fine.

UPDATE

I think start_date / end_date might be reserved variables?

I thought maybe the start_date in my parser() was somehow the conflicting variable. So I changed start_date = ... to start_date1 = ... and magically print "Start Date:", start_date1 seems to work.

However, I decided if that doesn't work then key (which is in the parser) should NOT work either. So I changed the code start_date1 = ... to key = ... and surprisingly `print "Start Date:", key" still works.

So I figured out a solution but I am still confused. I don't see start_date on the list of reserved variables for python.

start_date is definitely not a reserved variable in Python.

The issue is almost certainly hidden in the area of code that you've omitted:

def search():
    # print example for the sake of stack overflow
    print "Kicking off search."
    print "Client ID:", client_id
    print "Distance in Meters:", distance_in_meters
    print "Start Date:", start_date

    ... #<- This bit

You are almost certainly going to have an assignment to start_date somewhere in the omitted code. If you assign a value to a variable name somewhere in a function, you cannot access a global variable of the same name, even before the assignment. See this SO post for more details.

For an illustration of this issue, try the following:

>>> s = 1
>>> def f():
...     print s
>>> print f()
1

>>> s = 1
>>> def g():
...     print s
...     s = 2
>>> print g()
Traceback (most recent call last):

UnboundLocalError: local variable 's' referenced before assignment

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM