2011-03-25 11 views
30

मुझे कक्षा के ऑब्जेक्ट्स (पूर्णांक, स्ट्रिंग्स इत्यादि) के अलावा कुछ भी बड़े वर्गों के घटक के साथ एक परियोजना विरासत में मिली है। मैं यह जांचने में सक्षम होना चाहता हूं कि गुणों की सूची मैन्युअल रूप से परिभाषित करने के लिए एक विशेषता मौजूद है या नहीं।पायथन: क्या मानक वाक्यविन्यास का उपयोग करके कक्षा को पुन: सक्षम करना संभव है?

क्या यह पाइथन कक्षा मानक वाक्यविन्यास का उपयोग कर अपने आप को सक्षम कर सकता है? यही है, मैं पहले कक्षा का उदाहरण बनाने के बिना for attr in Foo: (या यहां तक ​​कि if attr in Foo) का उपयोग कर कक्षा के सभी विशेषताओं में पुन: प्रयास करने में सक्षम होना चाहता हूं। मुझे लगता है कि मैं __iter__ को परिभाषित करके ऐसा कर सकता हूं, लेकिन अब तक मैंने जो कुछ भी खोजा है, उसमें मैंने काफी प्रबंधन नहीं किया है।

मैं एक __iter__ विधि इतनी तरह जोड़कर जो मैं चाहता से कुछ हासिल कर लिया है:

class Foo: 
    bar = "bar" 
    baz = 1 
    @staticmethod 
    def __iter__(): 
     return iter([attr for attr in dir(Foo) if attr[:2] != "__"]) 

बहरहाल, यह काफी की पूर्ति नहीं करता मैं के लिए क्या देख रहा हूँ:

>>> for x in Foo: 
...  print(x) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'classobj' object is not iterable 

फिर भी, यह काम करता है:

>>> for x in Foo.__iter__(): 
...  print(x) 
bar 
baz 

उत्तर

47

वर्ग ही (यह मानते हुए अजगर 2.x) के बजाय metaclass को __iter__ जोड़ें:

class Foo(object): 
    bar = "bar" 
    baz = 1 
    class __metaclass__(type): 
     def __iter__(self): 
      for attr in dir(Foo): 
       if not attr.startswith("__"): 
        yield attr 

अजगर 3.x के लिए, का उपयोग

class MetaFoo(type): 
    def __iter__(self): 
     for attr in dir(Foo): 
      if not attr.startswith("__"): 
       yield attr 

class Foo(metaclass=MetaFoo): 
    bar = "bar" 
    baz = 1 
+1

अच्छा। कृपया आप समझा सकते हैं कि ओपी का दृष्टिकोण क्यों काम नहीं करता है? धन्यवाद। – NPE

+6

@aix: कारण ओपी का दृष्टिकोण काम नहीं करता है कि '__iter__' विधि केवल कक्षा के * उदाहरण * के लिए काम करती है। यह मेटाक्लास, यानी कक्षा के उदाहरणों तक '__iter__' विधि को बाधित करता है। – nmichaels

+0

@nmichaels यह समझ में आता है, स्पष्टीकरण के लिए धन्यवाद। – NPE

7

आप पुनरावृति कर सकते हैं for attr in (elem for elem in dir(Foo) if elem[:2] != '__') के साथ वर्ग के अनधिकृत विशेषताओं पर।

एक कम भयानक तरीका है कि वर्तनी के लिए है:

def class_iter(Class): 
    return (elem for elem in dir(Class) if elem[:2] != '__') 

तो

for attr in class_iter(Foo): 
    pass 
+0

भी अपडेट किया है मुझे यह स्वीकार करना होगा कि मैं इस समाधान को पसंद करता हूं जो ओपी में से एक की तुलना में अधिक पायथनिक दिखता है। लेकिन क्या उसने अपनी समस्या का समाधान नहीं किया है, मैंने –

5

यह कैसे हम एक वर्ग वस्तु iterable बनाते हैं। iter और अगली() विधि के साथ कक्षा प्रदान करें, फिर आप कक्षा विशेषताओं या उनके मूल्यों पर पुन: प्रयास कर सकते हैं। अगर आप चाहें तो अगली() विधि छोड़ सकते हैं, या आप अगले() को परिभाषित कर सकते हैं और स्टॉपइटरेशन को बढ़ा सकते हैं कुछ हालत

उदाहरण के लिए: वर्ग बुक की विशेषता मान से अधिक

class Book(object): 
     def __init__(self,title,author): 
      self.title = title 
      self.author = author 

     def __iter__(self): 
      for each in self.__dict__.keys(): 
       yield self.__getattribute__(each) 

>>> book = Book('The Mill on the Floss','George Eliot') 
>>> for each in book: each 
... 
'George Eliot' 
'The Mill on the Floss' 

इस वर्ग दोहराता। एक कक्षा वस्तु को इसे getitem विधि प्रदान करके इसे पुन: प्रयोज्य बनाया जा सकता है। उदाहरण के लिए:

class BenTen(object): 
    def __init__(self, bentenlist): 
     self.bentenlist = bentenlist 

    def __getitem__(self,index): 
     if index <5: 
      return self.bentenlist[index] 
     else: 
      raise IndexError('this is high enough') 

>>> bt_obj = BenTen([x for x in range(15)]) 
>>>for each in bt_obj:each 
... 
0 
1 
2 
3 
4 

अब जब Benten वर्ग की वस्तु, में एक के लिए में पाश, GetItem succesively उच्च सूचकांक मूल्य के साथ कहा जाता है प्रयोग किया जाता है जब तक यह IndexError को जन्म देती है।

+0

+1 नहीं किया है, यह कक्षा के _instance_ के गुणों पर पुनरावृत्त करता है (यानी 'पुस्तक' पुस्तक (...) 'में 'पुस्तक''; सवाल _class_ विशेषताओं पर सीधे पुनरावृत्ति के बारे में है (यानी 'पुस्तक पुस्तक' (पुस्तक) में 'पुस्तक': ')। – multipleinterfaces

+0

हालांकि यह ओपी के सवाल का जवाब नहीं है, लेकिन इससे मुझे मदद मिली क्योंकि मैं इसे खोजने योग्य वर्ग की खोज करते समय इसकी तलाश कर रहा था। – dlite922

संबंधित मुद्दे