Reputation: 633
I've made a lot of research on the net but I didn't find the correct way to extend "class" attributes dictionary with new values in a subclass. Most of the documentation are extending attributes inside methods.
I tried dictionary.update()
but it doesn't work.
This is my example:
class Super(object):
dictionary = {'one':1, 'two':2}
def __init__(self, var):
self.var = var
def supermethod(self):
pass
And I extended it to:
class Subclass(Super):
dictionary.update({"zero":0})
def __init__(self, var):
super(Subclass, self).__init__(var)
self.var = var
def submethod(self):
pass
If I override dictionary - it works fine. But If I try to extend, it gives me:
AttributeError: 'Subclass' object has no attribute 'dictionary'
Upvotes: 15
Views: 30139
Reputation: 31684
Subclasses do have their superclasses' attributes as their attributes.
You can not use directionay.update({"zero":0})
because at that time class Subclass
still not exist.
If you do not do line1 & line2, you can still see line4 print {'one':1, 'two':2}
which prove it.
But if you do line1 & line2, you had to add copy()
, otherwise, you will see line3 & line4 both becomes {'zero': 0, 'two': 2, 'one': 1}
, which means you want to extend parameters in subclass, but you also modify the parameters in superclass, it is not reasonable.
So following code will just output:
{'two': 2, 'one': 1}
{'zero': 0, 'two': 2, 'one': 1}
Which I think meet your requirements.
class Super(object):
dictionary = {'one':1, 'two':2}
def __init__(self, var):
self.var = var
def supermethod(self):
pass
class Subclass(Super):
dictionary = Super.dictionary.copy() # line1
dictionary.update({"zero":0}) # line2
def __init__(self, var):
super(Subclass, self).__init__(var)
self.var = var
def submethod(self):
pass
print(Super.dictionary) # line3
print(Subclass.dictionary) # line4
Upvotes: 5
Reputation: 77952
In Python, class
is an executable statement. When the interpreter finds a class
statement, then first all the code in the class
statement block is executed (in a special namespace), then all names defined in that block are used to build the class
object (Python classes are objects), and finally the class name is bound to the class object in the current scope.
IOW, within the class statement's block, the class
object doesn't exist yet and as a consequence it cannot be referenced, neither explicitly (by the class name) nor implicitly (Python overly flavors explicit over implicit anyway).
OTHO, the parent class object does exists at this point obviously (else you could not inherit from it), so you can explicitly reference it:
class Parent(object):
attr = something()
class Child(Parent):
attr = Parent.attr
# do something with Parent.attr
Note that attributes defined in the class statement block (here attr
) are "class attributes", IOW attributes of the class
object, and as such are shared amongst instances. When this attribute is a mutable object, mutating it from one instance will affect all instances.
Also remember that Python never implicitly copy anything, so the code below:
class Parent(object):
attr = {"foo": "bar"}
class Child(Parent):
attr = Parent.attr
attr["baaz"] = "quux"
# or attr.update(baaz="quux") etc
WILL update Parent.attr
.
Upvotes: 15
Reputation: 799580
Subclasses never have their superclasses' attributes as their attributes, whether methods or not.
class Subclass(Super):
dictionary = Super.dictionary
dictionary.update({zero:0})
Upvotes: 4