Python:如何轻松地将函数参数复制到对象的字段中?

时间:2010-05-26 11:54:16

标签: python parameters

我很多时候都有成员函数将参数复制到对象的字段中。例如:

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 个答案:

答案 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__的参数被明确命名,因此很清楚正在设置哪些属性。此外,它比目前接受的答案略微简化。