2010-07-02 18 views
17
inspect.getmembers(object[, predicate]) 

किसी ऑब्जेक्ट के सभी सदस्यों को नाम से क्रमबद्ध (नाम, मूल्य) जोड़े की सूची में वापस करें।निरीक्षण.getmembers क्रम में?

मैं इस विधि का उपयोग करना चाहता हूं, लेकिन मैं नहीं चाहता कि सदस्यों को सॉर्ट किया जाए। मैं चाहता हूं कि वे उसी क्रम में लौटे जो उन्हें परिभाषित किया गया था। क्या इस विधि का कोई विकल्प है?


उपयोग मामला:

तो कुछ ऐसे स्वरूप बनाना:

class RegisterForm(Form): 
    username = Field(model_field='username', filters=validators.minlength(3)) 
    password1 = Field(model_field='password', widget=widgets.PasswordInput) 
    password2 = Field(widget=widgets.PasswordInput) 
    first_name = Field(model_field='first_name') 
    last_name = Field(model_field='last_name') 
    address = SubForm(form=AddressForm, model_field='address') 

मैं क्षेत्रों में एक ही क्रम में वे परिभाषित कर रहे हैं में प्रदान की जा करना चाहते हैं।

+2

क्यों -1 के साथ मिल जा सकता है? इस क्यू के साथ क्या गलत है? – mpen

+1

आप ऐसा क्यों करना चाहते हैं? – Daenyth

+1

@ डेनथ: अद्यतन क्यू डब्ल्यू/उपयोग केस। – mpen

उत्तर

11

आप तरीकों के लिए लाइन नंबर, यकीन है कि अन्य सदस्यों के बारे में नहीं लगता है चारों ओर खुदाई कर सकते हैं:

import inspect 

class A: 
    def one(self): 
     pass 

    def two(self): 
     pass 

    def three(self): 
     pass 

    def four(self): 
     pass 

def linenumber_of_member(m): 
    try: 
     return m[1].im_func.func_code.co_firstlineno 
    except AttributeError: 
     return -1 

a = A() 
l = inspect.getmembers(a) 
print l 
l.sort(key=linenumber_of_member) 
print l 

प्रिंट:

[('__doc__', None), ('__module__', '__main__'), ('four', <bound method A.four of <__main__.A instance at 0x0179F738>>), ('one', <bound method A.one of <__main__.A instance at 0x0179F738>>), ('three', <bound method A.three of <__main__.A instance at 0x0179F738>>), ('two', <bound method A.two of <__main__.A instance at 0x0179F738>>)] 
[('__doc__', None), ('__module__', '__main__'), ('one', <bound method A.one of <__main__.A instance at 0x0179F738>>), ('two', <bound method A.two of <__main__.A instance at 0x0179F738>>), ('three', <bound method A.three of <__main__.A instance at 0x0179F738>>), ('four', <bound method A.four of <__main__.A instance at 0x0179F738>>)] 
+0

+1। दिलचस्प विचार – Skurmedel

5

विशेषताएं (तरीकों और अन्य सदस्यों के) की एक वस्तु है आम तौर पर एक ऑब्जेक्ट के विशेष __dict__ विशेषता के माध्यम से देखा जाता है जो एक मानक पायथन शब्दकोश है। यह किसी भी विशिष्ट आदेश की गारंटी नहीं देता है।

एक विशेषता में वस्तु की __dict__ वर्ग के बजाय खोजा गया है (जहाँ तरीकों आमतौर पर रहते हैं) और इतने पर जब तक पूरी विरासत श्रृंखला चल कर दिया गया है नहीं पाया जाता है तो।

>>> class Klass(): 
...  def test(self): 
...    pass 
... 
>>> k = Klass() 
>>> k.__dict__ 
{} 
>>> k.__class__.__dict__.items() 
[('test', <function test at 0x00000000024113C8>), ('__dict__', <attribute '__dic 
t__' of 'Klass' objects>), ('__module__', '__main__'), ('__weakref__', <attribut 
e '__weakref__' of 'Klass' objects>), ('__doc__', None)] 

मैं Klass में एक निर्माता (__init__) रख दिया और self यह है जाएगा के माध्यम से एक विशेषता की स्थापना की है चाहेंगे:

यहाँ कुछ कस्टम इंटरैक्टिव शीघ्र से किया यह (पायथन 3.1) वर्णन करने के लिए निरीक्षण है k.__dict__ में दिखाया गया है।

आप एक कस्टम मेटाक्लास का उपयोग कर इसे बाधित कर सकते हैं। प्रलेखन में एक उदाहरण है जो वास्तव में वही करता है जो आप चाहते हैं।

OrderedClass example के लिए इस पृष्ठ के नीचे देखें।

पता नहीं है कि आपके पास पाइथन का कौन सा संस्करण है, इसलिए मैंने नवीनतम माना।

+0

पायथन 2.6। तो सदस्यों को क्रम में रखने के लिए मुझे मेटाक्लास का उपयोग करना होगा? – mpen

+0

@ मार्क: मुझे जोड़ा जाना चाहिए था, आप अभी भी निरीक्षण या डीआईआर का उपयोग नहीं कर सकते हैं, क्योंकि 'टाइप' ऑब्जेक्ट अंत में सीधे ऊपर शब्दकोश का उपयोग करेगा। लेकिन वे 'सदस्यों' नामक उप-वर्गों पर एक कस्टम विशेषता के माध्यम से आदेश देते हैं जिन्हें आदेश दिया जाता है। – Skurmedel

+1

@ स्कुरमेडेल: क्या हम स्पष्ट रूप से आदेशित आदेश के साथ '__dict__' को प्रतिस्थापित नहीं कर सके, हालांकि कोई फर्क नहीं पड़ता कि मुझे आदेश दिया गया सदस्य चर है। – mpen

3

मुझे नहीं लगता कि पायथन 2.6 में __prepare__ विधि है, इसलिए मैं किसी ऑर्डर के लिए डिफ़ॉल्ट dict को स्वैप नहीं कर सकता। हालांकि, मैं इसे metaclass और __new__ विधि का उपयोग करके प्रतिस्थापित कर सकता हूं। लाइन नंबरों का निरीक्षण करने के बजाय, सोचें कि एक सृजन काउंटर का उपयोग करने के लिए यह आसान और अधिक कुशल है।

class MetaForm(type): 
    def __new__(cls, name, bases, attrs): 
     attrs['fields'] = OrderedDict(
      sorted(
       [(name, attrs.pop(name)) for name, field in attrs.items() if isinstance(field, Field)], 
       key=lambda t: t[1].counter 
      ) 
     ) 
     return type.__new__(cls, name, bases, attrs) 

class Form(object): 
    __metaclass__ = MetaForm 

class Field(object): 
    counter = 0 
    def __init__(self): 
     self.counter = Field.counter 
     Field.counter += 1 
+0

यदि आपके पास ऑब्जेक्ट्स के विभिन्न वर्ग हैं और उन सभी के बीच ऑर्डर बनाए रखना चाहते हैं तो यह काम नहीं करता है ... मुझे लगता है कि मैं उन्हें सब कुछ बना सकता हूं हालांकि 'OrderedObject' से उत्तराधिकारी। – mpen

+0

धन्यवाद, यह एक शानदार विचार है, वास्तव में मुझे अपनी परियोजना के लिए क्या चाहिए – velis

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