2016-09-26 91 views
2

當我修飾了Python類中的綁定方法時,我需要從這個外部類的裝飾器中獲得一些信息。那可能嗎?裝飾器綁定方法訪問類和他的祖先

例如:

def modifier(func): 
    import sys 
    cls_namespace = sys._getframe(1).f_locals 
    cls_namespace['data'] # dictonary has no key 'data' 
    ... 
    return func 

class Parent: 
    data = "Hi!" 

class Child(Parent): 

    @modifier 
    def method(self): 
     pass 

cls_namespace是不data領域當前類的只是不完整的命名空間,我需要得到。

有沒有辦法讓它在裝飾者?

回答

3

函數修飾發生在類體正在執行時,此時對類本身或其基類沒有任何瞭解。這意味着modifier修飾了未綁定的函數對象,並且只有在實際調用func時纔會綁定該實例。

你可以返回一個包裝函數來代替裝飾功能,它會被代替約束,你將有機會獲得self

from functools import wraps 

def modifier(func): 
    @wraps(func) 
    def wrapper(self, *args, **kwargs): 
     # self is an instance of the class 
     self.data 
     return func(self, *args, **kwargs) 
    return wrapper 

的包裝然後將每次method稱爲被稱爲上一個實例。

如果你必須能夠訪問在類的創建時間基類,你將不得不等待,直到class Child語句完成執行。在Python 3.6之前,這隻能從類裝飾器或元類中實現;每個類都在創建類體後調用,並且您可以訪問(至少)基類。

使用類裝飾,例如:

def modifier(cls): 
    # cls is the newly created class object, including class attributes 
    cls.data 
    return cls 

@modifier 
class Child(Parent): 
    def method(self): 
     pass 

注意裝飾現在的位置。

Python 3.6增加了一個__init_subclass__ method也可以給你的訪問;該(類)方法被調用各子類是當前類的創建時間:

class Parent: 
    def __init_subclass__(cls, **kwargs): 
     # cls is a subclass of Parent 
     super().__init_subclass__(**kwargs) 
     cls.data 

    data = "Hi!" 

class Child(Parent): 
    def method(self): 
     pass 
-1

不傳遞給你的裝飾的包裝非常第一個參數將是一個對象實例(self)。感謝它,您可以訪問w =您需要的一切。

見Raphaels響應: Related issue

def wrapped(self, *f_args, **f_kwargs): 

自我是第一個參數