1

I have the following code that generates "E NameError: name 'local_func' is not defined" while class is initializing

(this is just a simplified example), what am I doing wrong?

from functools import partial

def glob_func(a, b, c, x):
    return 1000 * a + 100 * b + 10 * c + x

class MyClass:

    local_func = partial(glob_func, 3, 1, 4)

    my_list = [local_func(num)
        for num in (
            40,
            70,
            90
        )]

Note: the the below is working... why not from loop?

my_list = [local_func(40),
           local_func(70),
           local_func(90)]
Doron Levi
  • 458
  • 4
  • 16
  • class scopes don't play well with list comprehensions, because list comprehensions create a function scope but class bodies are not enclosing scopes, so local variables are not available to functions defined in the class body, just like when you use methods you cannot access class variables without referencing the class. Just use a regular for-loop. – juanpa.arrivillaga Feb 06 '20 at 07:57

3 Answers3

0

Using class is different from what you have tried here.

I hope this what you need:

from functools import partial

def glob_func(a, b, c, x):
return 1000 * a + 100 * b + 10 * c + x


local_func = partial(glob_func, 3, 1, 4)
my_list = [(local_func(num)) for num in (40,70,90)]
print my_list

Output:

[3180, 3210, 3230]
Siva Shanmugam
  • 662
  • 9
  • 19
  • Thanks, I was hoping to keep it in the class but I think there is some initialization order issue here... the strnage thing is that this works: my_list = [local_func(40), local_func(70), local_func(90)] – Doron Levi Feb 05 '20 at 15:00
0

You are getting the above error, because even though you have initialized local_func and my_list inside the class, but they are accessible yet. This may be considered analogous to function declaration and calling in Python. When you do

def sum(a, b):
  c = a + b
  return c

and you try to print c directly, it gives error that variable c cannot be found. This is because the function wasn't yet called, it was just declared. And hence the local variables of the function cannot be accessed before function call.

Similarly, your class isn't called yet (technically, instantiation). So either you access local_func as MyClass.local_func and my_list as MyClass.my_list, or you simply remove the class declaration, as indicated by @Siva

Swati Srivastava
  • 1,102
  • 1
  • 12
  • 18
  • Thanks @Swati, I added a note in the original question with a working example without loop, I can't explain, can you? why this don't work inside the loop but works outside loop? – Doron Levi Feb 05 '20 at 15:10
  • The issue is **not** that the class hasn't been called yet, the issue is that the list comprehension creates a function scope, and class bodies do not create enclosing scopes. Note, Python *doesn't have class declarations*, class definitions statements are executable code that get executed at runtime. – juanpa.arrivillaga Feb 06 '20 at 07:58
  • @juanpa.arrivillaga thanks for the valuable feedback. I'll look into it and search for better solutions to this problem. – Swati Srivastava Feb 07 '20 at 05:33
  • @DoronLevi I think the issue is as juanpa.arrivillaga specified. List comprehension is creating a function scope and class bodies do not create enclosing scopes. So the problem narrows down to a 'scope' problem. I'll soon search and try providing a solution – Swati Srivastava Feb 07 '20 at 05:35
  • @SwatiSrivastava did you see the accepted answer in the linked duplicate? It goes into **a lot of detail** and how to work around it. – juanpa.arrivillaga Feb 07 '20 at 05:58
  • @juanpa.arrivillaga Wow!! It really is a detailed answer. – Swati Srivastava Feb 07 '20 at 06:06
0

Not related to functools partial... the issue is discussed here, sorry

Accessing class variables from a list comprehension in the class definition

Doron Levi
  • 458
  • 4
  • 16