【问题标题】:how to ignore extra kwargs in python-attrs class如何在 python-attrs 类中忽略额外的 kwargs
【发布时间】:2020-05-16 11:51:21
【问题描述】:

例如:

@attrs
class Foo:
  a = attrib()

f = Foo(a=1, b=2)

上面的代码会抛出一个错误,因为类 Foo 没有 b 属性。但我想丢弃传递的b 值,就好像我刚刚调用了f = Foo(a=1)。在我的用例中,我有动态 dict(我想将其转换为 attr-class),我根本不需要某些键。

【问题讨论】:

    标签: python python-attrs


    【解决方案1】:
    class FromDictMixin:
        @classmethod
        def from_dict(cls, data: dict):
            return cls(**{
                a.name: data[a.name]
                for a in cls.__attrs_attrs__
            })
    
    @attrs
    class Foo(FromDictMixin):
        a = attrib()
    

    它有效,但它看起来有点难看。我希望attrs lib 有开箱即用的解决方案。

    【讨论】:

      【解决方案2】:

      这似乎更像是一个序列化/反序列化/验证的问题,并且由于多种原因,attrs 对其论点非常严格。其中一个是打字(如类型,而不是按键:)),另一个是健壮性/可调试性。忽略您可能拼错的论点可能会导致非常令人沮丧的时刻。最好将这种东西移到单独的层中。

      您可以在https://github.com/python-attrs/attrs/wiki/Extensions-to-attrs 中找到一些可能的工具。

      【讨论】:

        【解决方案3】:

        我想我想出了一个更优雅的解决方案,它允许您利用 attrs 的功能,同时调整 __init__ 逻辑。请参阅attrs documentation 了解更多信息。

        @attr.s(auto_attribs=True, auto_detect=True)
        class Foo():
            a: int
            optional: int = 3
        
            def __init__(self,**kwargs):
              filtered = {
                attribute.name: kwargs[attribute.name]
                for attribute in self.__attrs_attrs__
                if attribute.name in kwargs
              }
              self.__attrs_init__(**filtered)
        

        上面的代码允许你指定无关的关键字参数。它还允许使用可选参数。

        >>> Foo(a = 1, b = 2)
        Foo(a=1, optional=3)
        

        attrs 检测到显式 init 方法(由于 auto_detect=True)并仍然创建 init 函数,但将其称为 __attrs_init__。这允许您定义自己的 init 函数来进行预处理,然后在完成后调用 __attrs_init__

        >>> import inspect
        >>> print(inspect.getsource(Foo.__attrs_init__))
        def __attrs_init__(self, a, optional=attr_dict['optional'].default):
            self.a = a
            self.optional = optional
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-07-07
          • 2013-06-10
          • 2013-12-28
          • 2021-11-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多