python tutorial कैसे एक चर बताने के लिए चलने योग्य है, लेकिन एक स्ट्रिंग नहीं है




python tutorial (6)

मेरे पास एक फ़ंक्शन है जो एक तर्क लेता है जो या तो एक आइटम या एक डबल आइटम हो सकता है:

def iterable(arg)
    if #arg is an iterable:
        print "yes"
    else:
        print "no"

ताकि:

>>> iterable( ("f","f") )
yes

>>> iterable( ["f","f"] )
yes

>>> iterable("ff")
no

समस्या यह है कि स्ट्रिंग तकनीकी रूप से चलने योग्य है, इसलिए मैं arg[1] को आजमाते समय ValueError को नहीं पकड़ सकता। मैं आइंस्टीन () का उपयोग नहीं करना चाहता, क्योंकि यह अच्छा अभ्यास नहीं है (या इसलिए मुझे बताया गया है)।


मुझे लगता है कि यह एक पुरानी पोस्ट है, लेकिन मुझे लगा कि यह इंटरनेट पोस्टेरिटी के लिए मेरा दृष्टिकोण जोड़ने लायक है। नीचे दिया गया कार्य पायथन 2 और 3 दोनों के साथ अधिकांश परिस्थितियों में मेरे लिए काम करता है:

def is_collection(obj):
    """ Returns true for any iterable which is not a string or byte sequence.
    """
    try:
        if isinstance(obj, unicode):
            return False
    except NameError:
        pass
    if isinstance(obj, bytes):
        return False
    try:
        iter(obj)
    except TypeError:
        return False
    try:
        hasattr(None, obj)
    except TypeError:
        return True
    return False

यह (गलत) अंतर्निहित hasattr का उपयोग करके एक गैर-स्ट्रिंग पुनरावृत्ति के लिए जाँच करता है जो एक hasattr - hasattr को बढ़ाएगा जब इसका दूसरा तर्क स्ट्रिंग या यूनिकोड स्ट्रिंग नहीं होगा।


अमूर्त आधार वर्गों की शुरुआत के साथ पाइथन 2.6 के बाद से, isinstance (एबीसी पर प्रयोग किया जाता है, ठोस वर्ग नहीं) अब पूरी तरह से स्वीकार्य है। विशेष रूप से:

from abc import ABCMeta, abstractmethod

class NonStringIterable:
    __metaclass__ = ABCMeta

    @abstractmethod
    def __iter__(self):
        while False:
            yield None

    @classmethod
    def __subclasshook__(cls, C):
        if cls is NonStringIterable:
            if any("__iter__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented

यह Iterable की एक सटीक प्रतिलिपि (केवल वर्ग नाम बदलकर) है Iterable कि _abcoll.py ( _abcoll.py एक कार्यान्वयन विवरण) में दिया गया है ... यही कारण है कि जब आप चाहें, तो यह काम करता है, जबकि collections.Iterable नहीं है, वह है उत्तरार्द्ध अतिरिक्त मील को यह सुनिश्चित करने के लिए जाता है कि तार को Iterable.register Iterable.register(str) रूप में स्पष्ट रूप से इस class बयान के बाद कहा जाता है।

निश्चित रूप से यह __subclasshook__ को बढ़ाने के लिए आसान है, अन्य वर्गों के लिए any कॉल से पहले False वापसी करके जिसे आप विशेष रूप से अपनी परिभाषा से बाहर करना चाहते हैं।

किसी भी स्थिति में, जब आप इस नए मॉड्यूल को myiter , isinstance('ciao', myiter.NonStringIterable) रूप में आयात करते हैं, तो False होगा, और isinstance([1,2,3], myiter.NonStringIterable) True होगा, ठीक वैसे ही जैसे आप हैं अनुरोध - और पाइथन 2.6 में और बाद में इस तरह के चेक को मूर्त रूप देने के लिए उचित तरीका माना जाता है ... एक सार आधार वर्ग को परिभाषित करता है और इस पर जाँच isinstance करता है।


2017 तक, यहां एक पोर्टेबल समाधान है जो पायथन के सभी संस्करणों के साथ काम करता है:

#!/usr/bin/env python
import collections
import six


def iterable(arg):
    return (
        isinstance(arg, collections.Iterable) 
        and not isinstance(arg, six.string_types)
    )


# non-string iterables    
assert iterable(("f", "f"))    # tuple
assert iterable(["f", "f"])    # list
assert iterable(iter("ff"))    # iterator
assert iterable(range(44))     # generator
assert iterable(b"ff")         # bytes (Python 2 calls this a string)

# strings or non-iterables
assert not iterable(u"ff")     # string
assert not iterable(44)        # integer
assert not iterable(iterable)  # function

हुह, यह नहीं मिलता ... जाने में क्या हर्ज है

hasattr( x, '__iter__' )

?

... NB elgehelge ने इसे एक टिप्पणी में यहाँ कहा, "मेरे अधिक विस्तृत उत्तर को देखो", लेकिन मुझे उसका विस्तृत उत्तर नहीं मिला

बाद में

पाइथन 3 के बारे में डेविड चार्ल्स की टिप्पणी के मद्देनजर, किस बारे में:

hasattr(x, '__iter__') and not isinstance(x, (str, bytes))

? जाहिरा तौर पर "बेसिस्ट्रिंग" अब पायथन 3 में एक प्रकार नहीं है:

https://docs.python.org/3.0/whatsnew/3.0.html

The builtin basestring abstract type was removed. Use str instead. The str and bytes types dont have functionality enough in common to warrant a shared base class.

आइंस्टीन का प्रयोग करें (मुझे नहीं लगता कि यह बुरा व्यवहार क्यों है)

import types
if not isinstance(arg, types.StringTypes):

स्ट्रिंगटाइप्स के उपयोग पर ध्यान दें। यह सुनिश्चित करता है कि हम कुछ अस्पष्ट प्रकार के स्ट्रिंग के बारे में न भूलें।

उल्टा, यह व्युत्पन्न स्ट्रिंग वर्गों के लिए भी काम करता है।

class MyString(str):
    pass

isinstance(MyString("  "), types.StringTypes) # true

इसके अलावा, आप इस पिछले प्रश्न पर एक नज़र रखना चाहते हैं।

चीयर्स।

NB: StringTypes 3 के रूप में पायथन 3 में व्यवहार बदल गया है और basestring को अब परिभाषित नहीं किया गया है। अपनी आवश्यकताओं के आधार पर, आप उन्हें isinstance में str , या Cython उपयोगकर्ताओं के लिए (str, bytes, unicode) एक सबसेट टपल को बदल सकते हैं। जैसा कि @Theron Luhn ने उल्लेख किया है, आप six भी उपयोग कर सकते हैं।


पिछले उत्तरों को मिलाकर, मैं उपयोग कर रहा हूं:

import types
import collections

#[...]

if isinstance(var, types.StringTypes ) \
    or not isinstance(var, collections.Iterable):

#[Do stuff...]

100% मूर्खतापूर्ण सबूत नहीं है, लेकिन अगर कोई वस्तु एक चलने योग्य नहीं है, तो आप अभी भी इसे पास कर सकते हैं और बतख टाइपिंग में वापस आ सकते हैं।

संपादित करें: पायथन 3

types.StringTypes == (str, unicode) । Phython3 समतुल्य है:

if isinstance(var, str ) \
    or not isinstance(var, collections.Iterable):






python