2011-02-19 68 views
7

有沒有辦法自動綁定到self(一些)__init__方法的參數?用於自動綁定的Python裝飾器__init__參數

我的意思是這樣的:

class Person: 
    @lazy_init 
    def __init__(self, name, age, address): 
     ... 

...而不是:

class Person: 
    def __init__(self, name, age, address): 
     self.name = name 
     self.age = age 
     self.address = address 
     ... 

我不知道是否有類似的人在這種情況下,已經使用的東西。或者有什麼理由我不應該這樣做呢?

回答

4

這是絕對有可能,這裏是一個有點天真的實現:

def lazy_init(init): 
    import inspect 
    arg_names = inspect.getargspec(init)[0] 

    def new_init(self, *args): 
     for name, value in zip(arg_names[1:], args): 
      setattr(self, name, value) 
     init(self, *args) 

    return new_init 

class Person: 
    @lazy_init 
    def __init__(self, name, age): 
     pass 

p = Person("Derp", 13) 
print p.name, p.age 

一旦你開始有除了映射到性能屬性的東西,你要去雖然遇到了麻煩。你至少需要一些方法來指定哪些參數要初始化爲屬性......在這一點上,它會變得比它的價值更麻煩。

+0

感謝。我意識到,如果`__init__`方法複雜,它不值得,但簡單的方法非常普遍,我認爲擁有類似的東西是很好的。 – 2011-02-19 02:26:29

0

這裏有雲,在最簡單的形式:

def lazy_init(*param_names): 
    def ret(old_init): 
    def __init__(self, *args, **kwargs): 
     if len(args) > len(param_names): 
     raise TypeError("Too many arguments") 
     for k in kwargs: 
     if k not in param_names: 
      raise TypeError("Arg %r unexpected" % k) 
     for par, arg in zip(param_names, args): 
     setattr(self, par, arg) 
     for par, arg in kwargs.items(): 
     setattr(self, par, arg) 
     old_init(*args, **kwargs) 
    return __init__ 
    # 
    return ret 


class Q(object): 
    @lazy_init("a", "b") 
    def __init__(self, *args, **kwargs): 
    print "Original init" 

>>> q = Q(1, 2) 
Original init 
>>> q.a, q.b 
(1, 2) 

考慮制定類裝飾覆蓋__str__了。

0

initify.py由我創建:)它完全符合你的期望。

class Animal: 
    @init_args(exclude=["name"]) 
    def __init__(self, name): 
     pass 

或使用默認值:

class Animal: 
    @init_args 
    def __init__(self, name="Default name"): 
     pass 

甚至不包括繼承:

class Dog(Animal): 
    @init_args(exclude=["name"]) 
    def __init__(self, species): 
     pass 

https://github.com/prankymat/initify.py