POV
POV

Reputation: 12005

Static variable in Python set value from another class?

I have class in file api.py that contains property:

class API(object):
    api_key = ''
    def add_advert(self):
        print(self.api_key)

In another class I use import class above:

import api
api = api.API()

Then in class I try to write value into property api_key:

api.api_key = 'NEW VALUE'

So, when I call another method from api class:

api.add_advert()

It does not return me new value for api_key:

def add_advert(self):
    print(self.api_key) 

My final code is:

import controller.api

apiClass = controller.api.API()

When I try to set:

apiClass.api_key = 'NEW VALUE'

It gives me :

'NoneType' object has no attribute 'api_key'

Upvotes: 0

Views: 534

Answers (2)

Ondrej K.
Ondrej K.

Reputation: 9664

There seems to be a bit of confusion. Actually in its most recent form if you run:

>>> from api import API
>>> myapi = API()
>>> myapi.add_advert()

>>> myapi.api_key='xxx'
>>> myapi.add_advert()
xxx

Which sounds like what you wanted. So was there just a typo? Or is there a bit missing in the question?


To the wider question. No, there isn't a static class attribute (or variable) as such... but behavior of mutable objects sort of gives you that behavior known from other languages (and occasionally confuses heck out of people when they accidentally stumble upon it). With:

class C:
    mutable_attr = []

You can try:

>>> c1 = C()
>>> c2 = C()
>>> c1.mutable_attr.append('foo')
>>> c2.mutable_attr
['foo']

Indeed they all refer to the same object (instance of list).

>>> c1.mutable_attr is c2.mutable_attr is C.mutable_attr
True

However, assign directly to an attribute (instead of manipulating that object), the "magic" is gone:

>>> c1.mutable_attr = ['bar']
>>> c2.mutable_attr
['foo']

This is tangential, but even more fun with functions. If you use mutable type as a default value, it's assigned to a variable when the function is defined (not called) and every time you call it falling back to that default, it's still that one object:

def f(x=[]):
    x.append(1)
    print(x)

And then:

>>> f()
[1]
>>> f(['a'])
['a', 1]
>>> f()
[1, 1]  # back to the original (default) object for appending

In all honesty. You better avoid either... because it really can get confusing and surprising esp. when someone else gets to work on your code. It essentially breaks encapsulation of your object and impact of change goes beyond what is immediately obvious. A linter will flag it as a problem too. ;)

Upvotes: 2

Yang K
Yang K

Reputation: 437

First of all, don't make your variable name shadow the import name of your file. Change the api variable to something different like api_var. Then, Use api_var.api_key or if you import the API class, API.api_key. You need to refer to either the instance or the class to get the class/static variable. Python doesn't magically know what namespace you're referring to.

Upvotes: 0

Related Questions