【问题标题】:Implementing a decorator within class "major flaw"?在类“主要缺陷”中实现装饰器?
【发布时间】:2018-12-11 20:20:41
【问题描述】:

为什么这种装饰器策略被认为不好? (..还是它!?)

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 是一个实例方法是一个问题/错误/坏事。我只打算在课堂上使用装饰器。也许在这种情况下没关系?

【问题讨论】:

    标签: python python-2.7 python-decorators


    【解决方案1】:

    从风格上讲,将函数定义放入不是方法的类定义中有点不合适(恕我直言,它甚至可以是非 Python 的)。 Flat is better than nested,所以最好在类之外声明函数。这样,当读者查看您的课程时,就不会混淆为什么有一个 method 不将 self 作为参数(因为函数被声明为方法当它只是一个装饰器时,虽然如果函数是@staticmethod,这会略有不同。

    如果您担心它会在课堂外使用,请在其前面加上 _,然后 from my_package import * 将不会导入它。它仍然可以在该模块中使用,但除非明确导入,否则不会在外部使用。

    实际上,作者指的是偶尔出现的奇怪的作用域行为(类似于 Javascript 中关于是否使用 function() { ...() =&gt; { ... 基于事物的作用域的辩论。)如果你不小心并且不小心在装饰器的错误部分有涉及self 的逻辑,您可能会遇到范围问题。

    我可以看到在类中使用函数的唯一优势可能是因为它更接近方法(但这会引入不必要的嵌套、潜在的范围问题以及意识到这是装饰器而不是方法的认知负担),如果函数的名称以 ___ 开头,则可以更好地隐藏函数。

    TL;DR 风格/Pythonicity 问题,以及潜在的范围问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-23
      • 2011-03-08
      • 2013-02-25
      • 2010-10-31
      相关资源
      最近更新 更多