5

I am a bit puzzled why when initializing an instance of a class in Python, I cannot use class attributes. Here is the example:

class TestClass:
... shared_list = ['a', 'b', 'c']
... def __init__(self):
...     self.length = len(shared_list)

Now

>>> TestClass.shared_list
['a', 'b', 'c']

So the list exists before any instance of the class appears, but

>>> tc = TestClass()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __init__
NameError: global name 'shared_list' is not defined

Am I missing something simple?

UPD: Thanks to everyone for help and a prompt response. I've cleared up my confusion: class doesn't define a scope in Python.

3
  • 7
    You need self.shared_list or TestClass.shared_list if you want the scoped shared_list Commented Sep 30, 2016 at 14:09
  • @AChampion Thanks, putting TestClass.shared_list fixes it. Coming from C++ I still find it confusing, that within the class I need an explicit reference to the class. I thought if an attribute is not found in the instance, it will be searched for in the class, and not globally, no? Commented Sep 30, 2016 at 14:16
  • 1
    Unfortunately not, see scoping rules post above. Commented Sep 30, 2016 at 14:17

3 Answers 3

3

A class definition doesn't create a new scope for its methods, just a namespace for local variables. This is documented to some extent in Class Definition Syntax:

When a class definition is entered, a new namespace is created, and used as the local scope — thus, all assignments to local variables go into this new namespace. In particular, function definitions bind the name of the new function here.

When a class definition is left normally (via the end), a class object is created. This is basically a wrapper around the contents of the namespace created by the class definition.

That's why you need to reference the class attribute as TestClass.shared_list or self.shared_list in its method.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, that was precisely my source of confusion.
2

The problem occurs in your __init__ function, which is called when you instantiate TestClass.

The __init__ function uses the shared_list variable, but in reality this variable can only be used when tied to an instance or the base class itself. If you want to modify the shared variable, you will have to call it with the class name:

def __init__(self):
    self.length = len(TestClass.shared_list)

If you want to modify the variable only for that instance, you will have to declare it as an instance variable:

def __init__(self):
    self.not_shared_list = ['a', 'b', 'c']
    self.length = len(self.not_shared_list)

3 Comments

Note: self.share_list will reference the TestClass.shared_list and any changes to self.share_list will modify the class variable.
@AChampion Thanks--modified accordingly.
Thanks, - I've upvoted your answer, but I accepted a different one, since it happened to address exactly my source of confusion: class doesn't create a scope in Python.
1

If you do not specify the "environment" of the variable shared_list, here it's self or TestClass, python thinks it is a global variable - which is nor defined.

Use self.shared_list or TestClass.shared_list to reference it.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.