在decorator中自动分配init参数

时间:2017-07-25 14:17:03

标签: python python-decorators

我正在尝试将传递给init的所有参数分配给该类。我无法得到论据,也没有selfselfinit作为第一个arg传递过来:

class unpack_arguments(object):

    def __init__(self, f):
        self.f = f

    def __call__(self, *args, **kwargs):
        import ipdb; ipdb.set_trace()



class SomeObject(object):

    @unpack_arguments
    def __init__(self, one=1, two=2, three=3, four=4):
        pass


# At this point, you can do
#
# obj = SomeObject()
# obj.one # 1
# obj.two # 2
# obj.three # 3
# obj.four # 4


obj = SomeObject()

我尝试查找内容,但无法找到SomeObject的类实例或onetwo等关键名称:

ipdb> kwargs
{}
ipdb> args
self = <__main__.unpack_arguments object at 0x1077a3f60>
args = ()
kwargs = {}
ipdb> self.f
<function SomeObject.__init__ at 0x1077a06a8>
ipdb> dir(self.f)
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
ipdb> self.f.__defaults__
(1, 2, 3, 4)
ipdb> self.f.__kwdefaults__
ipdb> self.f.__kwdefaults__
ipdb> 

2 个答案:

答案 0 :(得分:2)

Pythonic的方法是使用**kwargs

class SomeObject(object):
    def __init__(self, **kwargs):
        for name, value in kwargs.items():
            setattr(self, name, value)


obj = SomeObject(a=1, b=2, c=3)

print(obj.__dict__)

你可能会看到对象的表示是:

{'a': 1, 'b': 2, 'c': 3}

因为你需要基类: 这是“虚拟”实现:

class SomeObject_with_init(object):
    def __init__(self, **kwargs):
        for name, value in kwargs.items():
            setattr(self, name, value)

    def my_name_is(self):
        return (self.__class__)


class SomeObject1(SomeObject_with_init):
    pass


class SomeObject2(SomeObject_with_init):
    pass


obj = SomeObject1(a=1, b=2)

obj2 = SomeObject2(test='1', test2='2')

print(obj.__dict__, obj.my_name_is())
print(obj2.__dict__, obj2.my_name_is())

这里的输出将是:

{'a': 1, 'b': 2} <class '__main__.SomeObject1'>
{'test': '1', 'test2': '2'} <class '__main__.SomeObject2'>

答案 1 :(得分:1)

你可以尝试这样的事情,虽然我更喜欢Arseniy's解决方案或使用元类而不是装饰domainIP

__init__

返回:

def unpack_arguments(func):
    def wrapper(*args, **kwargs):
        cls = args[0]
        cls.__dict__.update(kwargs)
        func(*args, **kwargs)
    return wrapper


class SomeObject(object):
    @unpack_arguments
    def __init__(self, *args, **kwargs):
        self.object = 'SomeObject'


s = SomeObject(a=1, b=2, c=3)
print (s.a)
print (s.b)
print (s.c)
print (s.object)