你如何在init的python类中自动设置自我属性?

时间:2016-01-13 22:05:11

标签: python python-3.x initialization subclass

我想一劳永逸地自动解压缩init变量。我的思维过程是解压缩所有并使用setattr和变量的名称作为属性名称。

class BaseObject(object):
    def __init__(self, *args):
        for arg in args:
            setattr(self, argname, arg)

class Sub(BaseObject):
    def __init__(self, argone, argtwo, argthree, argfour):
        super(Sub, self).__init__(args*)

然后你应该能够做到:

In [3]: mysubclass = Sub('hi', 'stack', 'overflow', 'peeps')

In [4]: mysubclass.argtwo
Out[4]: 'stack'

基于'stack'的参数被命名为argtwo

通过这种方式,您可以自动获得访问权限,但仍然可以覆盖如下:

class Sub(BaseObject):
    def __init__(self, argone, argtwo, argthree, argfour):
        super(Sub, self).__init__(arglist)
        clean_arg_three = process_arg_somehow(argthree)
        self.argthree   = clean_arg_three

显然,我坚持如何将param的实际名称(argone,argtwo等)作为字符串传递给setattr,以及如何正确地将args传递给super initargs)的super(Sub, self).__init__(args*)

谢谢

3 个答案:

答案 0 :(得分:1)

使用kwargs而不是args

class BaseObject(object):
    def __init__(self, **kwargs):
        for argname, arg in kwargs.iteritems():
            setattr(self, argname, arg)

class Sub(BaseObject):
    def __init__(self, argone, argtwo, argthree, argfour):
        super(Sub, self).__init__(argone=argone, argtwo=argtwo,   argthree=argthree)

然后你可以这样做:

s = Sub('a', 'b', 'c')

答案 1 :(得分:1)

import inspect

class BaseObject(object):
    def __init__(self, args):
        del args['self']
        self.__dict__.update(args)

class Sub(BaseObject):
    def __init__(self, argone, argtwo, argthree, argfour):
        args = inspect.getargvalues(inspect.currentframe()).locals
        super(Sub, self).__init__(args)

s = Sub(1, 2, 3, 4)

答案 2 :(得分:1)

Sub.__init__()需要以某种方式发现BaseObject.__init__()的参数名称。正如Uri Shalit建议的那样,明确的方法是将参数字典传递给inspect。或者,您可以使用import inspect class BaseObject(object): def __init__(self): frame = inspect.stack()[1][0] args, _, _, values = inspect.getargvalues(frame) for key in args: setattr(self, key, values[key]) class Sub(BaseObject): def __init__(self, argone, argtwo, argthree, argfour): super(Sub, self).__init__() 模块神奇地执行此操作,而子类中不需要额外的代码。这伴随着魔法的通常缺点("如何发生?' d。)。

Sub.__init__()

这样写得很好但是如果你没有定义inspect,这将从错误的地方(即从你调用Sub()的函数中获取参数来创建一个对象) 。您可以使用__init__()来重复检查调用者是BaseObject的子类的set_attributes_from_my_arguments()函数。或者您可以将此代码移动到单独的方法,例如__init__(),并从您的子类中调用该方法。当你想要这种行为时,new方法。