1
 name = 'Guido'
 
 class MyClass:
     name = 'Raymond'
     list_1 = [name] * 3
     list_2 = [name for i in range(3)]

     @classmethod
     def hello(cls):
       return '{} says hello'.format(name)

If i do this? it prints the following:

>>> print(MyClass.hello())
Guido says hello
>>> print(MyClass.list_1) 
['Raymond', 'Raymond', 'Raymond']
>>> print(MyClass.list_2)
['Guido', 'Guido', 'Guido']

My question here is,

  1. Why don't it prints 'Raymond' instead of 'Guido' on 3rd Output.
  2. How to make it print as:

    Raymond says hello

Community
  • 1
  • 1
Thirumalai vasan
  • 655
  • 2
  • 6
  • 19

1 Answers1

6

Python provides two different kinds of displays (syntax that you could informally call a literal) for defining a list.

list_1 is an "ordinary" list display, and uses the most recently bound value for name.

list_2 is defined using a list comprehension, which is implemented using an anonymous function. Now name is a free variable in that function, and so it resolves to the value of name in the nearest enclosing scope. Because a class statement does not establish a new scope, that would be the global scope, not the temporary namespace established by the class statement.

Try to avoid using class attributes as "local" variables in your class definition.

In the class method, if you want name to be the class attribute, not the global variable, you need to be explicit:

@classmethod
def hello(cls):
    return '{} says hello'.format(cls.name)
chepner
  • 497,756
  • 71
  • 530
  • 681
  • Why does this work differently when I'm in a `function`? e.g. `def func(): name='Raymond'; l1 = [name] *3; l2 = [name for _ in range(3)]; return l1, l2`, when printing `l1` and `l2` in global, they are both "Raymond"s x3. – r.ook Jan 15 '20 at 15:39
  • 1
    Functions define a new scope; a `class` statement does not. – chepner Jan 15 '20 at 15:41
  • Thanks @chepner, the inner nuances of scoping is not my strong suit. Learned something new today. Actually... now that I think of it, why *doesn't* a `class` statement define a new scope? – r.ook Jan 15 '20 at 15:43
  • 1
    A function definition just saves the body to be executed every time the function is called. A class definition, though, executes the body of the class statement *immediately*, and is discarded after the statement completes. The values computed by any code and assigned to a name are used as class attributes, but the code itself is not retained. – chepner Jan 15 '20 at 15:50
  • 1
    It is respecting that rule. The `class` statement doesn't create a scope, though, so the class attribute simply doesn't apply. The immediate scope in `list_2` is the anonymous function's local scope, and since `name` isn't defined there, it looks in the closest enclosing scope, which is the global scope (because the `class` statement doesn't define a scope). A `class` statement does define a temporary *namespace*, which is a distinct concept from *scope*. – chepner Jan 15 '20 at 16:30
  • Thanks @chepner. With your comment and the linked answer from Deepspace, I think I can understand it a bit better. It'll probably take some time for me to digest the concept but thank you. – r.ook Jan 15 '20 at 16:33