2011-05-21 33 views
1

在描述符的__init__函數中,是否可以在描述符中訪問'所有者'類,而不必像本示例中那樣手動傳遞它?我可以在描述符的__init__方法中獲得對「所有者」類的引用嗎?

class FooDescriptor(object): 
    def __init__(self, owner): 
     #do things to owner here 
     setattr(owner, 'bar_attribute', 'bar_value') 


class BarClass(object): 
    foo_attribute = FooDescriptor(owner=BarClass) 
+2

爲什麼'setattr(owner,'bar_attribute','bar_value')'而不是'owner.bar_attribute ='bar_value''? – delnan 2011-05-21 18:43:41

+1

我很確定*沒有*(沒有調用堆棧的魔法,我期望在響應中看到)。對於像這樣調用/創建'FooDecoractor'沒有什麼特別之處。 Pythonic的方式通常是「明確的」。 – 2011-05-21 18:48:56

+0

對於調用堆棧魔術,請參閱[SO:如何獲取調用方法名稱?](http://stackoverflow.com/questions/2654113/python-how-to-get-the-callers-method-name-in - 所謂的方法) – 2011-05-21 18:51:04

回答

4

這樣做的一種方法是用元類。只要確保它真的是你想要的,並且不要盲目複製,如果你不明白它是如何工作的。

class Descriptor(object): 
    pass 

class Meta(type): 
    def __new__(cls, name, bases, attrs): 
     obj = type.__new__(cls, name, bases, attrs) 
     # obj is now a type instance 

     # this loop looks for Descriptor subclasses 
     # and instantiates them, passing the type as the first argument 
     for name, attr in attrs.iteritems(): 
      if isinstance(attr, type) and issubclass(attr, Descriptor): 
       setattr(obj, name, attr(obj)) 

     return obj 

class FooDescriptor(Descriptor): 
    def __init__(self, owner): 
     owner.foo = 42 

class BarClass(object): 
    __metaclass__ = Meta 
    foo_attribute = FooDescriptor # will be instantiated by the metaclass 

print BarClass.foo 

如果您需要傳遞其他參數,可以使用例如一個(class, args)的元組代替類,或者使FooDescriptor成爲一個裝飾器,該裝飾器將返回一個在ctor中只帶有一個參數的類。

+0

可能應該重命名傳遞給'__new __()'而不是'dict'之外的最後一個參數... – martineau 2011-05-21 19:49:24

+0

@martineau:好吧,*可能*,也許是'ns';它是'dict',因爲它對應於類型的'__dict__',不過。隱藏內置的'dict'在這裏並不是那麼可怕和非常不相關的。 – 2011-05-21 19:54:36

+0

'classdict'將是一個好名字。真正的意義在於,當* dict *出現在任何*代碼中時,恕我直言,它應該意味着內置 - 而不管目前是使用內置還是甚至可能使用內置。聰明的答案在任何情況下。 +1 – martineau 2011-05-21 20:07:20

相關問題