Реализуете декоратор в классе "главный недостаток"? - PullRequest
0 голосов
/ 03 июля 2018

Почему эта стратегия декоратора считается плохой? (.. или это!?)

class User(object):

    def __init__(self):
        self.thing = 5

    def __atomic_rate_change(fn):
        def wrapper(self,*args,**kwargs):
            print "start magic"
            self.thing += 1
            fn(self,*args,**kwargs)
            print "end magic"
        return wrapper

    @__atomic_rate_change
    def foo(self,add):
        print self.__atomic_rate_change # <bound method User.__atomic_rate_change of <__main__.User object at 0x6ffffe1ef50>>
        self.thing += add
        print "normal call {0}".format(self.thing)

test = User()
test.foo(1)

Это работает. Но, согласно ресурсу ниже, это плохая практика. Причины таковы:

[...] в этом подходе есть большой недостаток: atomic_rating_change становится метод экземпляра класса User. Это не имеет никакого смысла. Больше чем это, он даже не работает как метод: если вы вызываете его, оформленный параметр будет использоваться как self.

https://medium.com/@vadimpushtaev/decorator-inside-python-class-1e74d23107f6

Я не понимаю, почему проблема / неправильно / плохо, что atomic_rate_change является методом экземпляра. Я только собираюсь использовать декоратор в классе. Возможно, в этом случае все в порядке?

1 Ответ

0 голосов
/ 03 июля 2018

Стилистически размещение определений функций в определении класса, которые не являются методами, неуместно (хотя это может быть даже не пифонично). Flat лучше, чем вложенный , поэтому, вероятно, лучше объявить функцию вне класса. Таким образом, когда читатель смотрит на ваш класс, не возникнет путаницы, почему существует метод , который не принимает self в качестве аргумента (поскольку функция объявляется как метод, когда это просто декоратор, хотя это немного отличается, если функция @staticmethod).

Если вас беспокоит, что он будет использоваться вне класса, добавьте к нему префикс _, и тогда from my_package import * не будет импортировать его. Он все еще может использоваться в этом модуле, но он не будет использоваться снаружи, если явно не импортирован.

Практически автор имеет в виду случайное странное поведение области видимости (похожее на дебаты в Javascript о том, использовать ли function() { ... или () => { ... в зависимости от того, как обстоят дела). Если вы неосторожны и случайно Если логика включает self не в той части декоратора, у вас могут возникнуть проблемы с областью видимости.

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

TL; DR Стилистические / Pythonicity проблемы и потенциальные проблемы объема.

...