我很多时候都有成员函数将参数复制到对象的字段中。例如:
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
}
还有其他想法吗? (无论您的建议是什么,请确保调用该函数的代码保持简单)
答案 0 :(得分: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)
答案 1 :(得分: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
这不太好,它应该只在原型设计时使用。如果您打算让其他人阅读,请使用明确的作业。
可能可以改进,不需要将函数作为参数,但这将需要更丑陋的黑客和欺骗:)
答案 2 :(得分:1)
尝试类似
的内容d = dict(locals())
del d['self']
self.__dict__.update(d)
当然,它返回所有局部变量,而不仅仅是函数参数。
答案 3 :(得分: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]
它也读得不好,不过我想你可以将它放在一个重用的实用方法中。
答案 4 :(得分:0)
您可以尝试这样的事情:
class C(object):
def __init__(self, **kwargs):
for k in kwargs:
d = {k: kwargs[k]}
self.__dict__.update(d)
或者使用setattr,你可以这样做:
class D(object):
def __init__(self, **kwargs):
for k in kwargs:
setattr(self, k, kwargs[k])
然后两者都可以被称为:
myclass = C(test=1, test2=2)
所以你必须使用** kwargs,而不是* args。
答案 5 :(得分:0)
我有时会为那些行为“束状”的类做这件事,也就是说,他们有一堆可自定义的属性:
class SuperClass(object):
def __init__(self, **kw):
for name, value in kw.iteritems():
if not hasattr(self, name):
raise TypeError('Unexpected argument: %s' % name)
setattr(self, name, value)
class SubClass(SuperClass):
instance_var = None # default value
class SubClass2(SubClass):
other_instance_var = True
@property
def something_dynamic(self):
return self._internal_var
@something_dynamic.setter # new Python 2.6 feature of properties
def something_dynamic(self, value):
assert value is None or isinstance(value, str)
self._internal_var = value
然后,您可以致电SubClass2(instance_var=[], other_instance_var=False)
,并且无需在其中任何一个中定义__init__
即可。您也可以使用任何财产。虽然这允许你覆盖你可能不想要的方法(因为它们像实例变量一样为hasattr()
返回True)。
如果您添加任何property
或其他其他描述符,它将正常工作。您可以使用它来进行类型检查;与__init__
中的类型检查不同,它会在值更新时应用。请注意,除非覆盖__init__
,否则不能使用任何位置参数,因此有时候自然位置参数将无效。 formencode.declarative涵盖了这个问题和其他问题,可能是彻底的,我不建议你尝试(回想起来我不认为这是值得的)。
请注意,使用self.__dict__
的任何配方都不会尊重属性和描述符,如果您一起使用它们,您将会得到奇怪且意外的结果。我仅建议使用setattr()
设置属性,从不 self.__dict__
。
此配方也没有给出非常有用的签名,而一些做框架和功能内省的配方也是如此。使用some work,可以动态生成一个澄清参数的__doc__
......但是我不确定是否值得添加更多移动部件。
答案 6 :(得分:0)
我是以下
的粉丝import inspect
def args_to_attrs(otherself):
frame = inspect.currentframe(1)
argvalues = inspect.getargvalues(frame)
for arg in argvalues.args:
if arg == 'self':
continue
value = argvalues.locals[arg]
setattr(otherself, arg, value)
class MyClass:
def __init__(self, arga="baf", argb="lek", argc=None):
args_to_attrs(self)
__init__
的参数被明确命名,因此很清楚正在设置哪些属性。此外,它比目前接受的答案略微简化。