2017-07-25 75 views
1

我試圖將傳遞給init的所有參數分配給類。我不能得到的參數,也沒有階級self(該selfinit被作爲第一個參數傳遞):在裝飾器中自動分配初始化參數

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的類實例或類似one鍵名,two等:

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> 
+0

能否請你描述的更大的問題你要解決這個問題呢?你有沒有嘗試過讓你的裝飾器成爲一個函數 - 這更容易理解? – 9000

+0

不完全一樣的東西,但對於類似的模式,看看'attrs'模塊(在pypi上)... –

+0

我想分配給裝飾器中的任何類init的任何kwargs。我不介意任何一種方式,我只是從來沒有使用函數裝飾器,他們更困惑 – codyc4321

回答

2

Python的方式做到這一點是使用**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'> 
+0

這是目標,但我想要一個裝飾者或至少一個子類 – codyc4321

1

你可以嘗試這樣的事情,但我更喜歡Arseniy's解決方案或使用元類而不是裝飾__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) 

返回:

1 
2 
3 
SomeObject