Python 中有没有一种方法可以从方法参数中声明实例变量,而不需要编写样板文件?
例如,有没有办法让
self.foo
、self.bar
和所有其他参数自动声明?
def __init__(self, foo, bar, ..., last):
self.foo = foo
self.bar = bar
...
self.last = last
确实有,虽然我认为这是一种非常丑陋的方式
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)
namedtuple
是一种更好、更干净的方法(您也可以看看 dataclasses.dataclass
)
您可以在
__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
访问它们。
正如 @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
设置实例变量(不使用集合库,并且可以说更容易)。
这是一个例子
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__
。
说实话,如果你有一组固定的输入,你可以使用这个:
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
无论你的方法签名是什么样的(无论是否预定义了位置和/或关键字参数),你总是可以使用
locals()
(在声明其他局部变量之前):
def __init__(self, foo=3, bar='f', *args, **kwargs):
for name, value in locals().items():
if name != 'self': setattr(self, name, value)
这样,所有参数都会复制到实例变量。