В Python украсьте два метода одним и тем же именем, чтобы различать их.

Я пишу фреймворк, который будет использоваться людьми, немного знакомыми с Python. Я остановился на некотором синтаксисе, и для меня и для них имеет смысл использовать что-то вроде этого, где Base - это базовый класс, реализующий структуру.

class A(Base):
    @decorator1
    @decorator2
    @decorator3
    def f(self):
        pass

    @decorator4
    def f(self):
        pass

    @decorator5
    def g(self)
        pass

Вся моя структура реализована через метакласс Base. Эта настройка подходит для моего варианта использования, потому что все эти определяемые пользователем классы имеют богатый граф наследования. Я ожидаю, что пользователь реализует некоторые методы или просто оставит это с pass. Большая часть информации, которую здесь дает пользователь, находится в декораторах. Это позволяет мне избегать других решений, в которых пользователю пришлось бы использовать обезьяну-патч, давать менее структурированные словари и тому подобное.

Моя проблема здесь в том, что f дважды определяется пользователем (по уважительной причине), и это должно обрабатываться моей структурой. К сожалению, к тому времени, когда это дойдет до метода метакласса'__new__, словарь атрибутов будет содержать только один ключ f. Моя идея заключалась в том, чтобы использовать еще один декоратор, например @duplicate, чтобы пользователь сигнализировал, что это происходит, и два f должны быть обернуты по-разному, чтобы они не перезаписывали друг друга. Может что-то подобное сработает?


person user1199915    schedule 26.10.2012    source источник
comment
Что должно произойти, если я сделаю A().f()?   -  person Eric    schedule 27.10.2012
comment
Как определение f дважды может иметь вескую причину - что оно означает или должно делать?   -  person martineau    schedule 27.10.2012
comment
Как я уже сказал, это для фреймворка. Класс A никогда не будет создан. Однако его существование важно, потому что это способ сообщить программе, что нечто вроде A должно существовать. Исходя из этого, моя структура определяет различные версии fs и создает различные подходящие классы, подобные A. Если хотите, это способ заниматься аспектно-ориентированным программированием, структурированным более классическим объектно-ориентированным способом.   -  person user1199915    schedule 27.10.2012


Ответы (3)


Вы должны использовать пространство имен, чтобы различать разные f.

Прислушайтесь к совету «Дзен Питона»:

Пространства имен - одна отличная идея - давайте сделаем их больше!

person Brian Cain    schedule 26.10.2012

Да, вы могли бы, но только с помощью уродливого взлома и только сохранив функцию с новым именем.

Вам нужно будет использовать sys._getframe() функцию для получения локального пространства имен вызывающий фрейм. Это локальное пространство имен является конструктивным классом, и добавление элементов в это пространство имен означает, что они попадут в словарь классов, переданный вашему метаклассу.

Следующее извлекает это пространство имен:

callframe = sys._getframe(1)
namespace = callframe.f_locals

namespace - объект типа dict, как и locals(). Теперь вы можете сохранить что-нибудь в этом пространстве имен (например, __function_definitions__ или подобное), чтобы добавить дополнительные ссылки на функции.

person Martijn Pieters    schedule 26.10.2012
comment
В конце раздела под названием Описательное: стили именования в PEP 8 говорится __double_leading_and_trailing_underscore__: магические объекты или атрибуты, которые живут в пространствах имен, контролируемых пользователем. Например. __init__, __import__ или __file__. Никогда не придумывайте такие имена; используйте их только так, как описано в документации, поэтому сохранение something в пространстве имен с этим именем не кажется хорошим советом. - person martineau; 27.10.2012
comment
@martineau: да, но традиция гласит, что многие проекты все равно используют соглашение о двойном подчеркивании (на свой собственный, низкий, риск). Поскольку метакласс все равно будет обрабатывать все (предположительно, удалив лишнее значение), это не должно представлять большой проблемы. - person Martijn Pieters; 27.10.2012
comment
В том, чем я хочу заниматься, есть несколько уровней пользователей. Я использую Python, но у меня тоже есть пользователи. Я хочу, чтобы пользователь дал мне хорошо оформленную диаграмму классов, за исключением той незначительной разницы, что можно разрешить несколько определений методов. Для меня имеет смысл проникнуть в вызывающий фрейм, единственная альтернатива, которую я вижу, - это изменить интерпретатор Python ... - person user1199915; 27.10.2012
comment
@ user1199915: Как вызовы функций различаются по типу аргумента (ов), например C ++? Если это так, возможно, вы можете изменить имя функции на основе них, как это делает. - person martineau; 27.10.2012
comment
@Martijn Pieters: Независимо от того, насколько важен низкий риск внутри проекта, но если это часть интерфейса, особенно доступного для пользователей, лучше всегда избегать этого. - person martineau; 27.10.2012

Возможно, вы думаете о Java - перегрузке методов и сигнатуре аргументов - но это Python, и вы не можете этого сделать. Второй f () переопределит первый f (), и вы получите только один f (). Пространство имен - это словарь, и у вас не может быть дублированных ключей.

person Meitham    schedule 26.10.2012