Why do attribute references act like this with Python inheritance?
You are right, somedata
is shared between all instances of the class and it's subclasses, because it is created at class definition time. The lines
somedata = {}
somedata['was_false_in_base'] = False
are executed when the class is defined, i.e. when the interpreter encounters the class
statement - not when the instance is created (think static initializer blocks in Java). If an attribute does not exist in a class instance, the class object is checked for the attribute.
At class definition time, you can run arbritrary code, like this:
import sys
class Test(object):
if sys.platform == "linux2":
def hello(self):
print "Hello Linux"
else:
def hello(self):
print "Hello ~Linux"
On a Linux system, Test().hello()
will print Hello Linux
, on all other systems the other string will be printed.
In constrast, objects in __init__
are created at instantiation time and belong to the instance only (when they are assigned to self
):
class Test(object):
def __init__(self):
self.inst_var = [1, 2, 3]
Objects defined on a class object rather than instance can be useful in many cases. For instance, you might want to cache instances of your class, so that instances with the same member values can be shared (assuming they are supposed to be immutable):
class SomeClass(object):
__instances__ = {}
def __new__(cls, v1, v2, v3):
try:
return cls.__insts__[(v1, v2, v3)]
except KeyError:
return cls.__insts__.setdefault(
(v1, v2, v3),
object.__new__(cls, v1, v2, v3))
Mostly, I use data in class bodies in conjunction with metaclasses or generic factory methods.
reference instance attribute in child class
Each __init__
method should be invoking the parent's __init__
method, so that the instance is properly initialized for all the classes in the hierarchy.
class mainclass:
def __init__(self):
super().__init__()
self.mainclassvar1 = "mainclass"
class subclass(mainclass):
def __init__(self):
super().__init__()
self.subclassvar1 = "subclass"
def changeval(self):
self.subclassvar1 = "subclassedited"
class subsubclass(subclass):
def __init__(self):
super().__init__()
# Not sure why you would really need this, but...
self.subsubclassvar1 = self.subclassvar1
There's no reason, though that subsub.subclassvar1
should be related to sub.subclassvar1
, though. Calling sub.changeval()
has nothing to do with subsub
.
The inheritance of attributes using __init__
When writing the __init__
function for a class in python, you should always call the __init__
function of its superclass. We can use this to pass the relevant attributes directly to the superclass, so your code would look like this:
class Person(object):
def __init__(self, name, phone):
self.name = name
self.phone = phone
class Teenager(Person):
def __init__(self, name, phone, website):
Person.__init__(self, name, phone)
self.website=website
As others have pointed out, you could replace the line
Person.__init__(self, name, phone)
with
super(Teenager, self).__init__(name, phone)
and the code will do the same thing. This is because in python instance.method(args)
is just shorthand for Class.method(instance, args)
. If you want use super
you need to make sure that you specify object
as the base class for Person
as I have done in my code.
The python documentation has more information about how to use the super
keyword. The important thing in this case is that it tells python to look for the method __init__
in a superclass of self
that is not Teenager
Python: Inheritance of a class attribute (list)
It is not a matter of shallow or deep copies, it is a matter of references and assignments.
It the first case Unit.value
and Archer.value
are two variables which reference the same value. When you do Archer.value = 5
, you are assigning a new reference to Acher.value.
To solve your problem you need to assign a new list value to the Archer.list
.
If these values are only going to be accessed by class methods, then the simplest solution is to do the assignment when the class is initialized.
python unresolved attribute reference when using Type[class_name] instead of just class_name in type hinting
Type[A]
and A
are not the same thing! A
means an instance of A
, and Type[A]
means the type of A
-- in other words, the class itself. Mypy is correctly complaining about your attempts to access A.a
because a
is an instance attribute and you've said the function doesn't take an instance! :)
You want just:
def c(arg: A):
if isinstance(arg, B):
print(arg.b)
if isinstance(arg, D):
print(arg.d)
print(arg.a)
inheritance on class attributes (python)
Er, sounds like you want a classmethod, which not surprisingly is done with the classmethod
decorator:
class Parent(object):
class_attribute = "parent"
@classmethod
def class_method(cls):
print cls.class_attribute
class Child(Parent):
class_attribute = "child"
>>> Parent.class_method()
parent
>>> Child.class_method()
child
Or, as bgporter points out, you can do it directly with the attributes, with no need for the methods at all.
Error in attribute creation and reference Python classes multilevel inheritance
You define attribute self.totalmarks
in display()
method of Marks
class
So when you call eligible_for_reward(), totalmarks is not defined at this moment. So you can fix this by calling display() method first:
m2=Marks()
m2.dispay()
m2.eligible_for_reward()
But this won't work because self.literature
self.math
self.biology
self.physics
are not defined at this time as well.
You have to add init() method to all the classes to call super() inside and correctly instantiate the class, like this:
class Student:
def __init__(self):
self.name = input("Name: ")
self.age = input("Age: ")
self.gender = input("Gender: ")
class Test(Student):
def __init__(self):
super(Test, self).__init__()
self.stuClass = input("YearGroup/Class: ")
print("Enter the marks of the respective subjects")
self.literature = int(input("Literature: "))
self.math = int(input("Math: "))
self.biology = int(input("Biology: "))
self.physics = int(input("Physics: "))
class Marks(Test):
def __init__(self):
super(Marks, self).__init__()
self.total_marks = self.literature + self.math + self.biology + self.physics
def display(self):
print("\n\nName: ",self.name)
print("Age: ",self.age)
print("Gender: ",self.gender)
print("Class Year Group: ",self.stuClass)
print("Total Marks: ", self.literature + self.math + self.biology + self.physics)
def eligible_for_reward(self):
if self.total_marks>=90 and self.age>13:
print("You are eligible for the fabulous school sponsored trip to London")
else:
print("Sorry, you are not eligible and so are going nowhere....!")
And you can use it as follow:
marks = Marks()
marks.eligible_for_reward()
marks.display()
How to inherit and extend class attributes in Python?
Subclasses never have their superclasses' attributes as their attributes, whether methods or not.
class Subclass(Super):
dictionary = Super.dictionary
dictionary.update({zero:0})
Related Topics
Skip Multiple Iterations in Loop
Error "Importerror: Dll Load Failed: %1 Is Not a Valid Win32 Application"
How to Invoke Pandas.Rolling.Apply with Parameters from Multiple Column
Hitting Maximum Recursion Depth Using Pickle/Cpickle
Extension Method for Python Built-In Types
Intersection of Two Lists Including Duplicates
How to Tell If a String Repeats Itself in Python
Python: Dynamically Create Function at Runtime
Cancel an Already Executing Task with Celery
Numpy 'Smart' Symmetric Matrix
Can Pandas Groupby Aggregate into a List, Rather Than Sum, Mean, etc
Find and Replace Values in Xml Using Python
Python: Changing Methods and Attributes at Runtime
How to Make a Barplot and a Lineplot in the Same Seaborn Plot with Different Y Axes Nicely
How Does Keras Calculate the Accuracy
Replace Column Values in One Dataframe by Values of Another Dataframe