【问题标题】:Automatically assign method arguments to instance variables自动将方法参数分配给实例变量
【发布时间】:2021-07-13 21:39:07
【问题描述】:

在 Python 中有没有一种方法可以从方法参数中声明实例变量而无需编写样板代码?

例如,有没有办法让self.fooself.bar 和所有其他参数自动声明?

def __init__(self, foo, bar, ..., last):
    self.foo = foo
    self.bar = bar
    ...
    self.last = last

【问题讨论】:

  • docs.python.org/3/library/dataclasses.html 能解决您的问题吗?
  • 我发现namedtuple 对这样的事情很有用。 docs.python.org/3/library/…
  • 您可以使用dataclasses.dataclasscollections.namedtuple,但您应该知道它们有特定的用例
  • 我现在实际上正在发现数据类。不知道这会与我的问题有关。我喜欢 namedtuple 选项,因为与 dict 或 kwarg 相比,它确实限制了可用参数,它可以允许任何东西通过。稍后需要测试这些

标签: python class variables


【解决方案1】:

确实有,虽然我认为这是一种非常丑陋的方式

class Foo:
    def __init__(self, **kwargs):
        for name, value in kwargs.items():
            setattr(self, name, value)


Foo(name='foo', baz=123, bar=True, last=None)

正如 Tim Roberts 在 cmets 中建议的那样,使用 namedtuple 是一种更好、更简洁的方式(您也可以查看 dataclasses.dataclass

【讨论】:

    【解决方案2】:

    您可以在__init__ 中使用关键字参数。例如:

    class MyClass:
        def __init__(self, **kwargs):
            for name, value in kwargs.items():
                setattr(self, name, value)
    

    然后你可以使用任何你想要的关键字参数来创建一个类:

    >>> mc = MyClass(foo=123, bar=456, baz=789)
    >>> 
    

    这些参数被分配为类实例的属性:

    >>> mc.foo
    123
    >>> mc.bar
    456
    >>> mc.baz
    789
    >>> 
    

    如果您这样做,您可能需要添加一些检查,例如将它们限制为一些已知的名称集。否则,不想要的名称可能会覆盖例如方法名称。

    或者,您可以将关键字字典直接保存在类实例中,作为单个属性。这将使类与名称隔离。例如:

    class MyClass:
        def __init__(self, **kwargs):
            self.args = kwargs
    

    然后您可以通过self.args 访问它们。

    【讨论】:

      【解决方案3】:

      解决方案 1

      正如@Tim Roberts 建议的那样,这就是使用namedtuple 完成的方法。

      from collections import namedtuple
      
      class Foo(namedtuple("Foo", ["param1", "param2"])):
          pass # Rest of code goes here
      
      my_class = Foo(1, 2)
      my_class.param1  # returns 1
      

      您甚至可以创建默认参数

      namedtuple("Foo", ["param1", "param2"], defaults=[1, 2])
      

      解决方案 2

      或者,如果您对用户传递任何随机参数感到满意,您可以使用**kwargs 设置实例变量(它不使用集合库并且可以说更容易)。

      这是一个例子

      class Foo:
          def __init__(self, **kwargs):
              super().__dict__.update(kwargs)
      
      my_class = Foo(param1=1)
      my_class.param1  # returns 1
      
      # Doesn't force you to pass the correct parameters
      random_param_class = Foo(a_made_up_parameter=2)
      random_param_class.param1  # Results in an error
      

      请记住,这些都不是标准的,通常人们只是在 __init__ 中声明实例变量。

      【讨论】:

        猜你喜欢
        • 2015-11-05
        • 2017-12-27
        • 2018-10-24
        • 2012-06-07
        • 2017-10-27
        • 1970-01-01
        • 1970-01-01
        • 2021-06-18
        • 1970-01-01
        相关资源
        最近更新 更多