python 自动将方法参数赋给示例变量[重复]

bpzcxfmw  于 2023-09-29  发布在  Python
关注(0)|答案(5)|浏览(93)

此问题已在此处有答案

How can I automatically assign init arguments to attributes?(6个回答)
昨天关门了。
Python中有没有一种方法可以从方法参数声明示例变量,而不需要编写样板文件?
例如,是否有一种方法可以自动声明self.fooself.bar和所有其他参数?

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

of1yzvn41#

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

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在评论中建议的那样,使用namedtuple是一种更好、更干净的方法(您也可以看看dataclasses.dataclass)。

eh57zj3b

eh57zj3b2#

您可以在__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访问它们。

bgtovc5b

bgtovc5b3#

方案一

正如@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])

方案二

或者,如果您对用户传递任何随机参数没有意见,您可以使用**kwargs来设置示例变量(它不使用collections库,并且可以说更容易)。
这里有一个例子

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__中声明示例变量。

gojuced7

gojuced74#

老实说,如果你有一组固定的输入,你可以使用这个:

from inspect import getargvalues, stack

def arguments():
    args = getargvalues(stack()[1][0])[-1]
    del args['self']
    if 'kwargs' in args:
        args.update(args['kwargs'])
        del args['kwargs']
    return args

class myClass():
    def __init__(self, foo, bar, ..., last):
        # Auto update all arguments into object dictionary
        self.__dict__.update(arguments())

如果不指定 *kwargs,这应该可以完成

object = myClass(1,2,3,'foo','random')
# all the right instances will be created
# object.foo =1
# object.bar = 2
cwxwcias

cwxwcias5#

无论你的方法签名看起来如何(是否有预定义的位置和/或关键字参数),你都可以使用locals()(在声明其他局部变量之前):

def __init__(self, foo=3, bar='f', *args, **kwargs):
  for name, value in locals().items():
    if name != 'self': setattr(self, name, value)

这样,* 所有 * 参数都被复制到示例变量。

相关问题