python class attributes and subclassing

  • Last Update :
  • Techknowledgy :

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

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

Subclasses never have their superclasses' attributes as their attributes, whether methods or not.

class Subclass(Super):
   dictionary = Super.dictionary
dictionary.update({
   zero: 0
})

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

Suggestion : 2

A subclass “inherits” all the attributes (methods, etc) of the parent class. We can create new attributes or methods to add to the behavior of the parent We can change (“override”) some or all of the attributes or methods to change the behavior. We can also extend the behavior of the parent by using the original methods and adding a bit more.,One of the core purposes of a subclass is to change the behavior of the parent class in some useful way. We call this overriding the inherited behavior. Overriding attributes of a parent class in Python is as simple as creating a new attribute with the same name:,Remember that we have stated previously that inheritance should be used primarily to promote code re-use. It’s really meant to be used when the thing you want to build is a variation on the parent class.,If you want to be able to use your new class in all the places and in all the ways that you can use the parent, then it should inherit from the parent. But this is not the only possible choice.

class Subclass(Superclass):
   pass
class Circle(object):
   color = "red"

class NewCircle(Circle):
   color = "blue"

nc = NewCircle
print(nc.color)
blue
class Circle(object):
   ...
   def grow(self, factor = 2):
   ""
"grows the circle's diameter by factor"
""
self.diameter = self.diameter * factor
   ...

   class NewCircle(Circle):
   ...
   def grow(self, factor = 2):
   ""
"grows the area by factor..."
""
self.diameter = self.diameter * math.sqrt(2)
whenever you override a method, the interface of the new method should be
the same as the old.It should take the same parameters,
   return the same
type, and obey the same preconditions and postconditions.

If you obey this rule, you will find that any
function designed to work
with an instance of a superclass, like a Deck, will also work with
instances of subclasses like a Hand or PokerHand.If you violate this
rule, your code will collapse like(sorry) a house of cards.

   --[ThinkPython 18.10]
class Circle(object):
   color = "red"
def __init__(self, diameter):
   self.diameter = diameter
   ...
   class CircleR(Circle):
   def __init__(self, radius):
   diameter = radius * 2
Circle.__init__(self, diameter)
class Circle(object):
   ...
   def get_area(self, diameter):
   return math.pi * (diameter / 2.0) ** 2

class CircleR2(Circle):
   ...
   def get_area(self):
   return Circle.get_area(self, self.radius * 2)

Suggestion : 3

All the attributes and methods of superclass are inherited by its subclass also. This means that an object of a subclass can access all the attributes and methods of the superclass. Moreover, subclass may have its own attributes or methods in addition to the inherited ones as well. ,The class Employee is a subclass of the class Person. Thus, Employee inherits the attributes (name and age), the method (display1()) and the constructor (__init__()) of Person. As a result, these can also be accessed by the objects of the subclass Employee.,The super() function returns a parent class object and can be used to access the attributes or methods of the parent class inside the child class.,We know that an object of a child class can access the attributes or methods of the parent class. But the reverse is not true, i.e., an object of the parent class can’t access the attributes or methods of the child class.

# superclass
class Person():
   def display1(self):
   print("This is superclass")

# subclass
class Employee(Person):
   def display2(self):
   print("This is subclass")

emp = Employee() # creating object of subclass

emp.display1()
emp.display2()
# superclass
class Person():
   def display1(self):
   print("This is superclass")

# subclass
class Employee(Person):
   def display2(self):
   print("This is subclass")

p = Person() # creating object of superclass

p.display1()
p.display2()
# superclass
class Person():
   def __init__(self, per_name, per_age):
   self.name = per_name
self.age = per_age

def display1(self):
   print("In superclass method: name:", self.name, "age:", self.age)

# subclass
class Employee(Person):
   def display2(self):
   print("In subclass method: name:", self.name, "age:", self.age)

emp = Employee("John", 20) # creating object of superclass

emp.display1()
emp.display2()
print("Outside both methods: name:", emp.name, "age:", emp.age)
# superclass
class Person():
   def __init__(self, per_name, per_age):
   self.name = per_name
self.age = per_age

# subclass
class Employee(Person):
   def __init__(self, emp_name, emp_age, emp_salary):
   self.salary = emp_salary
Person.__init__(self, emp_name, emp_age)

emp = Employee("John", 20, 8000) # creating object of superclass

print("name:", emp.name, "age:", emp.age, "salary:", emp.salary)
# superclass
class Person():
   def __init__(self, per_name, per_age):
   self.name = per_name
self.age = per_age

def display1(self):
   print("name:", self.name)
print("age:", self.age)

# subclass
class Employee(Person):
   def __init__(self, emp_name, emp_age, emp_salary):
   self.salary = emp_salary
Person.__init__(self, emp_name, emp_age)

def display2(self):
   print("salary:", self.salary)
Person.display1(self)

emp = Employee("John", 20, 8000) # creating object of superclass

emp.display2()
# superclass
class Person():
   def __init__(self, per_name, per_age):
   self.name = per_name
self.age = per_age

def display1(self):
   print("name:", self.name)
print("age:", self.age)

# subclass
class Employee(Person):
   def __init__(self, emp_name, emp_age, emp_salary):
   self.salary = emp_salary
super().__init__(emp_name, emp_age)

def display2(self):
   print("salary:", self.salary)
super().display1()

emp = Employee("John", 20, 8000) # creating object of subclass

emp.display2()

Suggestion : 4

Storing constants. As class attributes can be accessed as attributes of the class itself, it’s often nice to use them for storing Class-wide, Class-specific constants. For example:,In my experience, Python class attributes are a topic that many people know something about, but few understand completely.,Let’s use a Python class example to illustrate the difference. Here, class_var is a class attribute, and i_var is an instance attribute:,I too was wrong in that it isn’t setting a “default value” for the instance attribute. Instead, it’s defining data as a class attribute with value [].

I took a deep breath and started typing. After a few lines, I had something like this:

class Service(object):
   data = []

def __init__(self, other_data):
   self.other_data = other_data
   ...

For reference, and to give you an idea of what I was going for, here’s how I amended the code:

class Service(object):

   def __init__(self, other_data):
   self.data = []
self.other_data = other_data
   ...

Let’s use a Python class example to illustrate the difference. Here, class_var is a class attribute, and i_var is an instance attribute:

class MyClass(object):
   class_var = 1

def __init__(self, i_var):
   self.i_var = i_var

Depending on the context, you may need to access a namespace using dot syntax (e.g., object.name_from_objects_namespace) or as a local variable (e.g., object_from_namespace). As a concrete example:

class MyClass(object):
   # # No need
for dot syntax
class_var = 1

def __init__(self, i_var):
   self.i_var = i_var

# # Need dot syntax as we 've left scope of class namespace
MyClass.class_var
# # 1

When you try to access an attribute from an instance of a class, it first looks at its instance namespace. If it finds the attribute, it returns the associated value. If not, it then looks in the class namespace and returns the attribute (if it’s present, throwing an error otherwise). For example:

foo = MyClass(2)

# # Finds i_var in foo 's instance namespace
foo.i_var
# # 2

# # Doesn 't find class_var in instance namespace…
# # So look 's in class namespace (MyClass.__dict__)
foo.class_var
# # 1

If a class attribute is set by accessing the class, it will override the value for all instances. For example:

foo = MyClass(2)
foo.class_var
# # 1
MyClass.class_var = 2
foo.class_var
# # 2

If a Paython class variable is set by accessing an instance, it will override the value only for that instance. This essentially overrides the class variable and turns it into an instance variable available, intuitively, only for that instance. For example:

foo = MyClass(2)
foo.class_var
# # 1
foo.class_var = 2
foo.class_var
# # 2
MyClass.class_var
# # 1

Avoided using the empty list (a mutable value) as our “default”:

class Service(object):
   data = None

def __init__(self, other_data):
   self.other_data = other_data
   ...

Storing constants. As class attributes can be accessed as attributes of the class itself, it’s often nice to use them for storing Class-wide, Class-specific constants. For example:

class Circle(object):
   pi = 3.14159

def __init__(self, radius):
   self.radius = radius

def area(self):
   return Circle.pi * self.radius * self.radius

Circle.pi
# # 3.14159

c = Circle(10)
c.pi
# # 3.14159
c.area()
# # 314.159

Defining default values. As a trivial example, we might create a bounded list (i.e., a list that can only hold a certain number of elements or fewer) and choose to have a default cap of 10 items:

class MyClass(object):
   limit = 10

def __init__(self):
   self.data = []

def item(self, i):
   return self.data[i]

def add(self, e):
   if len(self.data) >= self.limit:
   raise Exception("Too many elements")
self.data.append(e)

MyClass.limit
# # 10

We could then create instances with their own specific limits, too, by assigning to the instance’s limit attribute.

foo = MyClass()
foo.limit = 50
# # foo can now hold 50 elements— other instances can hold 10

Suggestion : 5

Classes provide a means of bundling data and functionality together. Creating a new class creates a new type of object, allowing new instances of that type to be made. Each class instance can have attributes attached to it for maintaining its state. Class instances can also have methods (defined by its class) for modifying its state.,When a class defines an __init__() method, class instantiation automatically invokes __init__() for the newly created class instance. So in this example, a new, initialized instance can be obtained by:,Generally speaking, instance variables are for data unique to each instance and class variables are for attributes and methods shared by all instances of the class:,Note that the mangling rules are designed mostly to avoid accidents; it still is possible to access or modify a variable that is considered private. This can even be useful in special circumstances, such as in the debugger.

def scope_test():
   def do_local():
   spam = "local spam"

def do_nonlocal():
   nonlocal spam
spam = "nonlocal spam"

def do_global():
   global spam
spam = "global spam"

spam = "test spam"
do_local()
print("After local assignment:", spam)
do_nonlocal()
print("After nonlocal assignment:", spam)
do_global()
print("After global assignment:", spam)

scope_test()
print("In global scope:", spam)
After local assignment: test spam
After nonlocal assignment: nonlocal spam
After global assignment: nonlocal spam
In global scope: global spam
class ClassName:
<statement-1>
   .
   .
   .
   <statement-N>
class MyClass:
   ""
"A simple example class"
""
i = 12345

def f(self):
   return 'hello world'
x = MyClass()
def __init__(self):
   self.data = []

Suggestion : 6

By Bernd Klein. Last modified: 01 Feb 2022., 19 Oct 2022 to 21 Oct 2022 , 17 Oct 2022 to 21 Oct 2022

class A:
   a = "I am a class attribute!"
x = A()
y = A()
x.a
'I am a class attribute!'
y.a
A.a
class A:
   a = "I am a class attribute!"
x = A()
y = A()
x.a = "This creates a new instance attribute for x!"
A.a = "This is changing the class attribute 'a'!"

Suggestion : 7

An instance of a class is a Python object with arbitrarily named attributes that you can bind and reference. An instance object implicitly delegates to its class the lookup of attributes not found in the instance itself. The class, in turn, may delegate the lookup to classes from which it inherits, if any.,A class has arbitrarily named attributes that you can bind and reference., A class has arbitrarily named attributes that you can bind and reference. ,You can give an instance object an arbitrary attribute by binding a value to an attribute reference. For example:

The class statement is the most common way to create a class object. class is a single-clause compound statement with the following syntax:

class classname(base - classes):
   statement(s)

You normally specify an attribute of a class object by binding a value to an identifier within the class body. For example:

class C1(object):
   x = 23
print(C1.x) # prints: 23

You can also bind or unbind class attributes outside the class body. For example:

class C2(object): pass
C2.x = 23
print(C2.x) # prints: 23

The class statement implicitly sets some class attributes. Attribute __name__ is the classname identifier string used in the class statement. Attribute __bases__ is the tuple of class objects given as the base classes in the class statement. For example, using the class C1 we just created:

print(C1.__name__, C1.__bases__)
# prints: C1 (<type 'object'>,)

However, in statements in methods defined in a class body, references to attributes of the class must use a fully qualified name, not a simple name. For example:

class C4(object):
   x = 23
def amethod(self):
   print(C4.x) # must use C4.x or self.x, not just x!

Here’s an example of a class that includes a method definition:

class C5(object):
   def hello(self):
   print('Hello')

A descriptor is any object whose class supplies a special method named __get__. Descriptors that are class attributes control the semantics of accessing and setting attributes on instances of that class. Roughly speaking, when you access an instance attribute, Python gets the attribute’s value by calling __get__ on the corresponding descriptor, if any. For example:

class Const(object): # an overriding descriptor, see later
def __init__(self, value):
   self.value = value
def __set__(self, * _): # ignore any attempt at setting
pass
def __get__(self, * _): # always
return the constant value
return self.value

class X(object):
   c = Const(23)

x = X()
print(x.c) # prints: 23
x.c = 42
print(x.c) # prints: 23

To create an instance of a class, call the class object as if it were a function. Each call returns a new instance whose type is that class:

an_instance = C5()

When a class defines or inherits a method named __init__, calling the class object implicitly executes __init__ on the new instance to perform any needed per-instance initialization. Arguments passed in the call must correspond to the parameters of __init__, except for parameter self. For example, consider:

class C6(object):
   def __init__(self, n):
   self.x = n

Here’s how you can create an instance of the C6 class:

another_instance = C6(42)

You can give an instance object an arbitrary attribute by binding a value to an attribute reference. For example:

class C7: pass
z = C7()
z.x = 23
print(z.x) # prints: 23

Creating an instance implicitly sets two instance attributes. For any instance z, z.__class__ is the class object to which z belongs, and z.__dict__ is the mapping that z uses to hold its other attributes. For example, for the instance z we just created:

print(z.__class__.__name__, z.__dict__) # prints: C7 {
   'x': 23
}

When a class defines or inherits a method named __init__, calling the class object implicitly executes __init__ on the new instance to perform any needed per-instance initialization. Arguments passed in the call must correspond to the parameters of __init__, except for parameter self. For example, consider:

class C6(object):
   def __init__(self, n):
   self.x = n

Here’s how you can create an instance of the C6 class:

another_instance = C6(42)