Assuming you want to have a separate list in the subclass, not modify the parent class's list (which seems pointless since you could just modify it in place, or put the expected values there to begin with):
class Child(Parent):
foobar = Parent.foobar + ['world']
Note that this works independently of inheritance, which is probably a good thing.
Answer from user395760 on Stack OverflowConfused about class variables, also with inheritance
How does inheritance of class variables work in Python? - Stack Overflow
why are class variables not inherited but class methods are??
Define class variable in subclass
Videos
Assuming you want to have a separate list in the subclass, not modify the parent class's list (which seems pointless since you could just modify it in place, or put the expected values there to begin with):
class Child(Parent):
foobar = Parent.foobar + ['world']
Note that this works independently of inheritance, which is probably a good thing.
You should not use mutable values in your class variables. Set such values on the instance instead, using the __init__() instance initializer:
class Parent(object):
def __init__(self):
self.foobar = ['Hello']
class Child(Parent):
def __init__(self):
super(Child, self).__init__()
self.foobar.append('world')
Otherwise what happens in that the foobar list is shared among not only the instances, but with the subclasses as well.
In any case, you'll have to avoid modifying mutables of parent classes even if you do desire to share state among instances through a mutable class variable; only assignment to a name would create a new variable:
class Parent(object):
foobar = ['Hello']
class Child(Parent):
foobar = Parent.foobar + ['world']
where a new foobar variable is created for the Child class. By using assignment, you've created a new list instance and the Parent.foobar mutable is unaffected.
Do take care with nested mutables in such cases; use the copy module to create deep copies if necessary.
I'm finding class variables super confusing. I thought they were just like static variables in C++ (which instances can't own), but it seems they have quite different behavior.
Basic Class variable behavior - is this correct?
class Foo: x: int
-
if you set
Foo.x, it overrides the value of.xfor all instances of Foo, but -
if you set
.xon an instance ofFoo, it only changes.xon that instance.
edit: actually this can't be the full story, because sometimes changing Foo.x doesn't change the instance's .x??
Class variables + inheritance, what is going on?
class Parent: x: int class Child(Parent): pass Parent.x = 1 print(Child.x) # = 1. ok so child inherits parent class variable Child.x = 2 print(Parent.x) # = 1. ok, so child cannot set parent class variable Parent.x = 3 print(Child.x) # = 2. hol' up, now child doesn't inherit from parent anymore?
Also, if multiple classes inherit from Parent, if I set Child1.x does it affect the other children? How are instances affected too?
Class variables without declaration works too...?
What's the point of defining these variables in the class body if you don't need to?
class Foo: pass Foo.x = 3
I feel like there's some kind of mental model for class variables I'm just not understanding. Is there any easy way to think about them? Also is there any other weird behavior I should know?
Any property of Dog will override a property inherited from Cat. You can re-define a value in Cat, but it won't matter because it has already been overridden by the child. For example:
class Cat:
age = 0 # Cat.age = 0
class Dog(Cat):
pass # Dog.age = Cat.age = 0
Dog.age=1 # Dog.age = 1, and Dog.age no longer points to Cat.age
Cat.age=2 # Cat.age = 2
print(Dog.age, Cat.age) # Dog.age is no longer Cat.age. They are completely different
Contrast that with this:
class Cat:
age = 0 # Cat.age = 0
class Dog(Cat):
pass # Dog.age = Cat.age = 0
Cat.age = 10 # Cat.age = 10
print(Dog.age, Cat.age) # Dog.age points to Cat.age, so Dog.age resolves to 10
Inheritance refers to defining a new class with little or no modification to an existing class. The new class is called derived (or child) class and the one from which it inherits is called the base (or parent) class. The class inheritance mechanism allows multiple base classes, a derived class can override any methods of its base class(es), and a method can call the method of a base class with the same name.
class Cat:
def __init__(self):
self.age = 2
self.sound = "meow"
class Dog(Cat):
def __init__(self):
super().__init__()
self.sound = "bark"
cat = Cat()
dog = Dog()
print(f"The cat's age is {cat.age}, and the dog's age is {dog.age}.")
print(f"Cats {cat.sound}, and dogs {dog.sound}.")
The cat's age is 2, and the dog's age is 2.
Cats meow, and dogs bark.
So, you can see the dog.age can inherit from class Cat. Notice the sound part, the method in the derived class overrides that in the base class. This is to say, we wrote the dog sound, it gets preference over the class Cat sound.
This is my understanding as of now. Correct me if I'm wrong.
class E(A, C):
def __init__(self, age, name, goal):
A.__init__(self, age) # this is just to inherit VARIABLES of A
C.__init__(self, name) # this is just to inherit VARIABLES of C
self.goal = goal
def print_var(self):
print("age:", self.age)
print("name:", self.name)
print("goal:", self.goal)
def print_method(self):
self.printa() # no need to write "A.__init__(self, age)" to inherit this method
self.printc() # methods are inherited the moment you wrote E(A, C)Here, I had to declare that I want class A and C's variables to print it. But the print_method method worked just fine without it. Any reason why it is like that? (printa and printc just prints the statement that "this is class A/C")
Shouldn't inheritance itself mean that they will INHERITE stuff? why we need to declare it again??
Python's scoping rules for barenames are very simple and straightforward: local namespace first, then (if any) outer functions in which the current one is nested, then globals, finally built-ins. That's all that ever happens when a barename is looked up, and there's no need to memorize or apply any complicated rules (nor is there any need for a Python compiler to enforce more complicated rules).
Any time you want a different lookup, you'll be using a qualified name, not a bare name. Qualified names are vastly more powerful because the lookup can always be delegated to the objects whose attributes can be requested, and those object can implement whatever lookup rules they need. In particular, in an instance method within a class, self.x is the way to ask the self object to look up attribute name 'x' -- and in that lookup it can delegate to classes, including the implementation of the concept of inheritance (and multiple inheritance, method resolution order, and so on).
The body of a class (as opposed to the bodies of the methods defined in a class) executes as part of the class statement, before the class object is created or its name is bound (in particular, before any of the bases have been defined as being bases -- though this latest detail can never matter when referring to barenames, anyway!-).
So, in your example, in class B, barename x is looked up with the universal rules -- is it a name bound locally? If no, is it bound in any outer function in which this scope is nested? If no, is it bound as a global or built-in? If none of the above, using the barename in question of course causes a name-error exception.
Since you want a different lookup sequence than the barename lookup rules universally enforce, then clearly you need to use a qualified name, not a barename; and a moment's reflection will clearly show that the "one obvious choice" for a qualified name to use for your purpose has to be A.x -- since that's where you want it to be looked up (the bases haven't been recorded anywhere yet at that point, after all... it will be the metaclass, normally type, that will do the bases-binding as part of its job when it gets called after the class body is done executing!-).
Some people are so keenly attached to other "magical" rules for the lookup of barenames that they just can't stand this aspect of Python (originally inspired, I believe, by Modula-3, a little known language that's very well considered in theoreticians' circles;-) -- having to write self.x in a method to specify that x must be looked up on self rather than using the universal barename rules, for example, drives such people batty.
Me, I love the simplicity and universality of the barename lookup rules, and I love using qualified names instead of barenames any time I want any other form of lookup... but then, it's not a secret that I'm madly in love with Python (I have my own grumbles -- e.g., global x as a statement always makes my skin crawl, where I'd much rather write global.x, i.e., have global be a built-in name for "the currently executing module"... I do love qualified names!-), is it?-)
In Python, the body of a class is executed in its own namespace before the class is created (after which, the members of that namespace become the members of the class). So when the interpreter reaches y = x+1, class B does not exist yet at that point and, therefore, has no parent.
For more details, see http://docs.python.org/reference/compound_stmts.html#class-definitions
You need to call the constructor of the parent classes manually - Here, self.text is initialize in Parent constructor which is never called:
class Child1(Parent):
def __init__ (self):
super(Child1, self).__init__ ()
# or Parent.__init__ (self)
self.x = 'x'
Since python 3.6, we can now use the __init_subclass__ function, which is called automatically before __init__ of the Child.
class Parent:
def __init__(self):
self.text = 'parent'
def __init_subclass__(self):
Parent.__init__(self)
def getText(self):
print(self.text)
class Child1(Parent): pass
class Child2(Parent): pass
classes = [Parent(), Child1(), Child2()]
for item in classes:
item.getText()
output
parent
parent
parent
If you use your Parent class more as a "interface", here is another example.
class Animal():
def __init_subclass__(self, sound):
self.sound = sound
def make_sound(self):
print(self.sound)
class Cat(Animal, sound='meow'): pass
class Dog(Animal, sound='woof'): pass
animals = [Cat(), Dog()]
for animal in animals:
animal.make_sound()
output
meow
woof