I'd like to automate unpacking init variables once and for all. My thought process is to unpack all and use setattr with the name of the variable as the attribute name.
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*)
Then you should be able to do:
In [3]: mysubclass = Sub('hi', 'stack', 'overflow', 'peeps')
In [4]: mysubclass.argtwo
Out[4]: 'stack'
Based on the param for 'stack' having been named argtwo
.
This way you'll automatically have access but you could still override like below:
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
Clearly I'm stuck on how to pass the actual name of the param (argone, argtwo, etc) as a string to setattr
, and also how to properly pass the args into the super init
(the args
of super(Sub, self).__init__(args*)
)
Thank you
Use kwargs instead of 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)
Then you can do:
s = Sub('a', 'b', 'c')
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)
BaseObject.__init__()
needs to discover the names of the arguments to Sub.__init__()
somehow. The explicit approach would be to pass a dictionary of arguments to BaseObject.__init__()
, as Uri Shalit suggested. Alternatively, you can use the inspect
module to do this magically, with no extra code in your subclass. That comes with the usual downsides of magic ("how'd that happen?").
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__()
This works fine as written, but if you don't define Sub.__init__()
, this will grab the arguments from the wrong place (ie, from the function where you call Sub() to create an object). You might be able to use inspect
to doublecheck that the caller is an __init__()
function of a subclass of BaseObject
. Or you could just move this code to a separate method, eg, set_attributes_from_my_arguments()
and call that from your subclasses' __init__()
methods when you want this behavior.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.