Dynamic submit and inheritance in python

I am trying to modify a multipoint GUID (dynamic dispatch code):

http://www.artima.com/weblogs/viewpost.jsp?thread=101605

to handle inheritance arguments and possibly out of order.

eg. (inheritance problem)

class A(object): pass class B(A): pass @multimethod(A,A) def foo(arg1,arg2): print 'works' foo(A(),A()) #works foo(A(),B()) #fails 

Is there a better way than iteratively checking the super () of each element until it is found?

eg. (problem of ordering arguments) I thought about this in terms of collision detection.

eg.

 foo(Car(),Truck()) and foo(Truck(), Car()) and 

should run

 foo(Car,Truck) # Note: @multimethod(Truck,Car) will throw an exception if @multimethod(Car,Truck) was registered first? 

I am looking specifically for an โ€œelegantโ€ solution. I know that I could just lay my way on all the possibilities, but I try to avoid this. I just wanted to get some ideas / ideas before I sat down and beat up the solution.

thanks

+4
source share
2 answers

super() returns a proxy object, not a parent class (because you can have multiple inheritance), so this will not work. Using isinstance() is your best bet, although there is no way to make it as elegant as looking up a dictionary using type(arg) .

I do not think that the possibility of alternative orderings of arguments is a good idea; this can lead to unpleasant surprises and make it compatible with inheritance, will also be a significant headache. However, it would be quite simple to make a second decorator to "use this function if all arguments are of type A", or "use this function if all arguments are of type {A, B, E}".

+2
source

Regarding the inheritance issue: this can be done with a little change to MultiMethod. (Iterating through self.typemap and checking with issubclass ):

 registry = {} class MultiMethod(object): def __init__(self, name): self.name = name self.typemap = {} def __call__(self, *args): types = tuple(arg.__class__ for arg in args) # a generator expression! for typemap_types in self.typemap: if all(issubclass(arg_type,known_type) for arg_type,known_type in zip(types,typemap_types)): function = self.typemap.get(typemap_types) return function(*args) raise TypeError("no match") def register(self, types, function): if types in self.typemap: raise TypeError("duplicate registration") self.typemap[types] = function def multimethod(*types): def register(function): name = function.__name__ mm = registry.get(name) if mm is None: mm = registry[name] = MultiMethod(name) mm.register(types, function) return mm return register class A(object): pass class B(A): pass class C(object): pass @multimethod(A,A) def foo(arg1,arg2): print 'works' foo(A(),A()) #works foo(A(),B()) #works foo(C(),B()) #raises TypeError 

Note that self.typemap is a dict, and dicts are unordered. Therefore, if you use @multimethod to register two functions, one of which is a subclass of the other, then the behavior of foo may be undefined. That is, the result will depend on which typemap_types appears first in the for typemap_types in self.typemap .

+2
source

Source: https://habr.com/ru/post/1334836/


All Articles