В Python, как указать, что я переопределяю метод?

в Java, например,@Override аннотация не только обеспечивает проверку времени компиляции переопределения, но и обеспечивает отличный самодокументированный код.

Я просто ищу документацию (хотя, если это индикатор для какой-то проверки, такой как pylint, это бонус). Я могу добавить комментарий или docstring где-нибудь, но каков идиоматический способ указать переопределение в Python?

7 ответов


UPDATE (23.05.2015): на основе этого и ответа fwc:s Я создал установочный пакет piphttps://github.com/mkorpela/overrides

время от времени я заканчиваю здесь, глядя на этот вопрос. В основном это происходит после (снова) появления той же ошибки в нашей базе кода: кто-то забыл какой-то класс реализации "интерфейса" при переименовании метода в "интерфейсе"..

Ну Python не Java, но Python имеет власть - и явный лучше, чем неявно - и есть реальные конкретные случаи в реальном мире, когда эта вещь помогла бы мне.

Итак, вот эскиз переопределяет декоратора. Это проверит, что класс, заданный в качестве параметра, имеет то же имя метода (или что-то), что и оформляемый метод.

Если вы можете придумать лучшее решение, Пожалуйста, разместить его здесь!

def overrides(interface_class):
    def overrider(method):
        assert(method.__name__ in dir(interface_class))
        return method
    return overrider

это работает следующим образом:

class MySuperInterface(object):
    def my_method(self):
        print 'hello world!'


class ConcreteImplementer(MySuperInterface):
    @overrides(MySuperInterface)
    def my_method(self):
        print 'hello kitty!'

и если вы сделаете неисправную версию, она поднимет ошибка утверждения при загрузке класса:

class ConcreteFaultyImplementer(MySuperInterface):
    @overrides(MySuperInterface)
    def your_method(self):
        print 'bye bye!'

>> AssertionError!!!!!!!

вот реализация, которая не требует спецификации имени interface_class.

import inspect
import re

def overrides(method):
    # actually can't do this because a method is really just a function while inside a class def'n  
    #assert(inspect.ismethod(method))

    stack = inspect.stack()
    base_classes = re.search(r'class.+\((.+)\)\s*\:', stack[2][4][0]).group(1)

    # handle multiple inheritance
    base_classes = [s.strip() for s in base_classes.split(',')]
    if not base_classes:
        raise ValueError('overrides decorator: unable to determine base class') 

    # stack[0]=overrides, stack[1]=inside class def'n, stack[2]=outside class def'n
    derived_class_locals = stack[2][0].f_locals

    # replace each class name in base_classes with the actual class type
    for i, base_class in enumerate(base_classes):

        if '.' not in base_class:
            base_classes[i] = derived_class_locals[base_class]

        else:
            components = base_class.split('.')

            # obj is either a module or a class
            obj = derived_class_locals[components[0]]

            for c in components[1:]:
                assert(inspect.ismodule(obj) or inspect.isclass(obj))
                obj = getattr(obj, c)

            base_classes[i] = obj


    assert( any( hasattr(cls, method.__name__) for cls in base_classes ) )
    return method

Если вы хотите это только для целей документации, вы можете определить свой собственный переопределить декоратор:

def override(f):
    return f


class MyClass (BaseClass):

    @override
    def method(self):
        pass

это действительно ничего, кроме глаз конфеты, если вы не создаете переопределение (f) таким образом, что на самом деле проверяет переопределение.

но тогда это Python, зачем писать так, как будто это Java?


Python-это не Java. Конечно, на самом деле нет такой вещи, как проверка времени компиляции.

Я думаю, что комментарий в docstring достаточно. Это позволяет любому пользователю вашего метода ввести help(obj.method) и видим, что метод переопределен.

вы также можете явно расширить интерфейс с помощью class Foo(Interface), что позволит пользователям вводить help(Interface.method) чтобы получить представление о функциональности, которую должен предоставить ваш метод.


насколько я знаю, нет специального способа указать переопределение в Python. Вы просто определяете метод и включаете docstring, как всегда.


Как и другие сказали, в отличие от Java, нет тега @Overide, однако выше вы можете создать свой собственный, используя декораторы, однако я бы предложил использовать глобальный метод getattrib () вместо использования внутреннего Дикта, чтобы вы получили что-то вроде следующего:

def Override(superClass):
    def method(func)
        getattr(superClass,method.__name__)
    return method

Если бы вы хотели, вы могли бы поймать getattr () в своем собственном try catch поднять свою собственную ошибку, но я думаю, что метод getattr лучше в этом случае.

также это ловит все элементы, связанные с классом, включая методы класса и vairables


Hear простейший и работает под Jython с классами Java:

class MyClass(SomeJavaClass):
     def __init__(self):
         setattr(self, "name_of_method_to_override", __method_override__)

     def __method_override__(self, some_args):
         some_thing_to_do()