【问题标题】:Iterable decorator可迭代装饰器
【发布时间】:2022-01-21 13:35:38
【问题描述】:

我在 python 中有一个类,其结构如下:

class MyClass:
    def __init__(self, iterable):
        self.iterable = iterable

    def example_0(self):
        for i in self.iterable:
            print(i)

    def example_1(self):
        for i in self.iterable:
            print(i + 1)

    def example_2(self):
        for i in self.iterable:
            print(i + 2)

也就是说,我有几个方法可以在作为类属性的可迭代对象上运行不同的操作。我需要为类中的每个方法运行for i in self.iterable,否则我想对所有这些方法使用装饰器,例如:

class MyClass:
    def __init__(self, iterable):
        self.iterable = iterable

    @iterate
    def example_0(self, i):
        print(i)

    @iterate
    def example_1(self, i):
        print(i + 1)

    @iterate
    def example_2(self, i):
        print(i + 2)

你能帮我编写这个装饰器,使我的类的行为与新类的行为相同吗?


我试过了:

class MyClass:
    def __init__(self, iterable):
        self.iterable = iterable

    def iterate(self, f):
        def func(*args, **kwargs):
            for i in self.iterable:
                f(self, i, *args, **kwargs)
        return func

    @iterate
    def example_0(self, i):
        print(i)

    @iterate
    def example_1(self, i):
        print(i + 1)

    @iterate
    def example_2(self, i):
        print(i + 2)

它返回:TypeError: iterate() missing 1 required positional argument: 'f'

我的主要问题是我不确定如何将装饰器放在我的类中,因为它正在迭代类的属性。

【问题讨论】:

  • 你知道一般怎么写装饰器吗?如果是这样,您是否尝试编写此装饰器?你的尝试出了什么问题?如果你被卡住了,特别是为什么你被卡住了(如你所见)?一般不能"help you";我们需要一个明确的问题。
  • 这样的装饰器看起来与您现在拥有的方法非常相似。你到底在为什么呢?你知道如何编写这样一个 迭代某些东西的装饰器吗?
  • 我可以建议完全不同的方法吗?编写 one 方法,该方法接受一个函数作为参数,迭代可迭代对象并将函数应用于每个;然后你可以传入例如printlambda i: print(i + 1)
  • 我认为装饰器不应该在它的初始化中使用self,而是在 func 中。装饰器本身不是类方法。
  • “我的主要问题是我不确定如何将装饰器放在我的类中,因为它正在迭代类的属性。”不需要,因为self 将像传递到原始版本一样传递到装饰版本。把它放在里面会导致问题,因为当你尝试应用装饰器时,Python 想要调用iterate 作为方法,但是没有实例可以提前使用 .您可以通过装饰装饰器(使用@staticmethod)并删除self 参数来解决此问题;但实际上把它放在外面更容易。

标签: python decorator


【解决方案1】:

我不认为这有什么好处,但这里有一个选择。这也允许使用其他参数。

from functools import wraps

def iterated(f):
    @wraps(f)
    def _f(self, *args, **kwargs):
        for i in self.iterable:
            f(self, i, *args, **kwargs)
    return _f

例子:

In [11]: class MyClass2:
    ...:     def __init__(self, iterable):
    ...:         self.iterable = iterable
    ...: 
    ...:     @iterated
    ...:     def example_0(self, i, k):
    ...:         print(i + k)

In [12]: MyClass2([1,2,3]).example_0(2)
3
4
5

这是在类之外定义的。在您失败的实现中,您忘记了返回的闭包中的 self 参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-28
    • 2021-09-16
    • 2017-02-04
    • 2020-05-20
    • 2021-08-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多