python mark a class method that must be overwritten at init [duplicate] - python

Suppose I have a base class with unimplemented methods as follows:
class Polygon():
def __init__(self):
pass
def perimeter(self):
pass
def area(self):
pass
Now, let's say one of my colleagues uses the Polygon class to create a subclass as follows:
import math
class Circle(Polygon):
def __init__(self, radius):
self.radius = radius
def perimeter(self):
return 2 * math.pi * self.radius
(H/Sh)e has forgotten to implement the area() method.
How can I force the subclass to implement the parent's area() method?

this could be your parent class:
class Polygon():
def __init__(self):
raise NotImplementedError
def perimeter(self):
raise NotImplementedError
def area(self):
raise NotImplementedError
although the problem will be spotted at runtime only, when one of the instances of the child classes tries to call one of these methods.
a different version is to use abc.abstractmethod.
from abc import ABC, abstractmethod
import math
class Polygon(ABC):
#abstractmethod
def __init__(self):
pass
#abstractmethod
def perimeter(self):
pass
#abstractmethod
def area(self):
pass
class Circle(Polygon):
def __init__(self, radius):
self.radius = radius
def perimeter(self):
return 2 * math.pi * self.radius
# def area(self):
# return math.pi * self.radius**2
c = Circle(9.0)
# TypeError: Can't instantiate abstract class Circle
# with abstract methods area
you will not be able to instantiate a Circle without it having all the methods implemented.
this is the python 3 syntax; in python 2 you'd need to
class Polygon(object):
__metaclass__ = ABCMeta
also note that for the binary special functions __eq__(), __lt__(), __add__(), ... it is better to return NotImplemented instead of raising NotImplementedError.

You can raise NotImplementedError exception in base class method.
class Polygon:
def area(self):
raise NotImplementedError
Also you can use #abc.abstractmethod, but then you need to declare metaclass to be abc.ABCMeta, which would make your class abstract. More about abc module

That's exactly what NotImplementedError are used for :)
In your base class
def area(self):
raise NotImplementedError("Hey, Don't forget to implement the area!")

Related

Difference between #staticmethod and a function inside a method

Which are the differences or advantages of Circle1 and Circle2? Is there a more correct way than the other? The only advantage is that in Circle2 I can inherit it?
class Geometry(object):
def __init__(self, x, y):
self.ptsx = x
self.ptsy = y
class Circle1(Geometry):
def __init__(self, radius):
self.radius = radius
def area(self):
def circle_formula(radius):
return 3.14*radius
return circle_formula(self.radius)
class Circle2(Geometry):
def __init__(self, radius):
self.radius = radius
def area(self):
return self.circle_formula(self.radius)
#staticmethod
def circle_formula(radius):
return 3.14*radius
I know that the correct way would be that the #staticmethod of Cicle2 would be a function like area_formula and when inheriting it, rewrite it. But my doubt is, if I really have to use an auxiliary function that only is going to live inside a specific class, what is the most correct way to implement it?
The main difference between those two classes, is that, if you add staticmethod to a method, you can access to that method without instantiating the class.
I mean, I could do: Circle2.circle_formula(2).
In Circle1, you should instantiate the class to access to the method to calculate the area;
my_circle = Circle1(2)
my_circle.area()
But, in the case that you are presenting, I would add the logic inside the area method, as the Circle1 is implemented, without using a function inside of it. Like this:
class Circle1(Geometry):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14*radius

How to implement a constructor for an abstract base class?

I am trying to write a base abstract class that has some properties that will be initialized using a constructor. So far I have this:
from abc import ABC, abstractmethod
class A(ABC):
def __init__(self, n, *params):
self.n = n
self.initialize_params(*params) #I want to do this in all subsclasses of A
def initialize_params(self, *params)
pass
#abstractmethod
def do(self):
pass
class B(A):
def __init__(self, m, n, *super_params):
self.m = m
super(A, self).__init__(n, *super_params)
def do(self):
print("this is B")
But this will throw TypeError because of instantiation of A in __init__ of B. What is the correct way of doing this?
You seem to have a couple of mistakes:
from abc import ABC, abstractmethod
class A(ABC):
def __init__(self, n, *params):
self.n = n
self.initialize_params(*params) #I want to do this in all subsclasses of A
def initialize_params(self, *params):
pass
#abstractmethod
def do(self):
pass
class B(A):
def __init__(self, m, n, *super_params):
self.m = m
super().__init__(n, *super_params) # correct way to use super() to call init
def do(self):
print("this is B")
b = B(1,2)
b.do()
Note that you missed self. infront of initialize_params() and you didn't seem to be using super() correctly.

How to define a method in class that inherits from Abstract Base Class

I have two abstract Classes with two methods: getArea(width, height) and getPerimeter(width, height). Those methods are abstract too, so they can be (or not) implemented in a derived class (In my case they must be implemented). In C# I could write IRectangle.getArea(){} or IParallelogram.getPerimeter(){} and simply make implementation. How can I do this in Python? I think that I have to use something like super(IRectangle, self).getArea() but I am not sure how.
from abc import ABC, abstractmethod
class IRectangle(ABC):
#abstractmethod
def getArea(width, height):
pass
#abstractmethod
def getPerimeter(width, height):
pass
class IParallelogram(ABC):
#abstractmethod
def getArea(parHeight, parBase):
pass
#abstractmethod
def getPerimeter(parHeight, parBase):
pass
class Calculate (IParallelogram, IRectangle):
You would just make a class that inherits from the abstract class and overrides the abstract methods like you would write a regular method.
class A(ABC):
#abstractmethod
def f(self):
pass
class B(A):
def f(self):
print ('hello')
If you want to override it but make it do nothing:
class B(A):
def f(self):
pass
Your class hierarchy is upside down. First, you would define a more generic class like Shape as the (abstract) root of the hierarchy.
class Shape(ABC):
#abstractmethod
def getArea(self):
pass
#abstractmethod
def getPerimeter(self):
pass
Then, the concrete classes IRectangle and IParallelogram would implement getArea and getPerimeter appropriately.
class IRectangle(Shape):
def getArea(self):
...
def getPerimeter(self):
...
class IParallelogram:
def getArea(self):
...
def getPerimeter(self):
...

Force child class to override parent's methods

Suppose I have a base class with unimplemented methods as follows:
class Polygon():
def __init__(self):
pass
def perimeter(self):
pass
def area(self):
pass
Now, let's say one of my colleagues uses the Polygon class to create a subclass as follows:
import math
class Circle(Polygon):
def __init__(self, radius):
self.radius = radius
def perimeter(self):
return 2 * math.pi * self.radius
(H/Sh)e has forgotten to implement the area() method.
How can I force the subclass to implement the parent's area() method?
this could be your parent class:
class Polygon():
def __init__(self):
raise NotImplementedError
def perimeter(self):
raise NotImplementedError
def area(self):
raise NotImplementedError
although the problem will be spotted at runtime only, when one of the instances of the child classes tries to call one of these methods.
a different version is to use abc.abstractmethod.
from abc import ABC, abstractmethod
import math
class Polygon(ABC):
#abstractmethod
def __init__(self):
pass
#abstractmethod
def perimeter(self):
pass
#abstractmethod
def area(self):
pass
class Circle(Polygon):
def __init__(self, radius):
self.radius = radius
def perimeter(self):
return 2 * math.pi * self.radius
# def area(self):
# return math.pi * self.radius**2
c = Circle(9.0)
# TypeError: Can't instantiate abstract class Circle
# with abstract methods area
you will not be able to instantiate a Circle without it having all the methods implemented.
this is the python 3 syntax; in python 2 you'd need to
class Polygon(object):
__metaclass__ = ABCMeta
also note that for the binary special functions __eq__(), __lt__(), __add__(), ... it is better to return NotImplemented instead of raising NotImplementedError.
You can raise NotImplementedError exception in base class method.
class Polygon:
def area(self):
raise NotImplementedError
Also you can use #abc.abstractmethod, but then you need to declare metaclass to be abc.ABCMeta, which would make your class abstract. More about abc module
That's exactly what NotImplementedError are used for :)
In your base class
def area(self):
raise NotImplementedError("Hey, Don't forget to implement the area!")

Can't figure out why #property doesn't work

The following code doesn't work properly. setlen isn't called from this line a.length=10
class A():
def __init__(self,length=0):
self._length=length
self._area=length**2
#property
def area(self):
return self._area
def getlen(self):
return self._length
def setlen(self,x):
self._length=x
self.area=x**2
length=property(getlen, setlen)
a=A()
a.length=10
print a.area
You're on Python 2.x. Classes need to inherit from object, directly or through the inheritance chain, for most of the newer features of the class system to work properly.
Not sure why you're using the decorator form one time and not the other. Better to use it both times:
class A(object):
def __init__(self,length=0):
self._length=length
self._area=length**2
#property
def area(self):
return self._area
#property
def length(self):
return self._length
#length.setter
def setlen(self,x):
self._length=x
self.area=x**2
Although as user2357112 says, the root of the problem is that you are not inheriting from object.

Categories

Resources