Mithril
Mithril

Reputation: 13748

Why I can't assign a List Comprehensions to the list object inside it ?(Python)

After I write below code:

if isinstance(lst, (list, tuple)) and len(lst) > 0:
    lst = [v.lower() for v in lst]
    pv_on, uv_on = 'pv'in lst, 'uv' in lst

ouput error in PyCharm: NameError: name 'lst' is not defined

But if I use lst2 instead 'lst' inside [v.lower() for v in lst] as follow, it works fine.I just want to know why.

if isinstance(lst, (list, tuple)) and len(lst) > 0:
    lst2 = [v.lower() for v in lst]
    pv_on, uv_on = 'pv'in lst2, 'uv' in lst2

Update:
Maybe caused by decorator, test code:

lst = ['A', 'B', 'C']
def record_deco(lst):
    def _wrapper(func):
        def wrapper(*args,**kwargs):

            if isinstance(lst, (list, tuple)) and len(lst) > 0:
                lst = [v.lower() for v in lst]
                a_on, b_on = 'a' in lst, 'b' in lst
                print a_on
                print b_on
            return func(*args, **kwargs)
        return wrapper
    return _wrapper

@record_deco(['a'])
def a(x):
    print x


a('xxx')

This time I use sublime,the ouput error is :UnboundLocalError: local variable 'lst' referenced before assignment And this error disappear after I change lst to lst2.

Upvotes: 0

Views: 801

Answers (2)

BrenBarn
BrenBarn

Reputation: 251383

If you assign to a variable anywhere in a function, Python treats all uses of that variable in the function as local variables. Since you assign to lst in wrapper it is treated as local to wrapper. That means that when you do lst = [v.lower() for v in lst], the local variable lst already needs to exist so it can be iterated over. But no local variable lst exists, so an error is raised. You can find dozens of other questions about this by searching Stackoverflow for UnboundLocalError.

The solution, as you already found, is to use a different name for your inner variable. (In Python 3 you could use nonlocal lst to mark lst as being used from the enclosing record_deco function, but that wouldn't accomplish anything special here since you don't use lst except in the nested function.)

Upvotes: 2

James King
James King

Reputation: 6365

lst = ['A', 'B', 'C']
lst = [v.lower() for v in lst]
a_on, b_on = 'a' in lst, 'b' in lst
a_on, b_on
(True, True)

Works for me. Puzzling.

Upvotes: 2

Related Questions