我刚刚开始将attrs
模块用于非常漂亮的python模块(或者类似地,我们可以使用Python 3.7 DataClasses)。我的一种常见用法是将类用作参数值的容器。我喜欢在分配参数时使用标签,并且更喜欢使用值的更清洁的属性样式引用,但是我还喜欢在将值存储在有序的dict中时具有一些不错的功能:
*
像tuple
或list
一样解包以输入函数参数**
在有必要或需要传递关键字时打开包装。我可以通过在类中添加三种方法来实现所有这些目的
@attr.s
class DataParameters:
A: float = attr.ib()
alpha: float = attr.ib()
c: float = attr.ib()
k: float = attr.ib()
M_s: float = attr.ib()
def keys(self):
return 'A', 'alpha', 'c', 'k', 'M_s'
def __getitem__(self, key):
return getattr(self, key)
def __iter__(self):
return (getattr(self, x) for x in self.keys())
然后我可以使用这样的类:
params = DataParameters(1, 2, 3, 4, 5)
result1 = function1(100, 200, *params, 300)
result2 = function2(x=1, y=2, **params)
这里的动机是数据类提供了方便和清晰。但是,出于某些原因,我不需要使用数据类来编写要编写的模块。希望函数调用应该接受简单的参数,而不是复杂的数据类。
上面的代码很好,但是我想知道是否遗漏了一些东西,因为该模式非常清晰,所以可以让我完全跳过编写函数。按我希望它们解包的顺序添加属性,并且可以根据关键字参数的属性名称将其作为键值对读取。
也许是这样的:
@addtupleanddictunpacking
@attr.s
class DataParameters:
A: float = attr.ib()
alpha: float = attr.ib()
c: float = attr.ib()
k: float = attr.ib()
M_s: float = attr.ib()
但是我不确定attrs
本身是否有某些东西可以做我没有找到的。另外,我不确定添加属性时如何保持其顺序并将其转换为keys方法。
答案 0 :(得分:3)
它没有直接集成到类中,但是the asdict
和astuple
辅助函数旨在执行这种转换。
params = DataParameters(1, 2, 3, 4, 5)
result1 = function1(100, 200, *attr.astuple(params), 300)
result2 = function2(x=1, y=2, **attr.asdict(params))
它们未集成到类本身中,因为这会使类表现为序列或映射无处不在,当TypeError
/ {{1} }。性能方面,这应该很好;无论如何,解压缩都会转换为AttributeError
/ tuple
(因为C API希望能够将非dict
或tuple
的内容直接传递给dict
/ @classmethod
def keys(cls):
return attr.fields_dict(cls).keys()
def __getitem__(self, key):
return getattr(self, key)
def __iter__(self):
return iter(attr.astuple(self, recurse=False))
在其参数上使用特定于类型的API)。
如果您确实希望类充当序列或映射,则基本上您必须做的事情,尽管您可以使用辅助函数来减少自定义代码和重复的变量名,例如:
library(purrr)
storage <-c()
d = NULL
x1 <- rdunif(1, 3, a=1)
while ( x1 != 1) {
x1<- rdunif(1, 3, a=1)
storage <-c(storage, x1)
}
storage
答案 1 :(得分:0)
扩展@ShadowRanger的想法,可以使您自己的装饰器包含attr.s和attr.ib,从而获得一种更简洁的解决方案,基本上增加了额外的处理。
import attr
field = attr.ib # alias because I like it
def parameterset(cls):
cls = attr.s(cls)
# we can use a local variable to store the keys in a tuple
# for a faster keys() method
_keys = tuple(attr.fields_dict(cls).keys())
@classmethod
def keys(cls):
# return attr.fields_dict(cls).keys()
return (key for key in _keys)
def __getitem__(self, key):
return getattr(self, key)
def __iter__(self):
return iter(attr.astuple(self, recurse=False))
cls.keys = keys
cls.__getitem__ = __getitem__
cls.__iter__ = __iter__
return cls
@parameterset
class DataParam:
a: float = field()
b: float = field()
dat = DataParam(a=1, b=2)
print(dat)
print(tuple(dat))
print(dict(**dat))
提供输出
DataParam(a=1, b=2)
(1, 2)
{'a': 1, 'b': 2}