Is there a way to get ad-hoc polymorphism in Python?

operator overloading in python
method overloading in python
method overriding in python
you can change the way operators behave in python.
in python same operator may behave differently depending upon operands
python override method with different arguments
why method overloading is not supported in python
overlapping operator in python

Many languages support ad-hoc polymorphism (a.k.a. function overloading) out of the box. However, it seems that Python opted out of it. Still, I can imagine there might be a trick or a library that is able to pull it off in Python. Does anyone know of such a tool?

For example, in Haskell one might use this to generate test data for different types:

-- In some testing library:
class Randomizable a where
   genRandom :: a

-- Overload for different types
instance Randomizable String where genRandom = ...
instance Randomizable Int    where genRandom = ...
instance Randomizable Bool   where genRandom = ...


-- In some client project, we might have a custom type:
instance Randomizable VeryCustomType where genRandom = ...

The beauty of this is that I can extend genRandom for my own custom types without touching the testing library.

How would you achieve something like this in Python?

A Python function cannot be automatically specialised based on static compile-time typing. Therefore its result can only depend on its arguments received at run-time and on the global (or local) environment, unless the function itself is modifiable in-place and can carry some state.

Your generic function genRandom takes no arguments besides the typing information. Thus in Python it should at least receive the type as an argument. Since built-in classes cannot be modified, the generic function (instance) implementation for such classes should be somehow supplied through the global environment or included into the function itself.

I've found out that since Python 3.4, there is @functools.singledispatch decorator. However, it works only for functions which receive a type instance (object) as the first argument, so it is not clear how it could be applied in your example. I am also a bit confused by its rationale:

In addition, it is currently a common anti-pattern for Python code to inspect the types of received arguments, in order to decide what to do with the objects.

I understand that anti-pattern is a jargon term for a pattern which is considered undesirable (and does not at all mean the absence of a pattern). The rationale thus claims that inspecting types of arguments is undesirable, and this claim is used to justify introducing a tool that will simplify ... dispatching on the type of an argument. (Incidentally, note that according to PEP 20, "Explicit is better than implicit.")

The "Alternative approaches" section of PEP 443 "Single-dispatch generic functions" however seems worth reading. There are several references to possible solutions, including one to "Five-minute Multimethods in Python" article by Guido van Rossum from 2005.

Ad hoc polymorphism in Python, Ad hoc polymorphism in Python. Some statically typed languages have ad hoc polymorphism where a function can have multiple implementations depending on the types of its arguments. In languages like C++ and Java, it is called function overloading. In Haskell, it is accomplished with type classes. Function Polymorphism in Python. There are some functions in Python which are compatible to run with multiple data types. One such function is the len() function. It can run with many data types in Python. Let's look at some example use cases of the function. Example 2: Polymorphic len() function

Python is not a strongly typed language, so it really doesn't matter if yo have an instance of Randomizable or an instance of some other class which has the same methods.

One way to get the appearance of what you want could be this:

types_ = {}
def registerType ( dtype , cls ) :
    types_[dtype] = cls
def RandomizableT ( dtype ) :
    return types_[dtype]

Firstly, yes, I did define a function with a capital letter, but it's meant to act more like a class. For example:

registerType ( int , TheLibrary.Randomizable )
registerType ( str , MyLibrary.MyStringRandomizable )

Then, later:

type = ... # get whatever type you want to randomize
randomizer = RandomizableT(type) ()
print randomizer.getRandom()

polymorphism � PyPI, Ad hoc polymorphism for Python classes! Redefining the method with the same types Other methods can have any other names. In Python, operator overloading (also known as “operator ad-hoc polymorphism”) in particular is a form of ‘syntactic sugar’ that enables powerful and convenient ways to prescribe an operator’s, er, operations, as an infix expression of specified types.

Does this count for ad hock polymorphism?

class A:
    def __init__(self):
        pass

    def aFunc(self):
        print "In A"

class B:
    def __init__(self):
        pass

    def aFunc(self):
        print "In B"

f = A()
f.aFunc()
f = B()
f.aFunc()

output

In A
In B

Overloading Operators in Python, In Python, operator overloading (also known as “operator ad-hoc it needs to have its own corresponding __lt__() method in order to be able� Ad-hoc polymorphism and parametric polymorphism are specializations of the concept. (According to the relevant Wikipedia article , there also exist other types of polymorphism.) Ad-hoc polymorphism is also known as function overloading, and it refers to using the type system in order to resolve precisely which method will be invoked.

Another version of polymorphism

from module import aName

If two modules use the same interface, you could import either one and use it in your code. One example of this is from xml.etree.ElementTree import XMLParser

How many types of polymorphism are there in the Python language , As you see we can get the same kind of behavior as before but now Bar is not a Foo. Python specifically uses duck-typing, which means that any operation Parametric and subtype polymorphism are meaningless in the� Polymorphism with class methods: Below code shows how python can use two different class types, in the same way. We create a for loop that iterates through a tuple of objects. Then call the methods without being concerned about which class type each object is. We assume that these methods actually exist in each class.

Ad-hoc, Inclusion, Parametric & Coercion Polymorphisms , Hence, in the above code, we have two different Classes with a function having the Parametric Polymorphism opens a way to use the same piece of code for� Smart, pythonic, ad-hoc, typed polymorphism for Python. Features. Provides a bunch of primitives to write declarative business logic; Enforces better architecture; Fully typed with annotations and checked with mypy, PEP561 compatible; Allows to write a lot of simple code without inheritance or interfaces; Pythonic and pleasant to write and to

[PDF] Measuring Polymorphism in Python Programs, this extra expressiveness is needed, and how the possible polymorphism in dynamic predict the return type from an ad-hoc polymorphic function based on the Python allows multiple inheritance, i.e., a class may have many superclasses� ad-hoc polymorphism, which relates to the ability to define functions of the same name that vary only by the types they deal with (overloading in Java). The word polymorphism is also used to describe concepts in other, unrelated, domains such a s genetics .

Ad-hoc polymorphism in Python's BINARY ADD instruction , Download scientific diagram | Ad-hoc polymorphism in Python's BINARY ADD level is higher than that of the native machine they run on, have performance. programs by influencing how the JIT compiler generates the machine code. Modeling polymorphism in relational databases is a challenging task. In this article, we present several modeling techniques to represent polymorphic objects in a relational database using the Django object-relational mapping (ORM). This intermediate-level tutorial is designed for readers who are

Comments
  • Provide an example of what you have in mind or how it would help you.
  • I added an example. Hopefully that will earn your vote back.
  • Python doesn't have strongly typed parameters to methods. Just have a single method that checks the type of the input and reacts accordingly. Same effect, no?
  • @RobertB If you do that, then your cases are "closed" and you must modify the original method to add new types. That's what I'm trying to avoid and the main benefit of ad-hoc polymorphism.
  • You really need to include examples of how you intend to USE whatever it is you want. Saying "Haskell can do this:" doesn't help because the syntaxes are different. What is it exactly that you want to do?
  • I recently discovered singledispatch as well and you're right that it is the only "blessed" solution to this that I can find. Thank you for documenting it here!
  • @ElliotCameron, I am glad that my answer was to the point, but i may later add more thoughts on "ad-hoc polymorphism" in Python. The "blessed solution" looks hackish to me, in contradiction with its stated rationale, and inconsistent with the established approach. Note that, according to Guido van Rossum, multimethods (generic functions) are not very OO. It is not clear to me how the use of singledispatch decorator is better or different from multiple elif.
  • I believe that the pure and proper way to have ad-hoc polymorphism in Python is to use duck typing, or, what amounts to the same, protocols. This requires however that the developer of the generic function be able to modify the definitions of the classes for which the generic function is to be implemented. This poses an obvious problem for built-in classes. Subclassing built-in classes may work in some cases. If not, any kind of a hack can do the job...
  • The benefit over if/elif is that libraries can be extended without being modified. There is another way to do it, though. Instead of dispatching on type, libraries could ask that you provide the dispatch function yourself. This would be an argument, say, to a class that lets the application choose how to dispatch and optionally use the library-provided defaults. The problem with this is that it only works "post instantiation". For code that runs at import time, this gets trickier and using type-based dispatch can make that simpler.
  • This is exactly what I need. It allows the original testing library to generate random data for my custom type without having to modify the library.
  • That's just dynamic typing.
  • You could write two objects with a method call draw, which would draw the object. One object will draw a circle, the other a square. This is a very common object oriented example. My dynamic typing example is one way of implemented in python which is not available in c++. Doesn't handle subtypes.
  • In your example, I must know about both A and B in order to use them. The idea behind my example code is that the user of genRandom does not need to know about the type that it's dealing with. This means that a library can call it and genRandom data for a type that the library does not know about.
  • I think i've understood the real problem with this code: it is not that the user of genRandom needs to know about A and B (i do not see why he would need it), but that to implement the instances of the generic function for A and B, one needs to have access to the source code of A and B and be able to modify it.