software - python tutorial




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

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

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 को नहीं पकड़ सकता। मैं आइंस्टीन () का उपयोग नहीं करना चाहता, क्योंकि यह अच्छा अभ्यास नहीं है (या इसलिए मुझे बताया गया है)।


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

अमूर्त आधार वर्गों की शुरुआत के साथ पाइथन 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 करता है।


जैसा कि आप सही ढंग से इंगित करते हैं, एक एकल स्ट्रिंग एक चरित्र अनुक्रम है।

तो जिस चीज को आप वास्तव में करना चाहते हैं, वह यह पता लगाना है कि आइंस्टीन या टाइप (a) == str का उपयोग करके किस प्रकार का अनुक्रम arg है।

यदि आप एक ऐसे फंक्शन को महसूस करना चाहते हैं जो पैरामीटर्स की एक चर राशि लेता है, तो आपको इसे इस तरह करना चाहिए:

def function(*args):
    # args is a tuple
    for arg in args:
        do_something(arg)

फ़ंक्शन ("एफएफ") और फ़ंक्शन ("एफएफ", "एफएफ") काम करेगा।

मैं ऐसा परिदृश्य नहीं देख सकता जहाँ आपकी आवश्यकता के अनुसार एक अनुमापनीय () फ़ंक्शन हो। यह आइंस्टीन () नहीं है जो खराब शैली है, लेकिन ऐसी स्थितियों में जहां आपको आइंस्टीन () का उपयोग करने की आवश्यकता है।


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

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):

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

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.




python