0

In the python example below, methods and attributes seem to be out of scope but they still work, what is happening?

for module in output:
    a = 1
    attributes=[]
    methods=[]
    for branch in module[2]:

        for leaf in branch[2]:
            if leaf[0]=="method":
                methods.append(leaf[1]) 
            if leaf[0]=="attribute":
                attributes.append(leaf[1])
print methods
print attributes
print module[0]
print a

but if I outdent one more level it stops working

for filename in os.listdir("."):
    print filename
    fName, fExtension = os.path.splitext(filename)
    print fName, fExtension
    if fExtension == ".idl":
        f = open(filename)
        idl = f.read()
        f.close()
        output = parse(idl)
        pprint.pprint(output)
        root={}
        for module in output:
            a = 1
            attributes=[]
            methods=[]
            for branch in module[2]:
                for leaf in branch[2]:
                    if leaf[0]=="method":
                        methods.append(leaf[1]) 
                    if leaf[0]=="attribute":
                        attributes.append(leaf[1])
    print methods
    print module[0]

it says: NameError: name 'methods' is not defined I'm using python 2.7

Eduard Florinescu
  • 16,747
  • 28
  • 113
  • 179
  • 7
    Only functions, classes, methods and modules create new scopes. – Martijn Pieters Aug 14 '12 at 12:49
  • 3
    Please see this [Short Description of Python Scoping Rules](http://stackoverflow.com/questions/291978/short-description-of-python-scoping-rules) – kojiro Aug 14 '12 at 12:50
  • You could have also gone for `leaf`, try `for z in (1,2,3): print z`, then `z`. `z` is assigned and in scope! i.e. will return 3. List comprehensions on the other hand... http://stackoverflow.com/a/541958/201648 – Aaron Newton Aug 14 '12 at 13:01
  • @AaronNewton -- List comprehensions behave differently in this regard depending on python version (2.x "leaks" the loop variable into the current scope where apparently python 3.x doesn't). – mgilson Aug 14 '12 at 13:04
  • @mgilson true. I've just tested it under 2.7.3 and sure enough I get '9' `>>> i = 0 >>> [i+1 for i in range(10)] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> i 9` – Aaron Newton Aug 14 '12 at 13:08

1 Answers1

4

As indicated in the comments, for loops, while loops, if statements, etc. do not create a new scope. In fact, the only things that create a new scopes are functions, classes, modules and methods. Therefore, when you create a new variable inside a for loop, it is available outside of that loop because they share the same scope.

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • `print module[0]` isn't surprising if you take into account a few lines up: `for branch in module[2]`. It seems quite likely that `output` yields things supporting the sequence protocol (I'd put my money on tuples). – lvc Aug 14 '12 at 13:15
  • I edited with more code example were it brakes – Eduard Florinescu Aug 14 '12 at 13:16
  • 1
    @EduardFlorinescu -- This probably breaks because `fExtension == ".idl":` probably evaluates to `False`. This means that the code in the `if` statement is never executed and that variable is never added to the scope (resulting in a `NameError`). – mgilson Aug 14 '12 at 13:21
  • True. That's what happened. So we nee to be careful where the variable is defined, so practically there are other cases of scope by defining the variable in a specific condition or not. This I will keep in mind as a good practice even if the scope is overall local, don't use a variable out of the scope of a specific conditional evaluation if it was defined there. – Eduard Florinescu Aug 14 '12 at 13:29
  • @EduardFlorinescu -- Yeah. You'll sometimes see things like: `if condition: x=3 ; else: x = None` (that example is better accomplished using the ternary operator, but hopefully you get the idea). – mgilson Aug 14 '12 at 13:35
  • Yes is better with ternary because is an one-liner. Now I understood this particular situation, in case is not obvious:D I am new with python. – Eduard Florinescu Aug 14 '12 at 13:43
  • 1
    @EduardFlorinescu -- No problem. We're happy to help. Hopefully you stick with Python long enough to love it as much as I do :^) – mgilson Aug 14 '12 at 13:46
  • Its already my favourite but then there are people that say that I didn't met ruby. – Eduard Florinescu Aug 14 '12 at 13:55