Например, в Java @Override
аннотация не только обеспечивает проверку переопределения во время компиляции, но и обеспечивает отличный самодокументирующийся код.
Я просто ищу документацию (хотя, если это индикатор какой-то проверки, такой как pylint, это бонус). Я могу добавить комментарий или строку документации где-нибудь, но каков идиоматический способ указать переопределение в Python?
Ответы:
Основываясь на этом и ответе fwc: s, я создал установочный пакет для pip https://github.com/mkorpela/overrides
Время от времени я в конечном итоге здесь, глядя на этот вопрос. Главным образом это происходит после того, как (снова) обнаружена та же ошибка в нашей кодовой базе: кто-то забыл некоторый класс реализации интерфейса, переименовывая метод в интерфейсе.
Ну, Python - это не Java, но Python обладает мощью - и явное лучше, чем неявное, - и в реальном мире существуют реальные конкретные случаи, когда это помогло бы мне.
Итак, вот эскиз переопределений декоратора. Это проверит, что класс, заданный в качестве параметра, имеет то же имя метода (или что-то другое), что и оформляемый метод.
Если вы можете придумать лучшее решение, пожалуйста, опубликуйте его здесь!
Это работает следующим образом:
и если вы сделаете ошибочную версию, это вызовет ошибку утверждения во время загрузки класса:
источник
overrides
может скопировать строку документации переопределенного метода, если переопределенный метод не имеет своего собственного.Вот реализация, которая не требует указания имени interface_class.
источник
Если вы хотите это только для целей документирования, вы можете определить свой собственный декоратор переопределения:
Это на самом деле не что иное, как конфетка, если вы не создадите override (f) таким способом, который фактически проверяет переопределение.
Но тогда, это Python, зачем писать так, как будто это Java?
источник
override
декоратора.Python не является Java. Конечно, нет такой вещи как проверка во время компиляции.
Я думаю, что комментариев в документации достаточно. Это позволяет любому пользователю вашего метода печатать
help(obj.method)
и видеть, что метод является переопределением.Вы также можете явно расширить интерфейс
class Foo(Interface)
, который позволит пользователям печатать,help(Interface.method)
чтобы получить представление о функциональности , которую должен обеспечить ваш метод.источник
@Override
в Java не в том, чтобы документировать, а в том, чтобы поймать ошибку, когда вы намеревались переопределить метод, но в итоге определили новый (например, потому что вы неправильно написали имя; в Java это также может произойти, потому что вы использовали неправильная подпись, но это не проблема в Python - но орфографическая ошибка все еще есть).@Override
является документация в дополнение к проверке времени компиляции.Импровизация на @mkorpela отличный ответ , вот версия с
более точные проверки, присвоение имен и поднятие объектов Error
Вот как это выглядит на практике:
NotImplementedError
" не реализовано в базовом классе "приводит к более описательной
NotImplementedError
ошибкеполный стек
NotImplementedError
« ожидаемый реализованный тип »приводит к более описательной
NotImplementedError
ошибкеполный стек
Самое замечательное в ответе @mkorpela - проверка происходит во время фазы инициализации. Проверку не нужно «запускать». Ссылаясь на предыдущие примеры,
class B
никогда не инициализируется (B()
), ноNotImplementedError
все равно будет повышаться. Это означает, чтоoverrides
ошибки обнаруживаются раньше.источник
overrides.py
. Я не уверен, что еще я могу значительно улучшить, кроме как изменить типы исключений сTypeError
наNotImplementedError
.types.MethodType
. Это была хорошая идея в вашем ответе.Как и другие говорили, в отличие от Java, тег @Overide отсутствует, однако выше вы можете создать свой собственный, используя декораторы, однако я бы предложил использовать глобальный метод getattrib () вместо использования внутреннего dict, чтобы вы получили что-то вроде следующего:
Если вы хотите, вы можете поймать getattr () в своем собственном try catch и поднять свою собственную ошибку, но я думаю, что метод getattr лучше в этом случае.
Также это ловит все элементы, связанные с классом, включая методы класса и vairables
источник
Основываясь на отличном ответе @ mkorpela, я написал похожий пакет ( ipromise pypi github ), который выполняет еще много проверок:
Пусть
A
наследует отB
иC
,B
наследуется отC
.Модуль ipromise проверяет, что:
Если
A.f
переопределяетB.f
,B.f
должен существовать иA
наследовать отB
. (Это чек из пакета переопределений).У вас нет шаблона,
A.f
объявляющего, что он переопределяетB.f
, который затем объявляет, что он переопределяетC.f
.A
следует сказать, что он переопределяет,C.f
посколькуB
может решить прекратить переопределение этого метода, и это не должно приводить к последующим обновлениям.У вас нет шаблона,
A.f
объявляющего, что он переопределяетC.f
, ноB.f
не объявляющего его переопределение.У вас нет шаблона,
A.f
объявляющего, что он переопределяетC.f
, ноB.f
заявляющего, что он переопределяет из некоторыхD.f
.Он также имеет различные функции для маркировки и проверки реализации абстрактного метода.
источник
Hear является самым простым и работает в Jython с классами Java:
источник
Мало того, что декоратор, который я сделал, проверял, является ли имя переопределяющего атрибута каким-либо суперклассом класса, в котором находится атрибут, без необходимости указывать суперкласс, этот декоратор также проверял, чтобы атрибут переопределения был того же типа, что и переопределенный атрибут. Методы класса обрабатываются как методы, а статические методы - как функции. Этот декоратор работает с вызываемыми объектами, методами классов, статическими методами и свойствами.
Исходный код см .: https://github.com/fireuser909/override.
Этот декоратор работает только для классов, которые являются экземплярами override.OverridesMeta, но если ваш класс является экземпляром пользовательского метакласса, используйте функцию create_custom_overrides_meta для создания метакласса, совместимого с декоратором переопределения. Для тестов запустите модуль переопределения .__ init__.
источник
В Python 2.6+ и Python 3.2+ вы можете это сделать (на самом деле имитируйте это , Python не поддерживает перегрузку функций, а дочерний класс автоматически переопределяет метод parent). Мы можем использовать декораторы для этого. Но сначала обратите внимание, что Python
@decorators
и Java -@Annotations
это совершенно разные вещи. Предыдущий - это оболочка с конкретным кодом, а позже - флаг компилятору.Для этого сначала сделайте
pip install multipledispatch
вывод:
Следует помнить одну вещь: поскольку Python не имеет прямой перегрузки функций, даже если класс B не наследуется от класса A, но нуждается во всех этих
foo
s, вам также нужно использовать @Override (хотя при использовании псевдонима «Overload» будет выглядеть лучше в таком случае)источник