2014-04-22 96 views
0

我有幾個類,他們有相同的實現名稱,但不同的實現。我想在一些類中修飾所有方法,但其他類不是。我曾想過繼承,但有些類有一些方法不需要進行修飾。問題是我不想一個接一個地裝飾方法,有些類需要用同一個裝飾器來裝飾,有沒有解決方法來解決它?如何裝飾班級中的所有方法?我能裝飾課堂嗎?

+0

請重新格式化您的問題和澄清點,如:「但有些班級已經不需要裝飾方法」對「我想在課堂上裝飾所有方法」 - 這聽起來像是一個悖論,也有很多語法錯誤。 –

+0

感謝提醒我。問題是我不想一個接一個地裝飾方法,有些類需要用同一個裝飾器來裝飾 –

+0

你知道你可以在整個類中使用裝飾器嗎? '@decorator; class A(object):...' – Bakuriu

回答

0

你可以啓動需要一些前綴裝飾,然後用這樣的方法都:

class Xobject(object): 

    def __init__(self, decorator): 
     for method_name in dir(self): 
      if method_name.startswith("dec_"): 
       attr = getattr(self, method_name) 
       wrapped = decorator(attr) 
       setattr(self, method_name, wrapped) 

    def dec_me_1(self): 
     print("In dec_me1") 
     return 0 

    def dec_me_2(self): 
     print("In dec_me2") 
     return 1 


def decorator(func): 

    def wrapped(*args): 
     print("TEST") 
     return func(*args) 

    return wrapped 


x = Xobject(decorator) 

x.dec_me_1() 
x.dec_me_2() 

UPDATE

您可以通過以下功能均裝飾類。在使用Python時,您應該知道Python中的class也是對象,因此您可以將其更改並傳遞給其他函數。

def decorator(func): 

    def wrapped(*args): 
     print("TEST") 
     return func(*args) 

    return wrapped 


def decorate_object(p_object, decorator): 
    for method_name in dir(p_object): 
     if method_name.startswith("dec_"): 
      attr = getattr(p_object, method_name) 
      wrapped = decorator(attr) 
      setattr(p_object, method_name, wrapped) 

decorate_object(Xobject, decorator) 

x = Xobject() 

x.dec_me_1() 
x.dec_me_2() 

而且你可以裝飾已經實例化對象相同的方法:

x = Xobject() 

x.dec_me_1() 
x.dec_me_2() 

decorate_object(x, decorator) 

x.dec_me_1() 
x.dec_me_2() 
+1

如果我的類沒有__init__方法,它們實際上是從同一個類繼承的,但我不想更改基類。 –

+0

可以使用分離的函數來裝飾以「something」開頭的每個類的方法,並將類或對象傳遞給它,這需要進行修飾。我用例子更新了我的答案。 – Alexei

+0

它的工作原理,謝謝。我知道如何解決它! :) –

0

我敢肯定,有幾個方法可供選擇,但主要領導選項有:

  • 創建一個自定義元類,其中__new__方法遍歷屬性字典,標識方法並對其進行裝飾。有關Python元類編程的示例,請參閱http://eli.thegreenplace.net/2011/08/14/python-metaclasses-by-example/。缺點:這可能比我們想要進入的更復雜。
  • 在普通班級的__init__方法中做同樣的事情。缺點:只裝飾實例方法而不裝入類或靜態方法,而且速度較慢,因爲每次創建新實例時都會運行該方法。
  • 做它的類外:

    class Foo(object): 
        def bar(self): 
        print 'bar' 
    
    for name, ref in vars(Foo): 
        if callable(ref): ... 
    

    缺點:你只有一次機會做正確的事:在導入時。子類不會被修改。

  • 在類級裝飾器中執行此操作。與在課堂以外一樣的缺點(我認爲)。

+0

是的,我也想過元類,它很複雜,很難閱讀,所以也許我只是一個接一個地添加裝飾器。謝謝 –

0

在某些時候,你必須明確什麼被包裹,什麼不包含。

如果我理解正確的話,你,我想你可以做這樣的事情:

def wrapper(func): 
    def inner(*args, **kwargs): 
     print "%s was called" func.__name__ 
     return func(*args, **kwargs) 
    return inner 

class A(object): 
    def foo(self): 
     print "foo called" 
    def bar(self): 
     print "BAR CALLED" 

class B(A): 
    @wrapper 
    def foo(self): 
     super(B, self).foo() 

class C(A): 
    @wrapper 
    def bar(self): 
     super(C, self).bar() 

Stick = A() 
Dave = B() 
Jupiter = C() 

Jupiter.foo() #prints "foo called" 
Jupiter.bar() #prints "bar wrapped" and "BAR CALLED"