Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a Python Abstract Base Class enforce function signatures?

Suppose I define an abstract base class like this:

from abc import abstractmethod, ABCMeta  class Quacker(object):   __metaclass__ = ABCMeta    @abstractmethod   def quack(self):     return "Quack!" 

This ensures any class deriving from Quacker must implement the quack method. But if I define the following:

class PoliteDuck(Quacker):    def quack(self, name):      return "Quack quack %s!" % name  d = PoliteDuck()  # no error 

I'm allowed to instantiate the class because I've provided the quack method, but the function signatures don't match. I can see how this might be useful in some situations, but I'm in interested in ensuring I can definitely call the abstract methods. This might fail if the function signature is different!

So: how can I enforce a matching function signature? I would expect an error when creating the object if the signatures don't match, just like if I hadn't defined it at all.

I know that this is not idiomatic, and that Python is the wrong language to be using if I want these sorts of guarantees, but that's beside the point - is it possible?

like image 828
simonwo Avatar asked Aug 07 '14 13:08

simonwo


People also ask

Can abstract class have implementation Python?

A class is called an Abstract class if it contains one or more abstract methods. An abstract method is a method that is declared, but contains no implementation. Abstract classes may not be instantiated, and its abstract methods must be implemented by its subclasses.

Can abstract class have only method signatures?

Since Java 8, methods can be implemented ( can have a code body ) in an interface if only if it is declared static or default. Abstract methods cannot have a body; all they can have is a method signature as shown in the example above.

What does abstract base class do in Python?

An abstract base class is a class that is used as a blueprint for other classes. Abstract base classes are a powerful feature in Python since they help you define a blueprint for other classes that may have something in common.

Are abstract classes Pythonic?

Python doesn't directly support abstract classes. But it does offer a module that allows you to define abstract classes. To define an abstract class, you use the abc (abstract base class) module. The abc module provides you with the infrastructure for defining abstract base classes.


2 Answers

It's worse than you think. Abstract methods are tracked by name only, so you don't even have to make quack a method in order to instantiate the child class.

class SurrealDuck(Quacker):     quack = 3  d = SurrealDuck() print d.quack   # Shows 3 

There is nothing in the system that enforces that quack is even a callable object, let alone one whose arguments match the abstract method's original. At best, you could subclass ABCMeta and add code yourself to compare type signatures in the child to the originals in the parent, but this would be nontrivial to implement.

(Currently, marking something as "abstract" essentially just adds the name to a frozen set attribute in the parent (Quacker.__abstractmethods__). Making a class instantiable is as simple as setting this attribute to an empty iterable, which is useful for testing.)

like image 112
chepner Avatar answered Oct 09 '22 01:10

chepner


I recommend you look at pylint. I ran this code through it's static analysis, and on the line where you defined the quack() method, it reported:

Argument number differs from overridden method (arguments-differ) 

(https://en.wikipedia.org/wiki/Pylint)

like image 20
user590028 Avatar answered Oct 08 '22 23:10

user590028