我最近创建了一个 @sequenceable 装饰器,它可以应用于任何接受一个参数的函数,并使其自动适用于任何序列。这是代码(Python 2.5):

def sequenceable(func):
    def newfunc(arg):
        if hasattr(arg, '__iter__'):
            if isinstance(arg, dict):
                return dict((k, func(v)) for k, v in arg.iteritems())
            else:
                return map(func, arg)
        else:
            return func(arg)
    return newfunc

正在使用:
@sequenceable
def unixtime(dt):
    return int(dt.strftime('%s'))

>>> unixtime(datetime.now())
1291318284
>>> unixtime([datetime.now(), datetime(2010, 12, 3)])
[1291318291, 1291352400]
>>> unixtime({'start': datetime.now(), 'end': datetime(2010, 12, 3)})
{'start': 1291318301, 'end': 1291352400}

我的问题是:
  • 这是一个糟糕的主意吗,为什么?
  • 这可能是个好主意,但在实现时有明显的缺点吗?
  • 有哪些潜在的陷阱?
    使用此代码?
  • 是否有内置函数或库
    已经做了我正在做的事情?
  • 最佳答案

    这是一个可怕的想法。这本质上是松散的打字。鸭子打字到此为止
    应该采取的东西,海事组织。

    考虑一下:

    def pluralize(f):
        def on_seq(seq):
            return [f(x) for x in seq]
        def on_dict(d):
             return dict((k, f(v)) for k, v in d.iteritems())
        f.on_dict = on_dict
        f.on_seq = on_seq
        return f
    

    你的例子然后变成
    @pluralize
    def unixtime(dt):
        return int(dt.strftime('%s'))
    
    
    unixtime.on_seq([datetime.now(), datetime(2010, 12, 3)])
    unixtime.on_dict({'start': datetime.now(), 'end': datetime(2010, 12, 3)})
    

    这样做仍然需要调用者知道(在鸭子类型的准确性范围内)传入的内容,并且不会向实际函数添加任何类型检查开销。它也适用于任何类似 dict 的对象,而您的原始解决方案取决于它是 dict 的实际子类。

    关于python - 我的装饰器有多糟糕?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4339099/

    10-14 18:15