class X(object):
def __init__(self, a,b,c,d):
vars = locals() # dict of local names
self.__dict__.update(vars) # __dict__ holds and object's attributes
del self.__dict__["self"] # don't need `self`
But the only solution I would recommend, besides just spelling it out, is "make a macro in your editor" ;-p
from inspect import signature, Parameter
import functools
def auto_assign(func):
# Signature:
sig = signature(func)
for name, param in sig.parameters.items():
if param.kind in (Parameter.VAR_POSITIONAL, Parameter.VAR_KEYWORD):
raise RuntimeError('Unable to auto assign if *args or **kwargs in signature.')
# Wrapper:
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
for i, (name, param) in enumerate(sig.parameters.items()):
# Skip 'self' param:
if i == 0: continue
# Search value in args, kwargs or defaults:
if i - 1 < len(args):
val = args[i - 1]
elif name in kwargs:
val = kwargs[name]
else:
val = param.default
setattr(self, name, val)
func(self, *args, **kwargs)
return wrapper
检查是否有效:
class Foo(object):
@auto_assign
def __init__(self, a, b, c=None, d=None, e=3):
pass
f = Foo(1, 2, d="a")
assert f.a == 1
assert f.b == 2
assert f.c is None
assert f.d == "a"
assert f.e == 3
print("Ok")
from functools import wraps
from inspect import Parameter, signature
def instance_variables(f):
sig = signature(f)
@wraps(f)
def wrapper(self, *args, **kwargs):
values = sig.bind(self, *args, **kwargs)
for k, p in sig.parameters.items():
if k != 'self':
if k in values.arguments:
val = values.arguments[k]
if p.kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY):
setattr(self, k, val)
elif p.kind == Parameter.VAR_KEYWORD:
for k, v in values.arguments[k].items():
setattr(self, k, v)
else:
setattr(self, k, p.default)
return wrapper
class Point(object):
@instance_variables
def __init__(self, x, y, z=1, *, m='meh', **kwargs):
pass
import inspect
def populate_self(self):
frame = inspect.getouterframes(inspect.currentframe())[1][0]
for k, v in frame.f_locals.items():
if k != 'self':
setattr(self, k, v)
class Point(object):
def __init__(self, x, y):
populate_self(self)
from fastcore.utils import store_attr
class Process:
def __init__(self, PID, PPID, cmd, FDs, reachable, user):
store_attr() # this will do the same as self.PID = PID etc.
from inspect import getargvalues, stack
def arguments():
args = getargvalues(stack()[1][0])[-1]
del args['self']
if 'kwargs' in args:
args.update(args['kwargs'])
del args['kwargs']
return args
class Process():
def __init__(self, PID, PPID, cmd, FDs, reachable, user):
# Auto update all arguments into object dictionary
self.__dict__.update(arguments())
如果没有指定 * kwargs,那么应该可以做到这一点
object = Process(1,2,3,'foo','random'...)
# all the right instances will be created
# object.PID =1
# object.PPID = 2