Inheritance and base class method call python - python

I would like a method in a base class to call another method in the same class instead of the overriding method in an inherited class.
I would like the following code to print out
Class B: 6
Class A: 9
Can this be done?
# Base class definition
class ClassA(object):
def __init__(self):
print("Initializing A")
# hoping that this function is called by this class's printFnX
def fnX(self, x):
return x**2
def printFnX(self, x):
print("ClassA:",self.fnX(x))
# Inherits from ClassA above
class ClassB(ClassA):
def __init__(self):
print("initizlizing B")
def fnX(self, x):
return 2*x
def printFnX(self, x):
print("ClassB:", self.fnX(x))
ClassA.printFnX(self,x)
bx = ClassB()
bx.printFnX(3)

Congratulations, you've discovered the motivating use case for Python's double-underscore name mangling :-)
For the details and a worked-out example see: http://docs.python.org/tutorial/classes.html#private-variables and at http://docs.python.org/reference/expressions.html#atom-identifiers .
Here's how to use it for your example:
# Base class definition
class ClassA(object):
def __init__(self):
print("Initializing A")
# hoping that this function is called by this class's printFnX
def fnX(self, x):
return x**2
__fnX = fnX
def printFnX(self, x):
print("ClassA:",self.__fnX(x))
# Inherits from ClassA above
class ClassB(ClassA):
def __init__(self):
print("initizlizing B")
def fnX(self, x):
return 2*x
def printFnX(self, x):
print("ClassB:", self.fnX(x))
ClassA.printFnX(self,x)
bx = ClassB()
bx.printFnX(3)
The use case is described as a way of implementing the Open-Closed Principle in "The Art of Subclassing" found at http://www.youtube.com/watch?v=yrboy25WKGo&noredirect=1 .

The same can be achieved by making fnX and printFnX both classmethods.
class ClassA(object):
def __init__(self):
print("Initializing A")
# hoping that this function is called by this class's printFnX
#classmethod
def fnX(self, x):
return x ** 2
#classmethod
def printFnX(self, x):
print("ClassA:",self.fnX(x))
class ClassB(ClassA):
def __init__(self):
print("initizlizing B")
def fnX(self, x):
return 2*x
def printFnX(self, x):
print("ClassB:", self.fnX(x))
ClassA.printFnX(x)
bx = ClassB()<br>
bx.printFnX(3)

Related

Zope.interface in Django

I am from a Java background and now working on a django application. Need your input if I am in the wrong direction.
I am trying to implement zope.interface.Interface in my Django application and trying to achieve what interfaces in Java do, but it does not throw any error if the implementer class does not provide the definition of all the methods in the interface.
Here is my sample implementation.
import zope.interface
class MyInterface(zope.interface.Interface):
x = zope.interface.Attribute("foo")
def method1(self, x):
pass
def method2(self):
pass
#zope.interface.implementer(MyInterface)
class MyClass:
def method1(self, x):
return x**2
def method2(self):
return "foo"
#zope.interface.implementer(MyInterface)
class MyClass2:
def method1(self, x):
return x**2
print(list(zope.interface.implementedBy(MyClass)))
print(list(zope.interface.implementedBy(MyClass2)))
c = MyClass()
print(c.method1(5))
print(c.method2())
d = MyClass2()
print(d.method1(5))
Kindly help me find out what am I doing wrong and your kind guidance.
Thank you,
I am going with MetaClass instead of Zope Interface. Here is the solution
class IStudent(type):
def __new__(cls, name, bases, attrs):
print("New from Interface")
x = super().__new__(cls, name, bases, attrs)
# Functions to be implemented
if(not hasattr(x, 'test')):
x.test = lambda self: print("Method not implemented")
return x
class Student1(metaclass=IStudent):
def __init__(self):
print("Init from Student1")
class Student2(metaclass=IStudent):
def __init__(self):
print("Init from Student2")
def test(self):
print("This is implemented method from Student 2")
std1 = Student1()
std2 = Student2()
std1.test()
std2.test()

Redefining methods through class inheritance in Python

I'm playing around with class inheritance and I'm wondering if its possible to change aspects of an inherited method in the child class without having to rewrite the whole thing?
For example:
class Parent:
def _init_(self, x):
self.x = x
def foo(self):
a = self.x
if a > 0:
forward = True
elif a < 0:
forward = False
return forward
class Child1(Parent):
def foo(self, y=None, bool=False):
if bool:
a = y
else:
a = self.x
super().foo()
class Child2(Parent):
pass
What I'm looking for is if I called Child1.foo it could reassign the variable a before running through
the method, as defined in the parent class. Where a is dependent on the y and bool arguments passed through the rewritten method in Child1:
print(Child1(2).foo(-2, True))
# => False
print(Child1(2).foo())
# => True
print(Child2(2).foo())
# => True
Is this possible, or would I just have to rewrite a new method for each class?
I think I understand your problem and I have some suggestions for how you can resolve this:
Using "private" methods
For example:
class Parent:
def __init__(self, x):
self.x = x
def _foo(self, a=None):
a = a if a else self.x * 2
if a > 10:
over = True
else:
over = False
return over
def foo(self):
return self._foo()
class Child1(Parent):
def foo(self, y=None, condition=False):
if condition:
a = y*2
else:
a = self.x*2
return self._foo(a)
class Child2(Parent):
pass
In this example, all child classes will inherit the _foo "private" function, where they may or may not receive a value of a.
Using abstract classes
There is another solution to this problem with abstract classes (here is an example of how to do this), where you forces the child class to implement the function foo:
Important
Remembering that in the case of abstract classes, if you do not define the function decorated with #abstractmethod, you will receive an error similar to this TypeError: Can't instantiate abstract class Child2 with abstract methods foo
Example:
Python 2.x
from abc import ABCMeta, abstractmethod
class Parent:
__metaclass__ = ABCMeta
def __init__(self, x):
self.x = x
def _foo(self, a=None):
a = a if a else self.x * 2
if a > 10:
over = True
else:
over = False
return over
#abc.abstractmethod
def foo(self):
pass
class Child1(Parent):
def foo(self, y=None, condition=False):
if condition:
a = y*2
else:
a = self.x*2
return self._foo(a)
class Child2(Parent):
def foo(self):
return self._foo()
Python 3.x
class Parent(metaclass=ABCMeta):
def __init__(self, x):
self.x = x
def _foo(self, a=None):
a = a if a else self.x * 2
if a > 10:
over = True
else:
over = False
return over
#abc.abstractmethod
def foo(self):
pass
class Child1(Parent):
def foo(self, y=None, condition=False):
if condition:
a = y*2
else:
a = self.x*2
return self._foo(a)
class Child2(Parent):
def foo(self):
return self._foo()
In both examples you will have the same result by running this:
print(Child1(2).foo(10, True)) // True
print(Child1(2).foo()) // False
print(Child2(2).foo()) // False

Can i divide my class(parent)addition answer in class(child)?

class a:
def __init__(self,x):
self.x=x
def __str__(self):
return 'addition is(%d)'%(self.x)
def __add__(self,other):
c=self.x+other.x
return a(self.x+other.x)
a1=a(2)`enter code here`
a2=a(5)
c=a1+a2
print(c)
class b(a):
can i divide my parent class addition answer(c)=7 in class b and how ?
I am still not really sure what you are looking for, but it sounds like you want a child class of a named b, which can do division. Here is what that would look like:
class a:
def __init__(self,x):
self.x=x
def __str__(self):
return string(self.x)
def __add__(self,other):
c=self.x+other.x
return a(self.x+other.x)
class b(a):
def __init__(self,x):
a.__init__(self, x)
def __div__(self, other):
return self.x/other.x
a1 = a(2)
a2 = a(5)
a3 = a1+a2
print(a3)
#7
a4 = b(21)
print(a4/a3)
#3
You need a call to initiate the super class to use it in a subclass, which is what
def __init__(self,x):
a.__init__(self, x)
does. Once you have that, you can access all the superclass functions and fields, along with functions and fields defined for the subclass.

Why we using super() when inherit is already enough

I saw an example that is about super();
class Class1:
def __init__(self):
pass
def name(self):
return "My name is"
class Class2(Class1):
def __init__(self):
pass
def name(self):
return super(Class2, self).name() + " Tom"
#now lets call the object.
b = Class2()
print(b.name())
#Output is 'My name is Tom'
Here is another version of this one without super() that I made on the above codes;
class Class1:
def __init__(self):
pass
def name(self):
return "My name is"
a = Class1()
class Class2(Class1):
def __init__(self):
pass
def name(self):
return a.name() + " Tom"
b = Class2()
print(b.name())
Output is same. So while we can inherit the abilites from Class1, we can use that abilities already. Then why we need super() ?
Because you're using the wrong example. Try to do this without super():
class Base:
def __init__(self, x):
self.x = x
def square(self):
return self.x**2
class Derived(Base):
def __init__(self, x, y):
super().__init__(x)
self.y = y
def square(self):
return super().square() + self.y**2
class CubeMixin(Base):
def square(self):
return self.x**3
class MultiplyDerived(Derived, CubeMixin):
pass
Edited to use multiple inheritance, per chepner in the comments.
When Derived calls super().square(), it gets CubeMixin.square(), rather than Base.square(). If it hadn't used super(), there would be no way for it to know that CubeMixin.square() even existed.
What you did here is called composition, although you missed it by a little.
For large codebase it's generally considered a better approach, because it alleviates issues with debugging. Imagine you had a class that inherited a class which inherited a class... After a while it tends to get hard to keep up. Proper example of a composition would be:
class a(object):
def __init__(self, a):
self.a = a
class b(object):
def __init__(self, b):
self.b = b
class rect(object):
def __init__(self, x, y):
self.a = a(x)
self.b = b(y)
Which seems a bit silly for something stupid, but has pretty much the same uses as inheritance. Additionally, it may take a bit more code (a decorator) to make the class instances not behave like objects so you don't bother the end user.
Get a better example, and comparison composition vs inheritance Here

Python Decorators and inheritance

Help a guy out. Can't seem to get a decorator to work with inheritance. Broke it down to the simplest little example in my scratch workspace. Still can't seem to get it working.
class bar(object):
def __init__(self):
self.val = 4
def setVal(self,x):
self.val = x
def decor(self, func):
def increment(self, x):
return func( self, x ) + self.val
return increment
class foo(bar):
def __init__(self):
bar.__init__(self)
#decor
def add(self, x):
return x
Oops, name "decor" is not defined.
Okay, how about #bar.decor? TypeError: unbound method "decor" must be called with a bar instance as first argument (got function instance instead)
Ok, how about #self.decor? Name "self" is not defined.
Ok, how about #foo.decor?! Name "foo" is not defined.
AaaaAAaAaaaarrrrgggg... What am I doing wrong?
Define decor as a static method and use the form #bar.decor:
class bar(object):
def __init__(self):
self.val = 4
def setVal(self,x):
self.val = x
#staticmethod
def decor(func):
def increment(self, x):
return func(self, x) + self.val
return increment
class foo(bar):
def __init__(self):
bar.__init__(self)
#bar.decor
def add(self, x):
return x
I know the question has been asked 11 years ago ...
I had the same problem, here is my solution to use an inherited private decorator :
class foo:
def __bar(func):
def wrapper(self):
print('beginning')
func(self)
print('end')
return wrapper
class baz(foo):
def __init__(self):
self.quux = 'middle'
#foo._foo__bar
def qux(self):
print(self.quux)
a = baz()
a.qux()
The output is :
beginning
middle
end

Categories