我有一组经常使用的功能,所以我想在库中收集它们。在我开始编写库之前,我在考虑在哪里存储影响某些函数行为的常量。
使用该库时我想写的内容如下:
import tools
tools.collect(object_a, object_b, mode=tools.collect.RECURSIVE)
一般来说,函数应该能够接受的常量应该存储在函数本身中。
为了实现这一点,我创建了一个装饰器函数,它将传递的属性赋值给装饰函数。
def attr_decorator(**attrs):
def decorator(f):
for k, v in attrs.iteritems():
setattr(f, k, v)
return f
return decorator
这个装饰器可以像这样使用:
@attr_decorator(
FLAT = 1 << 0,
RECURSIVE 1 << 1,
)
def collect(a, b, mode):
# ...
到目前为止,这种方法非常好。
@attr_decorator(
FLAT = 1 << 0,
RECURSIVE 1 << 1,
)
def collect(a, b, mode=collect.RECURSIVE):
# ...
这不起作用,因为 collect 函数未在 mode 参数的默认值存储的位置定义(因此甚至没有修饰)。
我能够提出的唯一解决方案导致了一种尴尬的语法,它看起来并不好看。我给装饰器函数赋予了与要装饰的函数相同的属性。
def attr_decorator(**attrs):
def decorator(f):
for k, v in attrs.iteritems():
setattr(f, k, v)
return f
for k, v in attrs.iteritems():
setattr(decorator, k, v)
return decorator
认识到这不好看,并不需要天才:
collect_d = attr_decorator(
FLAT = 1 << 0,
RECURSIVE = 1 << 1,
)
@collect_d
def collect(root, callback, mode=collect_d.RECURSIVE):
# ...
你能想到更好的方法吗?我真的很想留下“一个陈述到装饰”的东西。
答案 0 :(得分:1)
您可以使用特殊变量作为对所定义函数的引用。
class Attr(object):
def __init__(self, name): self.name = name
class Attributor(object):
def __getattr__(self, x): return Attr(x)
_ = Attributor()
def attr_decorator(**attrs):
def decorator(f):
for k, v in attrs.iteritems():
setattr(f, k, v)
f.func_defaults = tuple(attrs[t.name] if isinstance(t, Attr) else t for t in f.func_defaults)
return f
return decorator
@attr_decorator(
FLAT = 1 << 0,
RECURSIVE = 1 << 1,
)
def collect(a, b, mode=_.RECURSIVE, foo=123):
print a, b, mode, foo
collect(100,200) # 100 200 2 123
答案 1 :(得分:0)
一般来说,函数应该能够接受的常量应该存储在函数本身中。
我不同意这种说法。这些常量是函数的外部接口的一部分,用于调用者使用。将它们定义为tools
的一部分有什么问题?
COLLECT_RECURSIVE=0
COLLECT_NONRECURSIVE=1
COLLECT_OTHER=2
def collect(a,b,mode):
pass
来电者:
import tools
tools.collect(object_a, object_b, mode=tools.COLLECT_RECURSIVE)