Why Do Attribute References Act Like This with Python Inheritance

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



Leave a reply



Submit