Python generics: how to create object of an appropriate class? - python

I have the following code (this code is just for testing):
from typing import TypeVar, Generic, Type
import abc
class BaseMultiplier(abc.ABC):
#abc.abstractmethod
def multiply(self, n):
pass
class MultiplierByTwo(BaseMultiplier):
def multiply(self, n):
return n * 2
class MultiplierByThree(BaseMultiplier):
def multiply(self, n):
return n * 3
Multiplier = TypeVar('Multiplier', Type[MultiplierByTwo], Type[MultiplierByThree])
class MultiplierCreator(Generic[Multiplier]):
def create(self) -> Multiplier:
# I need to create an instance of Multiplier here
pass
class MultiplierByTwoCreator(MultiplierCreator[MultiplierByTwo]):
pass
class MultiplierByThreeCreator(MultiplierCreator[MultiplierByThree]):
pass
So how can I create an instance of an appropriate Multiplier class in create method?
So the following code must not raise any exceptions:
creator_by_two = MultiplierByTwoCreator()
assert type(creator_by_two.create()) == MultiplierByTwo
creator_by_three = MultiplierByThreeCreator()
assert type(creator_by_three.create()) == MultiplierByThree
Thanks in advance.

class MultiplierCreator(Generic[Multiplier]):
def create(self) -> Multiplier:
return self.multiplier()
class MultiplierByTwoCreator(MultiplierCreator[MultiplierByTwo]):
multiplier = MultiplierByTwo
class MultiplierByThreeCreator(MultiplierCreator[MultiplierByThree]):
multiplier = MultiplierByThree
By adding class attributes to the subclasses of MultiplierCreator that contain the related Multiplier subclass you can then use the inherited method create() to call this class attributes and return an instance of it. Hope this is what you are looking for.
Aside from that, to check whether an object is of the correct type you may want to use isinstance():
assert isinstance(creator_by_two.create(), MultiplierByTwo)
assert isinstance(creator_by_three.create(), MultiplierByThree)
Hopefully this can help you.

Related

In Python, how to specify that a Protocol implementer has a specific constructor signature?

Is it possible to define that a class needs a specific constructor?
class Constructible(Protocol):
def __init__(self, i: int): # how do I do this?
raise NotImplementedError
def get_value(self):
raise NotImplementedError
def map_is(cs: Iterable[Constructible], i: int):
mapped = tuple(C(i) for C in cs)
values = tuple(c.get_value() for c in mapped)
# both the constructor and a member method are used
return mapped, values
# implementors (omitting __hash__ and __eq__ for brevity)
class X(Constructible):
def __init__(self, i):
self.i=i
def get_value(self):
return self.i
class Sq(Constructible):
def __init__(self, i):
self.i=i
def get_value(self):
return self.i * self.i
cs, values = tuple(map_is((X, Sq), 5))
assert values == (5, 25)
When specifying it like this, I get
$ mypy constr.py
constr.py:12: error: "Constructible" not callable
Found 1 error in 1 file (checked 1 source file)
Is this even possible? Or should I revert to a factory function #classmethod def construct(i: int): Self?
As explained by #jonrsharpe, you do not pass an iterable of Constructible instances to map_is but an iterable of classes. That means that you should define the function that way:
def map_is(cs: Iterable[Type[Constructible]], i: int):
return (C(i) for C in cs)
That is enough for mypy to validate the code.
But there is an unrelated problem: you never declared any __hash__ nor __equal__ special method. That means that in assert values == (X(5), Sq(5)) the equality used is the one defined on the object class (same as is). So after the above fix, the code executes successfully but still raises an AssertionError, because the objects do have same value, yet they are distinct objects...

Type hint a subclass of list

I use a class which subclasses the built-in list.
class Qry(list):
"""Stores a list indexable by attributes."""
def filter(self, **kwargs):
"""Returns the items in Qry that has matching attributes.
Example:
obj.filter(portfolio='123', account='ABC').
"""
values = tuple(kwargs.values())
def is_match(item):
if tuple(getattr(item, y) for y in kwargs.keys()) == values:
return True
else:
return False
result = Qry([x for x in self if is_match(x)], keys=self._keys)
return result
Now I want to type hint:
class C:
a = 1
def foo(qry: Qry[C]):
"""Do stuff here."""
How do you type hint a custom container class in python 3.5+?
You can do this rather easily:
from typing import TypeVar, List
T = TypeVar('T')
class MyList(List[T]): # note the upper case
pass

How to wrap child methods multiple times in an inheritance tree?

In a framework, I often want to provide a base class that the framework user sub classes. The base class provides controlled access to the base class. One way to accomplish this is to provide unimplemented methods with different names, for example by adding an underscore as prefix:
class Base:
def method(self, arg):
# ...
result = self._method(arg)
# ...
return result
def _method(self, arg):
raise NotImplementedError
However, this scheme only works for one level of inheritance. For more levels, the different method names make it hard to keep an overview of what's going on. Moreover, the framework user has to override different methods depending on the base class he chooses:
class Base:
def method(self, arg):
# ...
result = self._method_sub(arg)
# ...
return result
def _method_sub(self, arg):
raise NotImplementedError
class Intermediate(Base):
def _method_sub(self, arg):
# ...
result = self._method_sub_sub(arg)
# ...
return result
def _method_sub_sub(self, arg):
raise NotImplementedError
Calling super methods does not help when the base method needs to access return values of the child method. I feel object orientation is slightly flawed, missing a child keyword that allows to forward calls to the child class. What solutions exist to solve this problem?
Does this give you what you want?
import abc
class Base(object):
__metaclass__ = abc.ABCMeta
def calculate(self):
result = self.doCalculate()
if 3 < result < 7: # do whatever validation you want
return result
else:
raise ValueError()
#abc.abstractmethod
def doCalculate(self):
pass
class Intermediate(Base):
__metaclass__ = abc.ABCMeta
class Leaf(Intermediate):
def doCalculate(self):
return 5
leaf = Leaf()
print leaf.calculate()
I think the question focuses on different points where behavior extension in an intermediate class can happen. The intermediate class obviously shall refine the "control" part here.
1st Solution
Mostly this can be done the classical way by just overriding the "safe" method - particularly when "both Base and Intermediate are abstract classes provided by the framework", things can be organized so.
The final "silly" implementation class which does the spade work overrides the unsafe method.
Think of this example:
class DoublePositive:
def double(self, x):
assert x > 0
return self._double(x)
def _double(self, x):
raise NotImplementedError
class DoubleIntPositive(DoublePositive):
def double(self, x):
assert isinstance(x, int)
return DoublePositive.double(self, x)
class DoubleImplementation(DoubleIntPositive):
def _double(self, x):
return 2 * x
2nd Solution
Calling virtual child class methods, thus behavior extension at "inner" execution points in a non-classical manner, could be done by introspection in Python - by stepping down the class __bases__ or method resolution order __mro__ with a helper function.
Example:
def child_method(cls, meth, _scls=None):
scls = _scls or meth.__self__.__class__
for base in scls.__bases__:
if base is cls:
cmeth = getattr(scls, meth.__name__, None)
if cmeth.__func__ is getattr(cls, meth.__name__, None).__func__:
return child_method(scls, meth) # next child
if cmeth:
return cmeth.__get__(meth.__self__)
for base in scls.__bases__:
r = child_method(cls, meth, base) # next base
if r is not None:
return r
if _scls is None:
raise AttributeError("child method %r missing" % meth.__name__)
return None
class Base(object):
def double(self, x):
assert x > 0
return Base._double(self, x)
def _double(self, x):
return child_method(Base, self._double)(x)
class Inter(Base):
def _double(self, x):
assert isinstance(x, float)
return child_method(Inter, self._double)(x)
class Impl(Inter):
def _double(self, x):
return 2.0 * x
The helper function child_method() here is thus kind of opposite of Python's super().
3rd solution
If calls should be chainable flexibly, things can be organized as a kind of handler chain explicitly. Think of self.addHandler(self.__privmeth) in the __init__() chain - or even via a tricky meta class. Study e.g. the urllib2 handler chains.

Python - How use properties without creating an object

How do I write a class to make this code work.
class number:
def double(self):
return n*2
print(number(44).double)
>> 88
Well, you could decorate the number.double method with property:
class number:
def __init__(self, number):
self.number = number
#property
def double(self):
return self.number * 2
print(number(42).double) # 84
If you know the type of your argument, it'd be better to inherit number from it. For example
class number(int):
#property
def double(self):
return type(self)(self * 2)
print(number(42).double) # 84
print(number(42).double.double) # 168
Here you are:
class Number(object):
def __init__(self, n):
self.n = n
def double(self):
return 2*self.n
print(Number(44).double())
A couple of notes:
Since double() is a method of the class Number (and not an attribute), you need to use parentheses to call it.
In Python it's considered standard practice to give classes uppercase names.
If you want to define an instance variable (in this case n, or 44, you must def the __init__() function which gives the interpreter instructions for how to create, or initialize an instance of your class.
Hope this helps, and good luck!

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