可选择在类方法上使用装饰器

Posted

技术标签:

【中文标题】可选择在类方法上使用装饰器【英文标题】:Optionally use decorators on class methods 【发布时间】:2014-05-09 00:21:50 【问题描述】:

我是 Python 新手,我正在为 api 构建一个包装器。我想让用户决定他/她是否想对我从模块公开的方法使用装饰器。

例如:

# create a new instance
api = MyApi()

# return a simple json response with all the data related to a timetable
print api.time_table

现在用户拥有了所有的数据,并且可以为所欲为。例如,我想添加一些“方便”的方法;让用户得到一小部分 json 而不是整个大的 json 响应。

我的想法是为此使用 python 装饰器。 (可选)我的目标应该是这样的:

# use the method and get al the data
print api.time_table

# Optionally, get a specific part, just the shows part. (PSEUDO CODE BELOW)
@shows
print api.time_table

当然,装饰器不是这样工作的,但是有没有办法在现有的类方法上选择使用装饰器,或者装饰器总是必须包装原始方法?

那么这里最 Pythonic 的方式是什么?我真的很想使用装饰器,但如果这不是一个好主意,我可以在我的 Api 类中创建更多“方便”方法。

【问题讨论】:

您只能在函数和类上使用装饰器,而不能在其他任何东西上使用装饰器(例如print 语句)。你可以扩展你的 API 来给用户更多的选择。 感谢您的快速回答,所以没有办法在现有函数上使用装饰器?在这种情况下,我不得不使用更多的类方法。使用 lambdas 可能会想出一些方便的东西。 当然你也可以使用装饰器;装饰器只是函数;应用于bar@foobar = foo(bar)完全相同;当以bar 作为参数调用时,将bar 替换为foo 的返回值。 【参考方案1】:

您的选择是向您的 API 添加更多方法或为用户提供实用功能:

from yourmodule import MyAPI

api = MyAPI

filtered_timetable = api.filter_on(something)

from yourmodule import MyAPI, filter_timetable

api = MyAPI

filtered_timetable = filter_timetable(api.time_table, something)

请记住,装饰器只是可调用的;语法:

@foo
def bar():
    pass

只是语法糖:

def bar():
    pass
bar = foo(bar)

foo() 被调用,返回值替换装饰对象。通常您将函数用于装饰器,但没有人说您必须将这些函数用作装饰器。

filter_timetable 可以是这样的装饰器;如果你有一个同时使用它的用例。

【讨论】:

以上是关于可选择在类方法上使用装饰器的主要内容,如果未能解决你的问题,请参考以下文章

如何在类中定义装饰器?

TS之装饰器

如何在类中移动这个方法装饰器模式?

TypeScript(21): 装饰器

JS 装饰器解析

在类中的所有实例方法自动调用之后调用方法:元类还是装饰器?