Python:如何轻松将函数参数复制到对象的字段中?
很多时候,我有一些成员函数,它们的作用是把参数复制到对象的字段里。比如:
class NouveauRiches(object):
def __init__(self, car, mansion, jet, bling):
self.car = car
self.mansion = mansion
self.jet = jet
self.bling = bling
有没有什么Python的语法可以让上面的代码写起来不那么繁琐呢?可以使用 *args:
def __init__(self, *args):
self.car, self.mansion, self.jet, self.bling = args
优点:写起来不那么繁琐
缺点:函数的签名不够清晰,调用这个函数的时候需要去看函数的代码才能知道怎么用
缺点:如果传入的参数数量不对,不会抛出 TypeError
错误(但会抛出 ValueError
)
还有其他的建议吗?(无论你的建议是什么,确保调用这个函数的代码保持简单)
7 个回答
1
我不太确定这个主意是否好,但确实可以这样做:
import inspect
class NouveauRiches(object):
def __init__(self, car, mansion, jet, bling):
arguments = inspect.getargvalues(frame)[0]
values = inspect.getargvalues(frame)[3];
for name in arguments:
self.__dict__[name] = values[name]
不过,这样写起来也不是很好看,不过我想你可以把它放在一个可以重复使用的工具方法里。
2
我会选择这个方法,另外你也可以覆盖已经定义的属性。
class D:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
不过我个人还是会选择走比较长的路。想想这些:
- Explicit is better than implicit.
- Flat is better than nested.
(The Zen of Python)
2
你可以通过一个辅助方法来实现这个功能,类似下面这样:
import inspect
def setargs(func):
f = inspect.currentframe(1)
argspec = inspect.getargspec(func)
for arg in argspec.args:
setattr(f.f_locals["self"], arg, f.f_locals[arg])
使用方法:
class Foo(object):
def __init__(self, bar, baz=4711):
setargs(self.__init__)
print self.bar # Now defined
print self.baz # Now defined
这个写法看起来不太美观,可能只适合在做原型时使用。如果你打算让别人看这个代码,最好还是用明确的赋值方式。
其实可以改进一下,让它不需要把函数作为参数传入,但那样会需要更多复杂的技巧和小把戏 :)