自动将方法参数分配给实例变量

问题描述 投票:0回答:5

Python 中有没有一种方法可以从方法参数中声明实例变量,而不需要编写样板文件?

例如,有没有办法让

self.foo
self.bar
和所有其他参数自动声明?

def __init__(self, foo, bar, ..., last):
    self.foo = foo
    self.bar = bar
    ...
    self.last = last
python class variables
5个回答
0
投票

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

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


0
投票

您可以在

__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
访问它们。


0
投票

解决方案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__


0
投票

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

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


0
投票

无论你的方法签名是什么样的(无论是否预定义了位置和/或关键字参数),你总是可以使用

locals()
(在声明其他局部变量之前):

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

这样,所有参数都会复制到实例变量。

© www.soinside.com 2019 - 2024. All rights reserved.