I have a parent class
class Vehicle():
def __init__(self, num_wheels=4):
self.reset_horsepower(num_wheels)
def reset_horsepower(self, num_wheels):
self.hp = num_wheels * 20
def upgrade_engine(self):
self.hp *= 2
And I want to subclass it like this:
class Car(Vehicle):
def __init__(self):
super(Car, self).__init__()
def reset_horsepower(self):
self.hp = 4 * 20
But that gives the following error:
reset_horsepower() takes 1 positional argument but 2 were given
So it seems that the call to super's __init__ is causing the old definition of reset_horsepower to be called
What's the correct way to do this?
When calculate_horsepower is called in Vehicle.__init__, self is still an instance of Car, so Car.calculate_horsepower is called, not Vehicle.calculate_horsepower.
I would recommend changing the signatures slightly. Vehicle.__init__ should take a required num_wheels argument; subclasses with 4 wheels can specify the value explicitly. Also, if you want to override calculate_horsepower but call it from the parent class, you need to preserve the function signature. I would recommend using the number of wheels in the instance, not an explicit argument.
class Vehicle:
def __init__(self, num_wheels, **kwargs):
super().__init__(**kwargs)
self.num_wheels = num_wheels
self.reset_horsepower()
def calculate_horsepower(self):
self.hp = self.num_wheels * 20
def upgrade_engine(self):
self.hp *= 2
class Car(Vehicle):
def __init__(self, **kwargs):
wheels = kwargs.get('num_wheels', 4)
super().__init__(wheels, **kwargs)
c = Car()
Car doesn't need to implement reset_horsepower, assuming that 4 in its definition is supposed to refer to the expected number of wheels on a car.
One thing I learned from writing inheritance / polymorphism code is that you should never call methods that are overridden by subclasses during construction. It should be noted that during object construction, as the name implies, means that the object is only being created currently and would only be fully constructed once the whole __init__ is done. Thus on your code, at the time super().__init__ is called, the subclass implementation isn't actually setup yet.
Some reading material I came across now was this:
https://help.semmle.com/wiki/display/PYTHON/init+method+calls+overridden+method
Quoting:
Recommendation
Do not use methods that are subclassed in the
construction of an object. For simpler cases move the initialization
into the superclass' init method, preventing it being overridden.
Additional initialization of subclass should be done in the init
method of the subclass. For more complex cases, it is advisable to use
a static method or function to manage object creation.
Based on that article, a proposed solution is:
class Vehicle():
def __init__(self, num_wheels=4):
self.super_reset_horsepower(num_wheels)
def super_reset_horsepower(self, num_wheels):
self.hp = num_wheels * 20
class Car(Vehicle):
def __init__(self):
super(Car, self).__init__()
self.sub_reset_horsepower()
def sub_reset_horsepower(self):
self.hp = 4 * 20
Related
From what I have understood so far (notice telling to me the correctness of the definition in my words): We should declare our abstract methods in the abstract class and led the implementation of those methods to the subclass or derived class.
Now I have 1 question:
is it useful or common to have instantiation in the base class(abstract class)?
Or, if not:
Should we have our instantiation in the derived class(child class) or in both?
Which one is better to do, or better to say pythonic?
Or you may say it does not matter...if that is the case notice telling me why please.
for example, this:
from abc import abstractmethod, ABC
class Athlete(ABC):
def __init__(self, name: str, mass: int, height: int, nationality: str):
self.name = name
self.mass = mass
self.height = height
self.nationality = nationality
#abstractmethod
def run(self):
pass
def play(self):
pass
def exercise(self):
pass
def sleep(self):
pass
class SoccerPlayer(Athlete):
def run(self):
print(f"{self.name} is running")
def play(self):
print(f"{self.name} with {self.height} is running to save his {self.nationality} nation.")
def exercise(self):
print(f"{self.name} is exercising to fit his {self.mass}")
def sleep(self):
print(f"{self.name} is sleeping 8 h a day to increase his {self.height}m height.")
player = SoccerPlayer('ali', 200, 180, 'american')
player.run()
For testing, it may be convenient to instantiate an abstract base class. It's also fairly simple to do. Don't do this in production code, though.
All you need to do is empty Athlete.__abstractmethods__
>>> Athlete("bob", 100, 200, "american")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Athlete with abstract methods run
>>> Athlete.__abstractmethods__
frozenset({'run'})
>>> Athlete.__abstractmethods__ = frozenset()
>>> Athlete("bob", 100, 200, "american")
<__main__.Athlete object at 0x10c9c0410>
always do the instantiation for the derived class.
because although if you do the instantiation in the base class you will inherit those attributes and methods in the derived class, but also consider this point that, you may want to override the attributes that you have instantiated in the base class(abstract class). and in that time you would need to rapidly modify your attributes in abstract class which is not a good idea.
So instantiate your attributes in the child class not the abstract class.
I have created four classes: experiment, experiment_type1, experiment_type2 and experiment_type3
experiment is an abstract class, it cannot be instantiated. It has 2 methods, __init__(self) and run(self) where run(self) is abstract.
experiment_type1 and experiment_type2 are derived from experiment. They inherit the __init__(self) from experiment (so they share the same constructor) but they implement run(self) differently from each other.
My problem is with experiment_type3 class. It also only has the run(self) method, implemented differently from experiment_type1 and experiment_type2, but its constructor takes an additional argument. Its constructor is of the form __init__(self, parameter)
Ideally I would like experiment_type3 to be derived from experiment. But there is a constructor mismatch. What is the best way to handle this? Programming in python in this case.
Edit:
This is the code for experiment and experiment_type3. As you can see it depends on self.epsilon which does not exist.
import numpy as np
from abc import ABC, abstractmethod
from Bandit import Bandit
class experiment(ABC):
def __init__(self, num_iter, bandit_list): #epsilon is the chance to explore, num_iter is num of iterations, bandit_list is the list of the bandits
self.num_iter = num_iter
self.bandit_list = bandit_list
self.best_bandit = np.random.choice(len(bandit_list))
#abstractmethod
def run(self):
raise NotImplementedError('derived class must implement run() method!')
class eg_experiment(experiment):
def run(self):
for iteration in range(self.num_iter):
bandit = np.random.choice(len(self.bandit_list))
if(np.random.random() > self.epsilon):
bandit = self.best_bandit
self.bandit_list[self.best_bandit].pull()
self.best_bandit = np.argmax([bandit.current_mean for bandit in self.bandit_list])
As the comments point out, using super() on the parent class's __init__ should give you what you want.
class A:
def __init__(self, parameter)
self.parameter = parameter
class B(A):
def __init__(self, parameter, new_parameter)
super().__init__(parameter)
self.new_parameter = parameter
or in your case
class eg_experiment(experiment):
def __init__(num_iter, bandit_list, epsilon):
super().__init__(num_iter, bandit_list) #Python3
# super(experiment,self).__init__(num_iter, bandit_list) # Pythyon2.7
self.epsilon = epsilon
There's a saying: "If your class only has two methods, and one is __init__, use a function instead." Especially here, where there is no common implementation of the run method. You just have a bunch of independent functions with similar signatures.
def run_experiment_one(num_iter, bandit_list):
...
def run_experiment_two(num_iter, bandit_list):
...
def run_experiment_three(num_iter, bandit_list, epislon):
...
class ThirdPartyA(object):
def __init__(self):
...
def ...():
...
-------------------
from xxx import ThirdPartyA
class ThirdPartyB(object):
def a(self):
...
#call to ThirdPartyA
....
def b(self):
...
#call to ThirdPartyA
...
def c(self):
...
#call to ThirdPartyA
...
-----------------------------------
from xxx import ThirdPartyA
class MyCodeA(ThirdPartyA):
def __init__(self):
# overriding code
When overriding the __init__ method of A class, how could I instruct B class that it should call MyCodeA instead of ThirdPartyA in all its methods?
The real code is here:
CLass Geoposition: ThirdPartyA
Class GeopositionField: ThirdPartyB
My override to class Geoposition so it returns max 5 decimal digits:
class AccuracyGeoposition(Geoposition):
def __init__(self, latitude, longitude):
if isinstance(latitude, float) or isinstance(latitude, int):
latitude = '{0:.5f}'.format(latitude)
if isinstance(longitude, float) or isinstance(longitude, int):
longitude = '{0:.5f}'.format(longitude)
self.latitude = Decimal(latitude)
self.longitude = Decimal(longitude)
From your updated code, I think what you're trying to do is change GeopositionField. to_python() so that it returns AccuracyGeoposition values instead of Geoposition values.
There's no way to do that directly; the code in GeopositionField explicitly says it wants to construct a Geoposition, so that's what happens.
The cleanest solution is to subclass GeopositionField as well, so you can wrap that method:
class AccuracyGeopositionField(GeopositionField):
def topython(self, value):
geo = super(AccuracyGeopositionField, self).topython(value)
return AccuracyGeoposition(geo.latitude, geo.longitude)
If creating a Geoposition and then re-wrapping the values in an AccuracyGeoposition is insufficient (because accuracy has already been lost), you might be able to pre-process things before calling the super method as well/instead. For example, if the way it deals with list is not acceptable (I realize that's not true here, but it serves as a simple example), but everything else you can just let it do its thing and wrap the result, you could do this:
class AccuracyGeopositionField(GeopositionField):
def topython(self, value):
if isinstance(value, list):
return AccuracyGeoposition(value[0], value[1])
geo = super(AccuracyGeopositionField, self).topython(value)
return AccuracyGeoposition(geo.latitude, geo.longitude)
If worst comes to worst, you may have to reimplement the entire method (maybe by copying, pasting, and modifying its code), but hopefully that will rarely come up.
There are hacky alternatives to this. For example, you could monkeypatch the module to globally replace the Geoposition class with your AccuracyGeoposition class But, while that may save some work up front, you're almost certain to be unhappy with it when you're debugging things later. Systems that are designed for aspect-oriented programming (which is basically controlled monkeypatching) are great, but trying to cram it into systems that were designed to resist it will give you headaches.
Assuming your real code works like your example—that is, every method of B creates a new A instance just to call a method on it and discard it—well, that's a very weird design, but if it makes sense for your use case, you can make it work.
The key here is that classes are first-class objects. Instead of hardcoding A, store the class you want as a member of the B instance, like this:
class B(object):
def __init__(self, aclass=A):
self.aclass = aclass
def a(self):
self.aclass().a()
Now, you just create a B instance with your subclass:
b = B(OverriddenA)
Your edited version does a different strange thing: instead of constructing a new A instance each time to call methods on it, you're calling class methods on A itself. Again, this is probably not what you want—but, if it is, you can do it:
class B(object):
def __init__(self, aclass=A):
self.aclass = aclass
def a(self):
self.aclass.a()
However, more likely you don't really want either of these. You want to take an A instance at construction time, store it, and use it repeatedly. Like this:
class B(object):
def __init__(self, ainstance):
self.ainstance = ainstance
def a(self):
self.ainstance.a()
b1 = B(A())
b2 = B(OverriddenA())
If this all seems abstract and hard to understand… well, that's because we're using meaningless names like A, B, and OverriddenA. If you tell us the actual types you're thinking about, or just plug those types in mechanically, it should make a lot more sense.
For example:
class Vehicle(object):
def move(self):
print('I am a vehicle, and I am moving')
class Operator(object):
def __init__(self, vehicle):
self.vehicle = vehicle
def move(self):
print('I am moving my vehicle')
self.vehicle.move()
class Car(object):
def move(self):
print('I am a car, and I am driving')
driver = Operator(Car())
driver.move()
I'm struggling to find a "pythonic" approach to the following class organization:
I have a base class with properties initialized in its constructor, for example:
class Animal(object):
def __init__(self, class_, species, is_domesticated):
self.class_ = class_
self.species = species
self.is_domesticated = is_domesticated
Then, when I subclass, I would like to "hard-code" one or more of these properties, like so:
class Mammal(Animal):
def __init__(self, species, is_domesticated):
Animal.__init__(self, 'Mammal', species, is_domesticated)
A Mammal is thus instantiated like so:
monkey = Mammal('Primate', false)
The problem is, I would like to use *args so as to leave any derived classes alone when altering the base class definition. Thus the definition of Mammal becomes:
class Mammal(Animal):
def __init__(self, *args):
Animal.__init(self, *(args + (class_='Mammal',)))
Which (needless to say) looks horrible. Some tips would be appreciated =)
If you only have a fixed set of arguments in the base class, there isn't much need to worry about variable arguments. Just do what you did in your first example and it's fine. If you want to be able to randomly add arguments to the base class, but add them as positional arguments and without defaults, there's no hope; you can't just change the base class willy-nilly and expect all derived classes to keep working.
However, there is a fairly common intermediate case where you might have a large set of attributes, various combinations of which may be passed to any class in the hierarchy. You might want to add new arguments to the base class, but they'll have defaults so that derived classes don't need to know about them explicitly; they'll just gracefully degrade to the base-class default. In such a case it's usually a better idea to use **kwargs rather than *args.
class Animal(object):
def __init__(self, **kwargs):
self.class_ = kwargs['class_']
self.species = kwargs['species']
# etc.
class Mammal(Animal):
def __init__(self, **kwargs):
Animal.__init__(self, class_="Mammal", **kwargs)
This requires the arguments to passed by keyword:
>>> Animal(class_='Fish', species='barracuda', is_domesticated=False)
4: <__main__.Animal object at 0x0177ABF0>
>>> Mammal(species="monkey", is_domesticated=False)
5: <__main__.Mammal object at 0x0177AFB0>
. . . but this is better if there are a lot of them, because no one will remember which order to pass them in if you have 10 different things getting passed in positionally. It also means that you can add new arguments easily; no one has to know where in the list to put the new ones, they can just add them anywhere by keyword.
In Python 2 you have to manually extract the kwargs as I did above. In Python 3 you can use keyword-only arguments to make this even easier.
Well, why don't you just do what you said you want? Make Mammal.__init__() take a *args argument, then use that. Here's the code:
class Animal(object):
def __init__(self, class_, species, is_domesticated):
self.class_ = class_
self.species = species
self.is_domesticated = is_domesticated
def __str__(self):
s_dom = "dom" if self.is_domesticated else "wild"
return ("Animal(%s, %s, %s)" % (self.class_, self.species, s_dom))
class Mammal(Animal):
def __init__(self, *args):
Animal.__init__(self, 'Mammal', *args)
cat = Mammal("cat", True)
print(cat)
lion = Mammal("lion", False)
print(lion)
The output:
Animal(Mammal, cat, dom)
Animal(Mammal, lion, wild)
I've read What are Class methods in Python for? but the examples in that post are complex. I am looking for a clear, simple, bare-bones example of a particular use case for classmethods in Python.
Can you name a small, specific example use case where a Python classmethod would be the right tool for the job?
Helper methods for initialization:
class MyStream(object):
#classmethod
def from_file(cls, filepath, ignore_comments=False):
with open(filepath, 'r') as fileobj:
for obj in cls(fileobj, ignore_comments):
yield obj
#classmethod
def from_socket(cls, socket, ignore_comments=False):
raise NotImplemented # Placeholder until implemented
def __init__(self, iterable, ignore_comments=False):
...
Well __new__ is a pretty important classmethod. It's where instances usually come from
so dict() calls dict.__new__ of course, but there is another handy way to make dicts sometimes which is the classmethod dict.fromkeys()
eg.
>>> dict.fromkeys("12345")
{'1': None, '3': None, '2': None, '5': None, '4': None}
I don't know, something like named constructor methods?
class UniqueIdentifier(object):
value = 0
def __init__(self, name):
self.name = name
#classmethod
def produce(cls):
instance = cls(cls.value)
cls.value += 1
return instance
class FunkyUniqueIdentifier(UniqueIdentifier):
#classmethod
def produce(cls):
instance = super(FunkyUniqueIdentifier, cls).produce()
instance.name = "Funky %s" % instance.name
return instance
Usage:
>>> x = UniqueIdentifier.produce()
>>> y = FunkyUniqueIdentifier.produce()
>>> x.name
0
>>> y.name
Funky 1
The biggest reason for using a #classmethod is in an alternate constructor that is intended to be inherited. This can be very useful in polymorphism. An example:
class Shape(object):
# this is an abstract class that is primarily used for inheritance defaults
# here is where you would define classmethods that can be overridden by inherited classes
#classmethod
def from_square(cls, square):
# return a default instance of cls
return cls()
Notice that Shape is an abstract class that defines a classmethod from_square, since Shape is not really defined, it does not really know how to derive itself from a Square so it simply returns a default instance of the class.
Inherited classes are then allowed to define their own versions of this method:
class Square(Shape):
def __init__(self, side=10):
self.side = side
#classmethod
def from_square(cls, square):
return cls(side=square.side)
class Rectangle(Shape):
def __init__(self, length=10, width=10):
self.length = length
self.width = width
#classmethod
def from_square(cls, square):
return cls(length=square.side, width=square.side)
class RightTriangle(Shape):
def __init__(self, a=10, b=10):
self.a = a
self.b = b
self.c = ((a*a) + (b*b))**(.5)
#classmethod
def from_square(cls, square):
return cls(a=square.length, b=square.width)
class Circle(Shape):
def __init__(self, radius=10):
self.radius = radius
#classmethod
def from_square(cls, square):
return cls(radius=square.length/2)
The usage allows you to treat all of these uninstantiated classes polymorphically
square = Square(3)
for polymorphic_class in (Square, Rectangle, RightTriangle, Circle):
this_shape = polymorphic_class.from_square(square)
This is all fine and dandy you might say, but why couldn't I just use as #staticmethod to accomplish this same polymorphic behavior:
class Circle(Shape):
def __init__(self, radius=10):
self.radius = radius
#staticmethod
def from_square(square):
return Circle(radius=square.length/2)
The answer is that you could, but you do not get the benefits of inheritance because Circle has to be called out explicitly in the method. Meaning if I call it from an inherited class without overriding, I would still get Circle every time.
Notice what is gained when I define another shape class that does not really have any custom from_square logic:
class Hexagon(Shape):
def __init__(self, side=10):
self.side = side
# note the absence of classmethod here, this will use from_square it inherits from shape
Here you can leave the #classmethod undefined and it will use the logic from Shape.from_square while retaining who cls is and return the appropriate shape.
square = Square(3)
for polymorphic_class in (Square, Rectangle, RightTriangle, Circle, Hexagon):
this_shape = polymorphic_class.from_square(square)
I find that I most often use #classmethod to associate a piece of code with a class, to avoid creating a global function, for cases where I don't require an instance of the class to use the code.
For example, I might have a data structure which only considers a key valid if it conforms to some pattern. I may want to use this from inside and outside of the class. However, I don't want to create yet another global function:
def foo_key_is_valid(key):
# code for determining validity here
return valid
I'd much rather group this code with the class it's associated with:
class Foo(object):
#classmethod
def is_valid(cls, key):
# code for determining validity here
return valid
def add_key(self, key, val):
if not Foo.is_valid(key):
raise ValueError()
..
# lets me reuse that method without an instance, and signals that
# the code is closely-associated with the Foo class
Foo.is_valid('my key')
Another useful example of classmethod is in extending enumerated types. A classic Enum provides symbolic names which can be used later in the code for readability, grouping, type-safety, etc. This can be extended to add useful features using a classmethod. In the example below, Weekday is an enuerated type for the days of the week. It has been extended using classmethod so that instead of keeping track of the weekday ourselves, the enumerated type can extract the date and return the related enum member.
from enum import Enum
from datetime import date
class Weekday(Enum):
MONDAY = 1
TUESDAY = 2
WEDNESDAY = 3
THURSDAY = 4
FRIDAY = 5
SATURDAY = 6
SUNDAY = 7
#
#classmethod
def from_date(cls, date):
return cls(date.isoweekday())
Weekday.from_date(date.today())
<Weekday.TUESDAY: 2>
Source: https://docs.python.org/3/howto/enum.html
in class MyClass(object):
'''
classdocs
'''
obj=0
x=classmethod
def __init__(self):
'''
Constructor
'''
self.nom='lamaizi'
self.prenom='anas'
self.age=21
self.ville='Casablanca'
if __name__:
ob=MyClass()
print(ob.nom)
print(ob.prenom)
print(ob.age)
print(ob.ville)