Wang Nick
Wang Nick

Reputation: 495

How to use class variable within the class

for instance:

class TEST:
    test = 'a'
    def __init__(self, test=TEST.test):
        self.test=test
    def resetTest(self):
        self.test=TEST.test

Then I got following error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in TEST
NameError: name 'TEST' is not defined

How can I use class variable test within the TESTclass ?

Upvotes: 0

Views: 115

Answers (5)

Harvey
Harvey

Reputation: 5821

Class variables are accessible in local scope (no TEST. required) from method definitions, but not method bodies. So, this would be the correct way to write your example:

class TEST:
    # even for an example, this should be named something like default_test.
    test = 'a'

    def __init__(self, test=test):   # can see TEST.test without the classname
        self.test=test

    def resetTest(self):
        self.test=TEST.test          # needs the class name to see TEST.test

Some testing:

In [23]: TEST.test
Out[23]: 'a'

In [24]: t = TEST()

In [25]: t.test, TEST.test
Out[25]: ('a', 'a')

In [26]: t2 = TEST(123)

In [27]: t2.test, TEST.test, t.test
Out[27]: (123, 'a', 'a')

In [28]: t2.resetTest()

In [29]: t2.test, TEST.test, t.test
Out[29]: ('a', 'a', 'a')

Upvotes: 0

LovelyJuice
LovelyJuice

Reputation: 710

What's the meaning of the

self.test=TEST.test

I think it can not reset member variable... And you can change the two "TEST.test" to "a"

Upvotes: 0

gmoben
gmoben

Reputation: 11

Let's start with some background in order to fully understand what's happening here.

Remember that a program is just a series of commands telling a machine what to do. Programming languages give us a way to organize and reason about those commands without knowing the machine-specific implementations, but as a result need to be translated before a machine can execute them. Depending on the language, the translation can be done either all at once via a compiler or as needed via an interpreter.

Compiled languages such as C, Go, or Haskell use compilers to translate the entirety of your code beforehand and output new files with all of the translated instructions. This way the compiler, in many cases, resolve out of order references as long as they are eventually defined. Interpreted languages (or scripting languages) like Python, Bash, or Ruby use interpreters (such as the python executable) to read code piece by piece and execute each translated piece immediately without looking ahead.

In your example, the class declaration is considered one "piece" and won't be registered as a variable accessible by the interpreter until the entire class body has been parsed.

Note that your traceback points to the __init__ method of TEST:

def __init__(self, test=TEST.test):
    self.test=test

Since you're in the middle of defining the class at this point, the interpreter doesn't know about it yet, thus:

NameError: name 'TEST' is not defined

TL;DR This only happens because the interpreter is trying to resolve TEST.test immediately so it can cache whatever the default is supposed to be for the test parameter to the __init__() function declaration. So it would be perfectly safe to move the reference inside the function body itself since it won't be called until you create an instance of the class like this:

class TEST:
    test = 'a'

    def __init__(self, test=None):
        if test is not None and test != TEST.test:
            self.test = test

    def resetTest(self):
        self.test=TEST.test 

You could also put the default variable in a superclass:

class BaseTEST:
    test = 'a'

class TEST(BaseTEST):

    def __init__(self, test=BaseTEST.test):
        self.test = test

    def resetTest(self):
        self.test = BaseTEST.test

Either way it will be ugly and/or you'll have to compromise, so I'd probably go with declaring default values outside of the class instead.

Upvotes: 1

Juan T
Juan T

Reputation: 1219

There are at least two ways of doing this:

Just remove the TEST.

Instead of:

TEST.test

Put:

test

As an argument in __init__().

def __init__(self, test=test):
    self.test = test
...

Note that here you can use both, test and self.test, you probably don't want both, so just don't do self.test = test. Or...


Although the code you posted is probably just an example, in this case I would just do: def __init__(self, test='a'): ... which is what you do in almost every situation.

Upvotes: 0

caimaoy
caimaoy

Reputation: 1228

You should use it like below

class TEST:
    test = 'a'
    def __init__(self):
        pass
    def resetTest(self):
        print self.test
        print TEST.test

t = TEST()
t.resetTest()

Upvotes: 1

Related Questions