2010-05-30 17 views
43

पाइथन में यह बताने का एक आसान तरीका है कि कुछ अनुक्रम नहीं है? - हालांकि यह "को खारिज कर दिया" अन्य गैर दृश्यों लेकिन उस चेक सेट और शब्दकोशों "स्वीकार करता है", if x is not sequence लेकिन अजगर किपायथन: जांचें कि कोई ऑब्जेक्ट अनुक्रम है

+2

संबंधित: अजगर में, मैं कैसे तय करते हैं कि एक चर Iterable है? http://stackoverflow.com/questions/1952464/in-python-how-do-i-determine-if-a-variable-is-iterable/1952481#1952481 – miku

+7

हाँ, लेकिन iterables नहीं सभी iterables रहे हैं, जबकि सभी दृश्यों रहे हैं अनुक्रम (सेट और डिक्टर्स अंतर्निहित कंटेनर हैं जो अनुक्रम नहीं हैं, उदाहरण के लिए)। –

उत्तर

57

iter(x) पसंद नहीं आया एक TypeError अगर x पर दोहराया नहीं जा सकता बढ़ा देंगे: मैं बस करने की कोशिश की जैसे None और संख्याएं।

अन्य हाथ पर, तार (जो सबसे अनुप्रयोगों "एकल आइटम" बल्कि दृश्यों से विचार करना चाहते) तथ्य दृश्यों में हैं (हां, तो किसी भी परीक्षा, जब तक स्ट्रिंग्स के लिए specialcased, पुष्टि करने के लिए वे कर रहे हैं कि जा रहा है) । इसलिए, ऐसे सरल चेक अक्सर पर्याप्त नहीं होते हैं।

पायथन 2.6 और बेहतर, सार आधार वर्ग पेश किए गए थे, और अन्य शक्तिशाली सुविधाओं के बीच वे इस तरह के "श्रेणी जांच" के लिए अधिक अच्छे, व्यवस्थित समर्थन प्रदान करते हैं।

>>> import collections 
>>> isinstance([], collections.Sequence) 
True 
>>> isinstance((), collections.Sequence) 
True 
>>> isinstance(23, collections.Sequence) 
False 
>>> isinstance('foo', collections.Sequence) 
True 
>>> isinstance({}, collections.Sequence) 
False 
>>> isinstance(set(), collections.Sequence) 
False 

आप ध्यान दें जाएगा तार अभी भी माना "एक दृश्य" (क्योंकि वे हैं) कर रहे हैं, लेकिन कम से कम आप रास्ते से हट dicts और सेट मिलता है। आप में से "दृश्यों जा रहा है" अपने अवधारणा से तार बाहर करना चाहते हैं, तो आप collections.MutableSequence इस्तेमाल कर सकते हैं (लेकिन यह भी tuples है, जो, तार की तरह, दृश्यों रहे हैं, लेकिन परिवर्तनशील नहीं हैं शामिल नहीं है), या यह स्पष्ट रूप से कार्य करें:

import collections 

def issequenceforme(obj): 
    if isinstance(obj, basestring): 
     return False 
    return isinstance(obj, collections.Sequence) 

स्वाद का मौसम, और गर्म सेवा! -)

+10

ध्यान दें कि यह कोड उदाहरण उन ऑब्जेक्ट्स के गलत परिणाम देगा जो अनुक्रम प्रोटोकॉल को लागू करते हैं लेकिन 'संग्रह। सिकेंस' एबीसी शामिल नहीं करते हैं। –

+4

हाँ: सरल एबीसी से अलग, अनुक्रम '__subclasshook__' वर्ग विधि को लागू नहीं करता है, इसलिए यह कभी भी उस वर्ग को पहचान नहीं पाएगा जिसने इसके साथ' पंजीकरण 'नहीं किया है (या इससे प्राप्तकर्ता) - यह अनिवार्य रूप से असंभव होगा आत्मनिरीक्षण से बताने के लिए कि क्या कक्षा का '__getitem__' पूर्णांक और स्लाइस स्वीकार करता है, गलत इंडेक्स पर' इंडेक्स एरर 'बढ़ाता है - आपको केवल 'dict' और' set' को रद्द करने की आवश्यकता होती है, अनिवार्य रूप से (_ _ _ _ _ अनुक्रम को लागू करने के लिए प्रतीत होता है) प्रोटोकॉल "अगर आप आत्मनिरीक्षण करते हैं ... लेकिन फिर बाहर नहीं निकलें! -)। –

+0

सेट्स को रद्द करना बहुत आसान है, क्योंकि उनके पास '__getitem__' नहीं है, लेकिन मैपिंग बहुत कठिन हैं। मैंने देखा है कि सबसे अच्छी जांच शायद 'keys' की तलाश में है, जैसे 'dict.update' करता है, लेकिन यह अभी भी वांछित होने के लिए बहुत कुछ छोड़ देता है। – user2357112

4

आप ऐसा क्यों कर रहे हैं? यहां सामान्य तरीका एक निश्चित प्रकार की चीज़ (एक अनुक्रम या संख्या या फ़ाइल जैसी वस्तु आदि) की आवश्यकता होती है और फिर कुछ भी जांच किए बिना इसका उपयोग करें। पायथन में, हम आम तौर पर अर्थपूर्ण जानकारी ले जाने के लिए कक्षाओं का उपयोग नहीं करते हैं बल्कि परिभाषित विधियों का उपयोग करते हैं (इसे "बतख टाइपिंग" कहा जाता है)। हम एपीआई भी पसंद करते हैं जहां हम जानते हैं कि वास्तव में क्या उम्मीद करनी है; यदि आप फ़ंक्शन कैसे काम करते हैं, तो यह बदलना चाहते हैं कि कीवर्ड तर्क, प्रीप्रोकैसिंग, या किसी अन्य फ़ंक्शन को परिभाषित करना।

+3

यह एक असाइनमेंट बाधा है। यदि हमारे द्वारा पारित तर्क एक int, लंबा या अनुक्रम नहीं है, तो हमें 'TypeError' – nicotine

+1

@nicotine बढ़ाने की आवश्यकता है, यह पहचानें कि यह असाइनमेंट आमतौर पर गैर-रंगीन और नाजुक डिज़ाइन को इंगित करता है। सामान्य मामले पर विचार करें, जहां एक वस्तु बिल्कुल एक प्रकार की चीज होनी चाहिए। यदि एक पैरामीटर अनुक्रम माना जाता है लेकिन आप एक int प्राप्त करते हैं, जब आप इसे इंडेक्स या फिर से सक्रिय करते हैं तो आपको पहले से ही 'TypeError' मिल जाएगा। इसी प्रकार, यदि आपने एक अनुक्रम के साथ पूर्णांक संचालन करने की कोशिश की है तो आप करेंगे। –

+0

एक सतत एपीआई (जब भी संभव हो) प्रदान करता है जो अपेक्षा करता है कि केवल एक ही प्रकार की चीज आपको सरल कोड लिखने देती है जो कुछ गलत होने पर त्रुटियों को उठाती है लेकिन इसमें अधिक मजबूत है कि यह उन प्रकारों का समर्थन करता है जिनके बारे में आपने नहीं सोचा था, लेकिन सत्य को पूरा करते हैं लक्ष्य –

6

Python 2.6.5 documentation निम्न अनुक्रम प्रकारों का वर्णन करता है: स्ट्रिंग, यूनिकोड स्ट्रिंग, सूची, ट्यूपल, बफर, और xrange।

def isSequence(obj): 
    return type(obj) in [str, unicode, list, tuple, buffer, xrange] 
+14

इस उत्तर के साथ समस्या यह है कि यह उन अनुक्रमों का पता नहीं लगाएगा जो कि बिल्टिन प्रकार नहीं हैं। एक पायथन "अनुक्रम" कोई वस्तु है जो अनुक्रम संचालन के जवाब देने के लिए आवश्यक विधियों को लागू करती है। – intuited

+3

इसके अलावा, उप-वर्गों का समर्थन करने के लिए 'टाइप' के बजाय' isinstance' का उपयोग करें। – bfontaine

-3

क्यों और क्यों

लंबाई हो रही कोशिश से पूछें कि अपवाद वापसी झूठी

def haslength(seq): 
    try: 
     len(seq) 
    except: 
     return False 
    return True 
+1

ए 'सेट' की लंबाई है लेकिन अनुक्रम नहीं है। – bfontaine

4

के बाद से अजगर "का पालन करता है" बतख टाइपिंग, दृष्टिकोण में से एक है, तो एक वस्तु कुछ की जांच करने के लिए है सदस्य (विधि)।

एक अनुक्रम की लंबाई है, वस्तुओं का अनुक्रम है, और समर्थन स्लाइसिंग [doc] है। इसलिए, यह इस तरह होगा:

def is_sequence(obj): 
    t = type(obj) 
    return hasattr(t, '__len__') and hasattr(t, '__getitem__') 
    # additionally: and hasattr(t, '__setitem__') and hasattr(t, '__delitem__') 

वे सभी विशेष तरीके हैं, __len__() मदों की संख्या लौटना चाहिए, __getitem__(i) आइटम को वापस लौटाने चाहिए (अनुक्रम में यह है मैं वें आइटम, नहीं बल्कि साथ मैपिंग), __getitem__(slice(start, stop, step)) को बाद में वापस लौटना चाहिए, और __setitem__ और __delitem__ जैसा कि आप उम्मीद करते हैं।यह ऐसा अनुबंध है, लेकिन क्या ऑब्जेक्ट वास्तव में इन्हें करता है या नहीं, इस पर निर्भर करता है कि ऑब्जेक्ट अनुबंध का पालन करता है या नहीं।

नोट कि, ऊपर दिया गया कार्य मैपिंग के लिए True भी लौटाएगा, उदाहरण के लिए dict, चूंकि मैपिंग में इन तरीकों का भी समावेश है। इस पर काबू पाने के लिए, आप एक भारी काम कर सकते हैं:

def is_sequence(obj): 
    try: 
     len(obj) 
     obj[0:0] 
     return True 
    except TypeError: 
     return False 

लेकिन समय की सबसे आप इस की जरूरत नहीं है, बस आप क्या चाहते हैं के रूप में वस्तु है अगर एक दृश्य करते हैं और एक अपवाद को पकड़ने यदि आप चाहते हैं। यह अधिक पाइथोनिक है।

+0

dict के बारे में महत्वपूर्ण बात यह है कि यदि आप इसे अनुक्रम की तरह मानते हैं तो आपको केवल चाबियां मिलेंगी, न कि मान, और जानकारी खो जाएगी। –

+2

यदि 'हैशटर()' का उपयोग करते हैं, तो आपको ऑब्जेक्ट के प्रकार के लिए ऑब्जेक्ट के प्रकार की जांच करने की आवश्यकता है, न कि ऑब्जेक्ट। [पायथन 2] देखें (https://docs.python.org/2/reference/datamodel.html#special-method-lookup-for- new-style-classes) और [पायथन 3] (https: // docs .python.org/3/संदर्भ/डेटामोडेल.html # विशेष-विधि-लुकअप) दस्तावेज कैसे विशेष तरीकों को देखा जाता है। – augurar

+0

@augurar धन्यवाद आदमी – BornToCode

4

मुझे लगता है कि नीचे दिए कोड स्निपेट आप क्या चाहते हैं करता है:

def is_sequence(obj): 
    return hasattr(type(obj), '__iter__') 
+2

'हैट्टर (प्रकार (ओबीजे), '__iter __') होना चाहिए, '[यह टिप्पणी] देखें (https://stackoverflow.com/questions/2937114/#comment71833903_31043360)। – augurar

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