Reputation: 866
I was going through some Python code and found this code snippet
class A(object):
...
def add_commands(self, cmd):
self.commands.append(cmd)
...
class B(A):
...
def __init__(self):
self.commands = []
...
Now, because of inheritance, B will have access to the method 'add_commands'. What surprises me is that even though class A does not know about the list 'commands' this program compiles just fine forget the method execution on the object B which also turns out to be fine. The only time it errors out is when we create an object of the class A and call the method 'add_commands'. I understand that its the 'self' keyword which is saving us here. This would not be the case in a programming language like C++ as the compilation itself fails.
This brings me to my question - How should one approach inheritance in a programming language like Python? Considering the above example, is that the right way to design a class in Python?
Upvotes: 0
Views: 158
Reputation: 669
I think that the question of how to approach inheritance in Python is too broad to be answered in a single post (I'd start checking the official docs). What I would like to add is the following:
Don´t apply the exact same design principles of inheritance you would apply on a compiled language (like C++ or Java) to Python. One of the biggest strengths of Python is its flexibility (which is a dangerous, but extremely powerful tool if used correctly).
Python is not reporting any errors in the code you posted above because it is not wrong from a Python point of view (and obviously because Python is interpreted and not compiled). The pythonic way to do things is not usually what is recommended (or even possible) in other languages.
You may find yourself in a situation (as has been pointed above in the comments) where you want to define attributes in a child to be accessed from its parent methods. I tried to come up with an example with the hope that it'll be helpful.
Imagine you have two classes representing two different resources (databases, files, etc) FirstResource
and SecondResource
. Each resource has its own methods, but both of them have structural similarities that cause some methods to have the same implementation, and those operations deal with some attribute resource_attr
. The initialization logic for resource_attr
is different for each resource.
Maybe this could be an implementation option to solve this situation:
class BaseResource(object):
def common_operation_a(self):
# Use self.resource_attr to do Operation A
def common_operation_b(self):
# Use self.resource_attr to do Operation B
class FirstResource(BaseResource):
def __init__(self):
self.resource_attr = initialize_attr_for_first_resource()
# ... FirstResource specific operations
class SecondResource(BaseResource):
def __init__(self):
self.resource_attr = initialize_attr_for_second_resource()
# ... SecondResource specific methods
Then you could use this implementation as follows:
# Create resources objects
first_resource_instance = FirstResource()
second_resource_instance = SecondResource()
# The resources share the implementation of Operation A
first_resource_instance.common_operation_a()
second_resource_instance.common_operation_a()
# The following implementations are resource-specific
first_resource_instance.some_operation_c()
second_resource_instance.some_operation_d()
Upvotes: 2
Reputation: 118
Inheritance in Python uses the same paradigms as Object oriented inheritance. Being an interpreted language, there is a lot you can get away with, but that doesn't mean your classes shouldn't be designed with the same care as if you were writing compiled languages like Java and C++.
Upvotes: 1