python best practices - classes are very similar, but constructor is different - python

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):
...

Related

How to subclass when __init__ calls a function you want to modify

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

Method Inheritance in Python

I have a parent class and two child class. The parent class is an abstract base class that has method combine that gets inherited by the child classes. But each child implements combine differently from a parameter perspective therefore each of their own methods take different number of parameters. In Python, when a child inherits a method and requires re-implementing it, that newly re-implemented method must match parameter by parameter. Is there a way around this? I.e. the inherited method can have dynamic parameter composition?
This code demonstrates that signature of overridden method can easily change.
class Parent(object):
def foo(self, number):
for _ in range(number):
print "Hello from parent"
class Child(Parent):
def foo(self, number, greeting):
for _ in range(number):
print greeting
class GrandChild(Child):
def foo(self):
super(GrandChild,self).foo(1, "hey")
p = Parent()
p.foo(3)
c = Child()
c.foo(2, "Hi")
g = GrandChild()
g.foo()
As the other answer demonstrates for plain classes, the signature of an overridden inherited method can be different in the child than in the parent.
The same is true even if the parent is an abstract base class:
import abc
class Foo:
__metaclass__ = abc.ABCMeta
#abc.abstractmethod
def bar(self, x, y):
return x + y
class ChildFoo(Foo):
def bar(self, x):
return super(self.__class__, self).bar(x, 3)
class DumbFoo(Foo):
def bar(self):
return "derp derp derp"
cf = ChildFoo()
print cf.bar(5)
df = DumbFoo()
print df.bar()
Inappropriately complicated detour
It is an interesting exercise in Python metaclasses to try to restrict the ability to override methods, such that their argument signature must match that of the base class. Here is an attempt.
Note: I'm not endorsing this as a good engineering idea, and I did not spend time tying up loose ends so there are likely little caveats about the code below that could make it more efficient or something.
import types
import inspect
def strict(func):
"""Add some info for functions having strict signature.
"""
arg_sig = inspect.getargspec(func)
func.is_strict = True
func.arg_signature = arg_sig
return func
class StrictSignature(type):
def __new__(cls, name, bases, attrs):
func_types = (types.MethodType,) # include types.FunctionType?
# Check each attribute in the class being created.
for attr_name, attr_value in attrs.iteritems():
if isinstance(attr_value, func_types):
# Check every base for #strict functions.
for base in bases:
base_attr = base.__dict__.get(attr_name)
base_attr_is_function = isinstance(base_attr, func_types)
base_attr_is_strict = hasattr(base_attr, "is_strict")
# Assert that inspected signatures match.
if base_attr_is_function and base_attr_is_strict:
assert (inspect.getargspec(attr_value) ==
base_attr.arg_signature)
# If everything passed, create the class.
return super(StrictSignature, cls).__new__(cls, name, bases, attrs)
# Make a base class to try out strictness
class Base:
__metaclass__ = StrictSignature
#strict
def foo(self, a, b, c="blah"):
return a + b + len(c)
def bar(self, x, y, z):
return x
#####
# Now try to make some classes inheriting from Base.
#####
class GoodChild(Base):
# Was declared strict, better match the signature.
def foo(self, a, b, c="blah"):
return c
# Was never declared as strict, so no rules!
def bar(im_a_little, teapot):
return teapot/2
# These below can't even be created. Uncomment and try to run the file
# and see. It's not just that you can't instantiate them, you can't
# even get the *class object* defined at class creation time.
#
#class WrongChild(Base):
# def foo(self, a):
# return super(self.__class__, self).foo(a, 5)
#
#class BadChild(Base):
# def foo(self, a, b, c="halb"):
# return super(self.__class__, self).foo(a, b, c)
Note, like with most "strict" or "private" type ideas in Python, that you are still free to monkey-patch functions onto even a "good class" and those monkey-patched functions don't have to satisfy the signature constraint.
# Instance level
gc = GoodChild()
gc.foo = lambda self=gc: "Haha, I changed the signature!"
# Class level
GoodChild.foo = lambda self: "Haha, I changed the signature!"
and even if you add more complexity to the meta class that checks whenever any method type attributes are updated in the class's __dict__ and keeps making the assert statement when the class is modified, you can still use type.__setattr__ to bypass customized behavior and set an attribute anyway.
In these cases, I imagine Jeff Goldblum as Ian Malcolm from Jurassic Park, looking at you blankly and saying "Consenting adults, uhh, find a way.."

Running a specific set of methods of sub-classes without explicitly calling them

I'm implementing the following in Python: (code skeleton below)
class Base(object):
def __init__(self, run_ext):
def common_method1(self, run_ext):
def common_method2(self, run_ext):
def run_all(self):
"""Run all the methods beginning with run*"""
class Ext1(Base):
def run11(self):
def run12(self):
def notrelated11(self):
class Ext2(Base):
def run21(self):
def run22(self):
def notrelated21(self):
Ext1.run_all() # should run all the *'run*'* methods in Ext1 and
Ext2.run_all() # should run all the *'run*'* methods in Ext2.
Objective:
Implementing run_all() in the base class that would run a specific set of methods from the sub-class when called.
Thoughts:
- The vanilla way of doing it is by making explicit calls to the methods in the sub-classes and defining run_all in the parent class as an abstract method.
- A somewhat hacky way is setting an attribute (or identifying the methods to be run by their names).
I'm looking for any better alternative solutions..
Also wanted to know if this problem fits in with any existing design pattern?
Note: The child classes may contain other methods than just run1, run2.. the not_related methods mentioned above.
Update: As pointed out by #mkriheli the base class wouldn't/shouldn't know about the child classes inheriting from it.
Thanks.
How about using decorators:
import inspect
def runnable(f):
setattr(f, '__can_run__', True)
return f
class Base:
def run_all(self):
for runner_name in inspect.getmembers(self, predicate=inspect.ismethod):
func = getattr(self, runner_name[0])
if hasattr(func, '__can_run__'):
if getattr(func, '__can_run__'):
func()
class Child(Base):
def __init__(self):
self.incremental = 0
#runnable
def run1(self):
self.incremental += 1
print "running", self.incremental
#runnable
def run2(self):
self.incremental += 1
print "running", self.incremental
c = Child()
c.run_all()
Output:
running 1
running 2
Please note that I do not recommend using inspect and what you are trying might be possible in a better way. inspect is a CPython implementation feature, and is not guaranteed to be present in other Python implementations. Do not do Wrong Thing To Do.
Following the idea of #Nandeep, a inspect-free alternative
class runnable(object):
run_list = []
#staticmethod
def add(f):
runnable.run_list.append(f)
class Base:
def run_all(self):
for runner_name in runnable.run_list:
# Now you have all the functions
class Child(Base):
def __init__(self):
self.incremental = 0
#runnable.add
def run1(self):
self.incremental += 1
print "running", self.incremental

Python: How to update the calls of a third class to the overriden method of the original class?

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()

What's an example use case for a Python classmethod?

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)

Categories

Resources