Updating a static variable when extending a Python class
-
21-12-2019 - |
Question
I am writing an extension to a library and I would like to register my new function with a dictionary of function pointers in the base class. My understanding is that the dictionary, since it is at the uppermost scope within a class, is static and should be update-able. However, when I try to update()
the dictionary with the new function in the extended class it tells me that it is undefined. The following minimal example reproduces the error:
def somefunction1(v):
return v
def somefunction2(v):
return v
class SomeClass(object):
dictionary = {'a':somefunction1}
class SomeExtensionClass(SomeClass):
dictionary.update({'b':somefunction2})
Running it gives the following error
9
10 class SomeExtensionClass(SomeClass):
---> 11 dictionary.update({'b':somefunction2})
NameError: name 'dictionary' is not defined
Since I cannot (reasonably) modify the original SomeClass
is there any way around this?
Edit: The desired result is that SomeExtensionClass
will have dictionary={'a':somefunction1, 'b':somefunction2}
Solution
If you want to modify SomeClass.dictionary
, just refer to it as SomeClass.dictionary
:
SomeClass.dictionary.update(whatever)
Variable lookup within a class
statement doesn't look through the superclasses' attributes.
If you want a new dictionary, so SomeExtensionClass.dictionary
is different from SomeClass.dictionary
, you'll want to copy the original and update the copy:
class SomeExtensionClass(SomeClass):
dictionary = SomeClass.dictionary.copy()
dictionary.update(whatever)
OTHER TIPS
There are two reasonable ways to give SomeExtensionClass an updated dictionary:
- Update the original dictionary by referring to
SomeClass.dictionary
. - Define a second
dictionary
variable for the derived class.
You can do the second like this:
class SomeExtensionClass(SomeClass):
dictionary = dict(SomeClass.dictionary, b=somefunction2)
Which you should choose depends on who uses the dictionary and for what. If a SomeClass method uses the variable like this:
def foo(self):
a = self.dictionary['a']()
The method will use the SomeExtensionClass dictionary for SomeExtensionClass objects. If OTOH it does:
def foo(self):
a = SomeClass.dictionary['a']()
It will always use the dictionary defined in SomeClass.