ভেরিয়েবলটি কীভাবে বলতে হয় তা পুনরুক্তিযোগ্য তবে স্ট্রিং নয়


92

আমার একটি ফাংশন রয়েছে যা একটি যুক্তি গ্রহণ করে যা কোনও একক আইটেম বা ডাবল আইটেম হতে পারে:

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

যাতে:

>>> পুনরাবৃত্তিযোগ্য (("চ", "চ"))
হ্যাঁ

>>> পুনরাবৃত্তিযোগ্য (["f", "চ"])
হ্যাঁ

>>> পুনরাবৃত্তিযোগ্য ("এফএফ")
না

সমস্যাটি হ'ল স্ট্রিংটি প্রযুক্তিগতভাবে পুনরাবৃত্তিযোগ্য, তাই চেষ্টা করার সময় আমি কেবল ভ্যালুআরার ধরতে পারি না arg[1]। আমি আইসনস্ট্যান্স () ব্যবহার করতে চাই না, কারণ এটি ভাল অনুশীলন নয় (বা তাই আমাকে বলা হয়েছে)।


4
পাইথনের কোন সংস্করণ? আমি বিশ্বাস করি উত্তরটি ২ থেকে ২ এর মধ্যে আলাদা
ক্যাথি ভ্যান স্টোন

4
আপনাকে ভুলভাবে বলা হয়েছিল, ইসিস্ট্যান্স খারাপ অভ্যাস নয়।
লেনার্ট রেজেব্রো

4
ওহ, অপেক্ষা করুন, সম্ভবত তিনি সেই নীতিটিকে বোঝান যে কোনও বস্তুর প্রকারের পরীক্ষা করা খারাপ, এবং এটি প্রোগ্রামটি ভেঙে যাওয়ার ইঙ্গিত দেয়? এটি নীতিগতভাবে সত্য (তবে সবসময় অনুশীলনে নয়)। এটি হতে পারে বা এ জাতীয় ঘটনা নাও হতে পারে। তবে এটি ফাংশনটির সমস্যা নয়, এটি ধরণের পরীক্ষা করার অভ্যাস habit
লেনার্ট রেজেব্রো


@ আপ এটি টাইপ-ভিত্তিক ফাংশন ওভারলোডিংয়ের কথা উল্লেখ করে না, এবং isinstanceএটি গতিশীল টাইপ করা ভাষায় এটি করার উপায়। একটি জিনিস প্রতিদিন ব্যবহার না করা, তবে ন্যায়সঙ্গত ক্ষেত্রে ঠিক আছে।
কোস

উত্তর:


50

ইসিনস্ট্যান্স ব্যবহার করুন (কেন এটি খারাপ অনুশীলন আমি তা দেখতে পাই না)

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

স্ট্রিংটাইপগুলির ব্যবহারটি নোট করুন। এটি নিশ্চিত করে যে আমরা কিছু অস্পষ্ট ধরণের স্ট্রিং সম্পর্কে ভুলে যাব না।

উল্টো দিকে, এটি উত্পন্ন স্ট্রিং ক্লাসগুলির জন্যও কাজ করে।

class MyString(str):
    pass

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

এছাড়াও, আপনি এই আগের প্রশ্নটি একবার দেখতে চান

চিয়ার্স


এনবি: পাইথন 3 তে আচরণটি পরিবর্তিত হয়েছে StringTypesএবং basestringএটি আর সংজ্ঞায়িত করা হয় না। আপনার প্রয়োজনের উপর ভিত্তি করে, আপনি তাদের মধ্যে প্রতিস্থাপন করতে পারেন isinstanceদ্বারা str, অথবা একটি উপসেট tuple (str, bytes, unicode)যেমন Cython ব্যবহারকারীদের জন্য। @ থেরন লুহন যেমন উল্লেখ করেছেন, আপনি এটিও ব্যবহার করতে পারেন six


সুন্দর, স্কভ্যালেক্স আমি এখন আমার -1 অপসারণ করছি এবং এটি একটি +1 :-) করছি।
টম

4
আমি মনে করি খারাপ অনুশীলন ধারণাটি হাঁসের টাইপিং নীতিটির কারণে। নির্দিষ্ট শ্রেণীর সদস্য হওয়ার অর্থ এই নয় যে এটি কেবলমাত্র একমাত্র অবজেক্ট যা ব্যবহার করা যেতে পারে বা প্রত্যাশিত পদ্ধতিগুলি উপলব্ধ। তবে আমি মনে করি কখনও কখনও আপনি কেবল পদ্ধতিটি উপস্থিত থাকলেও কী করে তা অনুমান করতে পারবেন না, তবে এটিই isinstanceহতে পারে একমাত্র উপায়।
ইস্তানী

4
দ্রষ্টব্য: প্রকার। স্ট্রিংটাইপগুলি পাইথন ৩ তে উপলভ্য নয় Since যেহেতু পাই 3 কেতে কেবল একটি স্ট্রিং টাইপ রয়েছে, তাই আমি মনে করি এটি নিরাপদ do isinstance(arg, str)। পিছনের দিকে সামঞ্জস্যপূর্ণ সংস্করণের জন্য, পাইথনহস্টেড.org
থেরন

আমি পাইথন 3 কঠোরভাবে ব্যবহার করি এবং লক্ষ্য করেছি types.StringTypesপাইথন 3 তে উপলব্ধ নেই। পাইথন 2 এর মান কত?
কেভিনার্পে

4
2017 : এই উত্তরটি আর বৈধ নয়, পাইথনের সমস্ত সংস্করণে কাজ করে এমন একের জন্য stackoverflow.com/a/44328500/99834 দেখুন ।
সোরিন

26

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

বাইটস্ট্রিংসের সাথে ২/৩ এর মধ্যে কিছুটা ছোটখাটো অসঙ্গতি রয়েছে তবে আপনি যদি "স্ট্রিং" ব্যবহার করেন তবে সেগুলি উভয়ই মিথ্যা
নিক টি

16

পাইথন ২.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সংজ্ঞায়িত করা হয়েছে _abcoll.py(এর একটি বাস্তবায়ন বিশদ collections.py) ... কারণ এটি আপনার ইচ্ছা অনুসারে কাজ collections.Iterableকরে , যখন না হয় তবে এটি পরেরটি নিশ্চিত করতে অতিরিক্ত মাইল চলে যায় Iterable.register(str)এই classবিবৃতি ঠিক পরে স্পষ্টভাবে কল করে, পুনরাবৃত্তিযোগ্য হিসাবে বিবেচিত ।

অবশ্যই আপনি অন্য শ্রেণীর জন্য কল করার আগে __subclasshook__ফিরে যাওয়ার মাধ্যমে আপনার সংজ্ঞাটি থেকে বিশেষত বাদ দিতে চান Falseএটি বাড়ানো সহজ any

যাই হোক, পরে আপনি এই নতুন মডিউল আমদানি করেছি myiter, isinstance('ciao', myiter.NonStringIterable)হতে হবে False, এবং isinstance([1,2,3], myiter.NonStringIterable)হতে হবে True, আপনি অনুরোধ ঠিক যেমন - এবং পাইথন 2.6 এবং পরে এই রূপ দান যেমন চেক সঠিক পথ বলে মনে করা হয় ... একটি বিমূর্ত বেস বর্গ সংজ্ঞায়িত এবং isinstanceএটি পরীক্ষা করে দেখুন।


ইন পাইথন 3 isinstance('spam', NonStringIterable)আয় True
নিক টি

4
(...) এবং পাইথন ২.6 এ এবং পরবর্তীকালে এ জাতীয় চেকগুলি মূর্ত করার উপযুক্ত উপায় হিসাবে বিবেচনা করা হয় (...) অ্যাবস্ট্রাক্ট শ্রেণির এইরকমভাবে সুপরিচিত ধারণাটি কীভাবে সঠিক উপায় হিসাবে বিবেচনা করা যেতে পারে তা আমার বোধগম্যতার বাইরে। এর সঠিক উপায়টি হ'ল পরিবর্তে কিছু বর্ণমালার অপারেটর প্রবর্তন করা।
পাইওটর ডব্রোগোস্ট

অ্যালেক্স, আপনি নিকের এই দৃ ?়তার প্রতিপন্ন করতে পারেন যে পাইথন 3 এ কাজ করে না? আমি উত্তরটি চাই, তবে নিশ্চিত করতে চাই যে আমি ভবিষ্যতের প্রুফ কোডটি লিখছি।
মের্লিন মরগান-গ্রাহাম

@ MerlynMorgan-গ্রাহাম, যে সঠিক, কারণ __iter__ হয় এখন পাইথন 3. তাই আমার "সহজ বৃদ্ধির জন্য" অনুচ্ছেদ প্রযোজ্য এবং যেমন হয়ে স্ট্রিং বাস্তবায়িত if issublass(cls, str): return Falseচাহিদা শুরুতে যোগ করার জন্য __subclasshook__(যে কোন অন্য ক্লাসের যা সংজ্ঞায়িত সেইসাথে __iter__কিন্তু আপনার মানসিকতা অবশ্যই "নন-স্ট্রিং পুনরাবৃত্ত" হিসাবে গ্রহণ করা উচিত নয়)।
অ্যালেক্স মার্টেলি

অ্যালেক্সমার্টেলি @ পাইথন 3-এর জন্য, আপনার অর্থ if issublass(C, str): return Falseকি যুক্ত হওয়া উচিত নয় ?
রব স্মলশায়ার

4

আমি বুঝতে পারি এটি একটি পুরানো পোস্ট তবে ভেবেছি এটি ইন্টারনেটের উত্তরোত্তর সম্পর্কে আমার দৃষ্টিভঙ্গি যুক্ত করা উপযুক্ত। নীচের ফাংশনটি পাইথন 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যা TypeErrorতার দ্বিতীয় আর্গুমেন্টটি স্ট্রিং বা ইউনিকোড স্ট্রিং না হলে এটি উত্থাপন করবে ।


3

পূর্ববর্তী উত্তরগুলি একত্রিত করে আমি ব্যবহার করছি:

import types
import collections

#[...]

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

#[Do stuff...]

১০০% বোকা প্রমাণ নয়, তবে কোনও বস্তু যদি পুনরাবৃত্তিযোগ্য না হয় তবে আপনি এখনও এটি পাস এবং হাঁসের টাইপিংয়ে ফিরে যেতে পারেন।


সম্পাদনা: পাইথন 3

types.StringTypes == (str, unicode)। পাইথন 3 সমতুল্য:

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

আপনার আমদানি বিবৃতিটি 'প্রকারের' নয় 'ধরণের' হওয়া উচিত
পলআর

3

2.x

আমি পরামর্শ দিতে হবে:

hasattr(x, '__iter__')

বা পাইথন 3 এর জন্য ডেভিড চার্লসের মন্তব্যে এটি টুইট করা হয়েছে, কী সম্পর্কে:

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

3.x

বিল্টিন basestringঅ্যাবস্ট্রাক্ট প্রকারটি সরানো হয়েছিলstrপরিবর্তে ব্যবহার করুন। strএবং bytesধরনের একটি ভাগ বেস বর্গ পরোয়ানা কমন কার্যকারিতা যথেষ্ট হবে না।


4
__iter__পাইথন 3 এ স্ট্রিং রয়েছে বলেই সম্ভবত ?
ডেভিডার্মচারগুলি

@ ডেভিডচারেলস ওহ, সত্যিই? আমার খারাপ। আমি একজন জাইথন ​​ব্যবহারকারী এবং জাইথনের বর্তমানে কোনও সংস্করণ 3 নেই
মাইক রডেন্ট

এটি আসলে কোনও উত্তর নয়, আরও একটি মন্তব্য / প্রশ্ন এবং এটি 3.x এর জন্য ভুল আপনি এটি পরিষ্কার করতে পারেন? আপনি কি "দ্য 'স্ট্রিং' এবং 'বাইটস' ধরণের দাবী করার পক্ষে যুক্তিযুক্ত যুক্ত করতে পারেন? 3.x এর অন্যতম মূল বিষয় হ'ল ইউনিকোড বাইটকে প্রথম শ্রেণির নাগরিক বানানো।
স্মি

আমি উপরের কোনওটি কেন লিখলাম তা সম্পর্কে আমার কোনও ধারণা নেই। আমি "3.x" এর অধীনে সমস্ত পাঠ্য মুছে ফেলার প্রস্তাব করছি ... যদিও আপনি ইতিমধ্যে আমার উত্তরটি সম্পাদনা করেছেন। আপনি চাইলে এটিকে আরও সম্পাদনা করুন।
মাইকে রডেন্ট

0

আপনি সঠিকভাবে চিহ্নিত হিসাবে, একটি একক স্ট্রিং একটি অক্ষর ক্রম।

সুতরাং আপনি যা করতে চান তা হ'ল argআইসনস্ট্যান্স বা টাইপ (ক) == স্ট্রিং ব্যবহার করে কোন ধরণের ক্রম রয়েছে তা সন্ধান করা।

আপনি যদি এমন কোনও ক্রিয়াকলাপ অনুধাবন করতে চান যা ভ্যারিয়েবলের পরিমাণে প্যারামিটার নেয়, আপনার এটি করা উচিত:

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

ফাংশন ("ff") এবং ফাংশন ("ff", "ff") কাজ করবে।

আমি এমন দৃশ্য দেখতে পাচ্ছি না যেখানে আপনার মতো একটি iteশ্বর্যমূলক () ফাংশন প্রয়োজন। এটি আইসনস্ট্যান্স () নয় এটি খারাপ স্টাইল তবে এমন পরিস্থিতিতে যেখানে আপনার আইসনস্ট্যান্স ব্যবহার করতে হবে ()।


4
ব্যবহার type(a) == strএড়ানো হবে। এটি একটি খারাপ অনুশীলন কারণ এটি থেকে প্রাপ্ত অনুরূপ প্রকারগুলি বা প্রকারগুলি বিবেচনা করে না strtypeধরণের শ্রেণিবিন্যাসকে আরোহণ করে না, এমনকী isinstance, তাই এটি ব্যবহার করা ভাল isinstance
আকিরস

0

অ্যালেক্স মার্তেলির দুর্দান্ত হ্যাকটি স্পষ্টভাবে প্রসারিত করতে collections.pyএবং এর আশেপাশের কয়েকটি প্রশ্নের সমাধান করতে: পাইথন ৩. in++ এর বর্তমান কাজের সমাধানটি

import collections
import _collections_abc as cabc
import abc


class NonStringIterable(metaclass=abc.ABCMeta):

    __slots__ = ()

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

    @classmethod
    def __subclasshook__(cls, c):
        if cls is NonStringIterable:
            if issubclass(c, str):
                return False
            return cabc._check_methods(c, "__iter__")
        return NotImplemented

এবং প্রদর্শিত

>>> typs = ['string', iter(''), list(), dict(), tuple(), set()]
>>> [isinstance(o, NonStringIterable) for o in typs]
[False, True, True, True, True, True]

আপনি যদি iter('')বাদে যুক্ত করতে চান তবে উদাহরণস্বরূপ, লাইনটি সংশোধন করুন

            if issubclass(c, str):
                return False

হতে

            # `str_iterator` is just a shortcut for `type(iter(''))`*
            if issubclass(c, (str, cabc.str_iterator)):
                return False

পেতে

[False, False, True, True, True, True]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.