Python Forum
Python inner classes inheritance from parent class
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Python inner classes inheritance from parent class
#1
Hello,

I am really struggling to understand the inheritance in python classes. In particular, I am trying to figure out how to pass the outer class attributes to inner class. Below is a sample code:

class Numbers:
   def __init__(self,a,b):
        self.a = a
        self.b = b

    class Operations:
        def __init__(self):
            Numbers.__init__(a,b)
            self.sum = self.a + self.b
            self.prod = self.a * self.b

twoNumbers = Numbers(5,4)

print(twoNumbers.Operations.sum)
When I run the code, I am getting an error:

Traceback (most recent call last):
  File "/Users/aabedin/Downloads/test_schedule.py", line 117, in <module>
    print(twoNumbers.Operations().sum)
          ^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/aabedin/Downloads/test_schedule.py", line 111, in __init__
    Numbers.__init__(a,b)
                     ^
NameError: name 'a' is not defined
My philosophy is as follows:
I create an object from the Numbers class. Inside that class there is another class called Operations which has certain attributes, corresponding to different arithmetic operations. I would imagine that accessing the attributes of the outer class should not be a problem, if the outer class Numbers has been instantiated inside the `__init__` method of the inner class, no?
Can you please help me understand how I can access the parent attributes within the child class?

P.S I am sorry of the formatting of the code is not right, but I don't know why "Insert ode snippet" does not show the formatting.
Reply
#2
Why 2 classes?

class Numbers:
    def __init__(self,a,b):
        self.sum = a + b
        self.prod = a * b
 
twoNumbers = Numbers(5,4)
 
print(twoNumbers.sum, twoNumbers.prod)
Reply
#3
(Yesterday, 07:43 PM)Axel_Erfurt Wrote: Why 2 classes?

class Numbers:
    def __init__(self,a,b):
        self.sum = a + b
        self.prod = a * b
 
twoNumbers = Numbers(5,4)
 
print(twoNumbers.sum, twoNumbers.prod)

Thank you for the offered solution, but I am actually writing a more sophisticated code and I need to access the parent class attributes (not methods) within the child class. The snippet I posted is just an illustration of what I am trying to achieve. My actual code is very big and not suitable for posting here.
Reply
#4
I don't understand why you are defining a class inside another class. Doing so doesn't provide any kind of class relationship. Operations is not related to numbers in any way. The only thing the embedding does is force you to refer to the Numbers class to access the Operations class.
class Numbers:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    class Operations:
        def __init__(self, a, b):
            self.numbers = Numbers(a, b)
            self.sum = self.numbers.a + self.numbers.b
            self.prod = self.numbers.a * self.numbers.b

two_numbers = Numbers.Operations(5, 4)
print(two_numbers.sum, two_numbers.prod)
It actually makes more sense to flip it around.
class Operations:

    class Numbers:
        def __init__(self, a, b):
            self.a = a
            self.b = b

    def __init__(self, a, b):
        self.numbers = self.Numbers(a, b)
        self.sum = self.numbers.a + self.numbers.b
        self.prod = self.numbers.a * self.numbers.b

two_numbers = Operations(5, 4)
print(two_numbers.sum, two_numbers.prod)
Class relationships are IS A or HAS A. An "is a" relationship is where one class inherits attributes of another. This is called inheritance. The terms used to describe the rolls of the two classes are superclass and subclass, not parent and child.

A "has a" relationship is where one class has attributes that are instances of another class. Child and parent fit better with this type of relationship. Since everything in Python is an object of some class, even numbers, strings and lists, most python classes have a "has a" relationship with some other classes. Nothing special here.

In your example there is no relationship at all between the Number and Operation classes. They know nothing at all about each other. In my second example I convert this to a "has a" relationship when an Operations object has an attribute that is a Numbers object.

For completeness, below is an example of an "is a" relationship. Numbers is a class that holds two numbers. Operations is a class that inherits the number holding attributes of Numbers and adds new behaviors, computing the product and sum of those numbers.
class Numbers:
    def __init__(self, a, b):
        self.a = a
        self.b = b


class Operations(Numbers):
    def product(self):
        return self.a * self.b

    def sum(self):
        return self.a + self.b


ab = Operations(4, 5)
print(ab.product(), ab.sum())
Since you don't know how python classes work, maybe you should try describing in words, not code, what you are trying to achieve.
Reply
#5
(11 hours ago)deanhystad Wrote: I don't understand why you are defining a class inside another class. Doing so doesn't provide any kind of class relationship. Operations is not related to numbers in any way. The only thing the embedding does is force you to refer to the Numbers class to access the Operations class.
class Numbers:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    class Operations:
        def __init__(self, a, b):
            self.numbers = Numbers(a, b)
            self.sum = self.numbers.a + self.numbers.b
            self.prod = self.numbers.a * self.numbers.b

two_numbers = Numbers.Operations(5, 4)
print(two_numbers.sum, two_numbers.prod)
It actually makes more sense to flip it around.
class Operations:

    class Numbers:
        def __init__(self, a, b):
            self.a = a
            self.b = b

    def __init__(self, a, b):
        self.numbers = self.Numbers(a, b)
        self.sum = self.numbers.a + self.numbers.b
        self.prod = self.numbers.a * self.numbers.b

two_numbers = Operations(5, 4)
print(two_numbers.sum, two_numbers.prod)
Class relationships are IS A or HAS A. An "is a" relationship is where one class inherits attributes of another. This is called inheritance. The terms used to describe the rolls of the two classes are superclass and subclass, not parent and child.

A "has a" relationship is where one class has attributes that are instances of another class. Since everything in Python is an object of some class, even numbers, strings and lists, all python classes have a "has a" relationship with some other classes. Nothing special here.

In your example there is no relationship at all between the Number and Operation classes. They know nothing at all about each other. In my second example I convert this to a "has a" relationship when an Operations object has an attribute that is a Numbers object.

For completeness, below is an example of an "is a" relationship. Numbers is a class that holds two numbers. Product is a class that inherits the number holding attributes of Numbers and adds a new attribute, computing the product of those numbers.

Since you don't know how python classes work, maybe you should try describing in words, not code, what you are trying to achieve.



Pardon my ignorance on how classes and object-oriented programming works, as the only language I had previously programmed in was Fortran :) !

OK, I was able to extract an excerpt from my code (below), which doesn't work at the moment. I don't really think posting my entire code will help in any way.

import pandas as pd
import numpy as np

courseID = 'CHEM1250'

df = pd.DataFrame({'courseid':['CHEM1250', 'CHEM1250', 'CHEM1250', 'PHYS1200', 'PHYS1200', 'BIOL1150', 'BIOL1150'], \
    'coursesec':['L01', 'L02', 'L03', 'L01','L02','L01','L01'], \
    'starttime':['8:00', '12:00', 'NaN', '9:00', 'NaN', '8:00', '12:00'], \
    'endtime':['8:30', '12:30', '14:00', '10:00','12:00', '8:50', '13:50'], \
    'instructorid':['John', 'John', 'Bob', 'Jenna', 'Michel', 'Michel', 'Alice']})

class CourseSchedule:

    def __init__(self, DataFrame):
        self.df= DataFrame


    def _omit_nans(self, DataFrame):
        return DataFrame[DataFrame.notna()]


    class Course:

        def __init__(self, courseName):
            self.courseName = courseName
            self.show = self.display_schedule()

        def display_schedule(self):
            return CourseSchedule._omit_nans(df[df['courseid']==self.courseName])

schedule = CourseSchedule(df)
print(schedule.Course(courseID).show)
I am using a course schedule excel file as a DataFrame. I'd like to be able to create a single object out of the CourseSchedule class and then have different classes, constructed out of that original class. Inside each class, there will be methods, pertinent to that specific subclass. I also want to be able to define some parent class methods, so that I don't have to repeat code in each method of subclasses.
For example, using the schedule object, I'd like to have a Course class and inside it, there will be a number of methods pertinent to that Course class. The reason why I decided to go with a nested class inside the CourseSchedule class is because I want to logically and neatly group methods pertinent to that class. When I create the schedule object, I might want to do something with that Data Frame returned by schedule.Course('CHEM1250'). I think it is much cleaner if I was able to do schedule.Course('CHEM1250').show or e.g. schedule.Course('CHEM1250').take_smaller_subset and do something else with it. Similarly, inside the CourseSchedule, I'll have an Instructor class with its own methods, so I can do the following: schedule.Instructor('Bob').do_something. Hopefully, that explains what I am trying to achieve.
Reply
#6
The Zen of Python

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

It was already mentioned, but let me repeat - there is no benefit whatsoever in nesting classes like this. And this is not inheritance, nor parent/child relation, if this is what you think, based on your post title....
In my humble opinion your CourseShedule class is just a wrapper around a DataFrame and does not make much sense to have such class. It makes sense to have just Course class with all its attributes - schedule, instructor, etc. populated from a DataFrame at instantiation and respective methods.
Then hold all instances of Cource class in a list or similar structure OR create separate class, to hold instances of Course class e.g. in an attribute that is listr in itsel, but only if it provides any benefits
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Python Classes rob101 4 1,522 Feb-05-2024, 06:51 PM
Last Post: rob101
  super() and order of running method in class inheritance akbarza 7 2,428 Feb-04-2024, 09:35 AM
Last Post: Gribouillis
Question [solved] Classes, assign an attributes to a class not to instances.. SpongeB0B 4 1,890 May-20-2023, 04:08 PM
Last Post: SpongeB0B
  Understanding Python classes PythonNewbee 3 2,151 Nov-10-2022, 11:07 PM
Last Post: deanhystad
Sad Python classes PythonNewbee 4 2,107 Nov-09-2022, 01:19 PM
Last Post: deanhystad
  Child class inheritance issue eakanathan 3 2,183 Apr-21-2022, 12:03 PM
Last Post: deanhystad
  dict class override: how access parent values? Andrey 1 2,528 Mar-06-2022, 10:49 PM
Last Post: deanhystad
  Subclass initialized property used in parent class method. Is it bad coding practice? saavedra29 5 3,644 Feb-07-2022, 07:29 PM
Last Post: saavedra29
  Inheritance vs Instantiation for Python classes mr_byte31 7 5,336 Oct-14-2021, 12:58 PM
Last Post: mr_byte31
  Understanding Python super() for classes OmegaRed94 1 2,446 Jun-09-2021, 09:02 AM
Last Post: buran

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020