代码之家  ›  专栏  ›  技术社区  ›  Vince W.

如何使attrs类具有元组和dict解包,但没有额外的方法

  •  0
  • Vince W.  · 技术社区  · 6 年前

    我刚开始用 attrs

    1. * 打开包装就像 tuple 或者 list
    2. ** 当关键字传递是必要的或需要的时候解包。

    我可以通过向类中添加三个方法来实现这一切

    @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()
    

    但我不确定里面有没有什么 我还没发现它自己能做到这一点。另外,我不确定如何在添加属性时保持属性的顺序,并将其转换为keys方法。

    2 回复  |  直到 6 年前
        1
  •  5
  •   ShadowRanger    6 年前

    它没有直接集成到类中,但是 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 / AttributeError tuple / dict 无论如何(它不能传递不是 元组 口述

    如果您真的希望类充当序列或映射,则基本上必须执行您所做的操作,不过您可以使用helper函数来减少自定义代码和重复的变量名,例如:

    @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))  
    
        2
  •  1
  •   Vince W.    6 年前

    扩展@ShadowRanger的思想,您可以创建自己的包含attr.s和属性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}