Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent function overriding in Python [duplicate]

Tags:

python

Is there any way I can prevent a child class from overriding a method in the base class?

My guess is that there is not, but I'm coming from the .NET world, and I'm trying to make my API as robust as possible, so any input is greatly appreciated.

class Parent:
    def do_something(self):
        '''This is where some seriously important stuff goes on'''
        pass

class Child(Parent):
    def do_something(self):
        '''This should not be allowed.'''
        pass

Is it possible to enforce this? I know the compiler won't help, so maybe by means of some runtime check? Or is it just not a pythonic way of going about things?

like image 260
Klaus Byskov Pedersen Avatar asked Oct 16 '10 12:10

Klaus Byskov Pedersen


People also ask

How do you stop overwrite names in Python?

You can't. You could use linters (e.g. pylint ) which will check for this kind of thing, but Python allows you to reuse anything except a keyword or None .

How do you stop a function from being overridden in Python?

By inheriting a class with a method having double underscores in front of it, it becomes difficult for the child class to override the above specified method. This practice is almost equivalent to final in Java.

How does super () work in Python?

The super() function in Python makes class inheritance more manageable and extensible. The function returns a temporary object that allows reference to a parent class by the keyword super. The super() function has two major use cases: To avoid the usage of the super (parent) class explicitly.


2 Answers

You are right: what you are attempting is contrary to Python's structure and its culture.

Document your API, and educate your users how to use it. It's their program, so if they still want to override your function, who are you to prevent them?

like image 79
Ned Batchelder Avatar answered Oct 07 '22 00:10

Ned Batchelder


If a API lets you provide subclasses of a certain class and calls your (legally) overridden methods, but also other API methods of that class with simple names like "add", accidentally overriding those methods could lead to hard-to-track-down bugs. It's better to at least warn the user.

The cases where a user wants/needs to override a method that will completely break the API is practically zero. The cases where a user accidentally overrides something that he shouldn't and needs hours to find the culprit are far more frequent. Debugging faulty behaviour caused by this can be cumbersome.

This is how I use to warn or protect attributes from being accidentally overridden:

def protect(*protected):
    """Returns a metaclass that protects all attributes given as strings"""
    class Protect(type):
        has_base = False
        def __new__(meta, name, bases, attrs):
            if meta.has_base:
                for attribute in attrs:
                    if attribute in protected:
                        raise AttributeError('Overriding of attribute "%s" not allowed.'%attribute)
            meta.has_base = True
            klass = super().__new__(meta, name, bases, attrs)
            return klass
    return Protect

You can use it like this:

class Parent(metaclass=protect("do_something", "do_something_else")):
    def do_something(self):
        '''This is where some seriously important stuff goes on'''
        pass

class Child(Parent):
    def do_something(self):
        '''This will raise an error during class creation.'''
        pass
like image 25
uzumaki Avatar answered Oct 06 '22 23:10

uzumaki