есть такой принцип - явное, лучше неявного, помоему это правильно, что нужно указывать объект.
по поводу кода - есть концепт, контекстной работы с объектами через декораторы и контекстные менеджеры:
вот декоратор:
class A: pass
# объект, на который навешиваются аттрибуты
some_A_inst = A()
# это декоратор
def arg_space(obj):
def setter(fnc):
args = fnc()
for n,v in args.items():
setattr(obj,n,v)
return setter
# функция, все ее внутренние переменные отправятся в декоратор
@arg_space(some_A_inst)
def set_args():
a = 1
b = "owl"
c = (4,8,4)
return vars()
print( some_A_inst.__dict__ ) # 'a': 1, 'b': 'owl', 'c': (4, 8, 4)}
print( some_A_inst.c ) # (4,8,4)
а это концепт контекстного менеджера, он только для иллюстрации, в коде это не повторять, потому-что тут используется глобальное пространство имен - и это неоправдано целью и гарантирует возникновение проблем с переменными:
class arg_space:
def __init__(self, obj):
self.obj = obj
def __enter__(self):
self.__s1 = set(globals().keys())
return self
def __exit__(self, exc_type, exc_value, exc_tb):
sd = set(globals().keys()) ^ self.__s1
gl = globals()
for at in sd:
setattr(self.obj, at, gl[at])
class A: pass
some_A_inst = A()
with arg_space(some_A_inst):
a = 1
b = "owl"
c = (4,8,4)
print( some_A_inst.__dict__ ) # 'a': 1, 'b': 'owl', 'c': (4, 8, 4)}
p.s. для хранения атрибутов есть NamedTuple, SimpleNamespace, Dataclasses