python - पाइथन मुहावरे पहले आइटम या कोई भी वापस करने के लिए




idioms python-2.4 (16)

पाइथन मुहावरे पहले आइटम या कोई नहीं लौटने के लिए?

सबसे पाइथोनिक दृष्टिकोण सबसे ऊपर उठाए गए उत्तर का प्रदर्शन करता है, और जब मैं प्रश्न पढ़ता हूं तो यह मेरे दिमाग में आने वाली पहली बात थी। यहां इसका उपयोग कैसे करें, सबसे पहले यदि संभावित रूप से रिक्त सूची किसी फ़ंक्शन में पास हो जाती है:

def get_first(l): 
    return l[0] if l else None

और यदि सूची get_list फ़ंक्शन से वापस get_list है:

l = get_list()
return l[0] if l else None

स्पष्टीकरण के साथ, यहां अन्य तरीकों से ऐसा करने का प्रदर्शन किया गया

for

जब मैंने ऐसा करने के चालाक तरीकों के बारे में सोचने की कोशिश करना शुरू किया, तो यह दूसरी बात है जिसके बारे में मैंने सोचा था:

for item in get_list():
    return item

यह मानता है कि फ़ंक्शन यहां समाप्त होता है, अगर None get_list खाली सूची लौटाता है तो निश्चित रूप से None लौटाता है। नीचे स्पष्ट कोड बिल्कुल बराबर है:

for item in get_list():
    return item
return None

if some_list

निम्नलिखित भी प्रस्तावित किया गया था (मैंने गलत चर नाम को सही किया) जो अंतर्निहित None भी का उपयोग None करता है। यह उपरोक्त के लिए बेहतर होगा, क्योंकि यह एक पुनरावृत्ति के बजाय तार्किक जांच का उपयोग करता है जो ऐसा नहीं हो सकता है। क्या हो रहा है तुरंत यह समझना आसान होना चाहिए। लेकिन अगर हम पठनीयता और रखरखाव के लिए लिख रहे हैं, तो हमें अंत में स्पष्ट return None भी जोड़नी चाहिए:

some_list = get_list()
if some_list:
    return some_list[0]

टुकड़ा or [None] और शून्य शून्य सूचकांक का चयन करें

यह सबसे ज्यादा वोट देने वाले उत्तर में भी है:

return (get_list()[:1] or [None])[0]

टुकड़ा अनावश्यक है, और स्मृति में एक अतिरिक्त एक आइटम सूची बनाता है। निम्नलिखित अधिक प्रदर्शनशील होना चाहिए। व्याख्या करने के लिए, or दूसरा तत्व लौटाता है यदि पहला बुलियन संदर्भ में False है, इसलिए यदि get_list एक खाली सूची देता है, तो कोष्ठक में निहित अभिव्यक्ति 'कोई नहीं' वाली सूची लौटाएगी, जिसे तब 0 अनुक्रमणिका द्वारा एक्सेस किया जाएगा :

return (get_list() or [None])[0]

अगला व्यक्ति इस तथ्य का उपयोग करता है कि यदि दूसरा बूलियन संदर्भ में True है तो दूसरा आइटम लौटाता है, और चूंकि यह दो बार my_list का संदर्भ देता है, यह टर्नरी अभिव्यक्ति (और तकनीकी रूप से एक-लाइनर नहीं) से बेहतर नहीं है:

my_list = get_list() 
return (my_list and my_list[0]) or None

next

फिर हमारे पास next और इसे iter के निम्नलिखित चालाक उपयोग हैं

return next(iter(get_list()), None)

व्याख्या करने के लिए, यह एक .next विधि के साथ एक .next है। ( .__next__ पायथन 3 में)। फिर .next next कॉल करता है .next विधि, और अगर इटरेटर समाप्त हो जाता है, तो हम जो डिफॉल्ट देते हैं, उसे वापस लौटाते हैं।

अनावश्यक टर्नरी अभिव्यक्ति ( a if b else c ) और वापस घूमना

नीचे प्रस्तावित किया गया था, लेकिन उलटा बेहतर होगा, क्योंकि ऋणात्मक रूप से ऋणात्मक रूप से सकारात्मक में सकारात्मक रूप से बेहतर समझा जाता है। चूंकि Get_list को दो बार बुलाया जाता है, जब तक परिणाम किसी भी तरह से याद नहीं किया जाता है, यह खराब प्रदर्शन करेगा:

return None if not get_list() else get_list()[0]

बेहतर उलटा:

return get_list()[0] if get_list() else None

इससे भी बेहतर, स्थानीय चर का उपयोग करें ताकि get_list को केवल एक बार बुलाया जा सके, और आपके पास पहले सुझाए गए पायथनिक समाधान की अनुशंसा की गई है:

l = get_list()
return l[0] if l else None

मुझे यकीन है कि ऐसा करने का एक आसान तरीका है जो मेरे साथ नहीं हो रहा है।

मैं विधियों का एक समूह बुला रहा हूं जो एक सूची लौटाता है। सूची खाली हो सकती है। यदि सूची खाली नहीं है, तो मैं पहले आइटम को वापस करना चाहता हूं; अन्यथा, मैं कोई भी वापस नहीं करना चाहता हूं। यह कोड काम करता है:

my_list = get_list()
if len(my_list) > 0: return my_list[0]
return None

ऐसा लगता है कि ऐसा करने के लिए एक साधारण एक-पंक्ति मुहावरे होना चाहिए, लेकिन मेरे जीवन के लिए मैं इसके बारे में सोच नहीं सकता। है?

संपादित करें:

कारण यह है कि मैं यहां एक-पंक्ति अभिव्यक्ति की तलाश में हूं, यह नहीं है कि मुझे अविश्वसनीय रूप से कोड पसंद है, लेकिन क्योंकि मुझे इस तरह के बहुत सारे कोड लिखना है:

x = get_first_list()
if x:
    # do something with x[0]
    # inevitably forget the [0] part, and have a bug to fix
y = get_second_list()
if y:
    # do something with y[0]
    # inevitably forget the [0] part AGAIN, and have another bug to fix

मैं जो करना चाहता हूं वह निश्चित रूप से एक समारोह (और शायद होगा) के साथ पूरा किया जा सकता है:

def first_item(list_or_none):
    if list_or_none: return list_or_none[0]

x = first_item(get_first_list())
if x:
    # do something with x
y = first_item(get_second_list())
if y:
    # do something with y

मैंने सवाल पोस्ट किया क्योंकि मुझे अक्सर आश्चर्य होता है कि पाइथन में क्या सरल अभिव्यक्तियां कर सकती हैं, और मैंने सोचा था कि एक समारोह लिखना एक मूर्ख बात थी अगर एक सरल अभिव्यक्ति चाल चल सकती थी। लेकिन इन उत्तरों को देखते हुए, ऐसा लगता है कि एक समारोह सरल समाधान है।


पायथन 2.6+

next(iter(your_list or []), None)

पायथन 2.4

def get_first(iterable, default=None):
    if iterable:
        for item in iterable:
            return item
    return default

उदाहरण:

x = get_first(get_first_list())
if x:
    ...
y = get_first(get_second_list())
if y:
    ...

एक और विकल्प उपरोक्त फ़ंक्शन को रेखांकित करना है:

for x in get_first_list() or []:
    # process x
    break # process at most one item
for y in get_second_list() or []:
    # process y
    break

break से बचने के लिए आप लिख सकते हैं:

for x in yield_first(get_first_list()):
    x # process x
for y in yield_first(get_second_list()):
    y # process y

कहा पे:

def yield_first(iterable):
    for item in iterable or []:
        yield item
        return

इस बारे में कैसा है:

(my_list and my_list[0]) or None

नोट: यह ऑब्जेक्ट्स की सूचियों के लिए ठीक काम करना चाहिए लेकिन नीचे दी गई टिप्पणियों के अनुसार संख्या या स्ट्रिंग सूची के मामले में यह गलत जवाब दे सकता है।


इसके बिल्ली के लिए, यहां एक और संभावना है।

return None if not get_list() else get_list()[0]

लाभ: यह विधि उस मामले को संभालती है जहां get_list कोई नहीं है, कोशिश / छोड़कर या असाइनमेंट का उपयोग किए बिना। मेरे ज्ञान के लिए, ऊपर दिए गए कोई भी कार्यान्वयन इस संभावना को संभाल सकता है

डाउनफॉल्स: get_list () को दो बार बुलाया जाता है, काफी अनावश्यक रूप से, विशेष रूप से अगर सूची लंबी होती है और / या फ़ंक्शन कहलाता है तो बनाया जाता है।

सच्चाई यह है कि, मेरी राय में यह "पायथनिक" है, जो कोड पढ़ने योग्य है, उसे एक लाइनर बनाने के लिए है क्योंकि आप कर सकते हैं :) मुझे यह मानना ​​है कि मैं अनावश्यक रूप से पाइथन कोड को कॉम्पैक्ट करने के कई बार दोषी हूं क्योंकि मैं इतना प्रभावित हूं कि मैं एक जटिल फ़ंक्शन कैसे देख सकता हूं :)

संपादित करें: उपयोगकर्ता "हैसन जे" के रूप में नीचे टिप्पणी की गई है, ऊपर वर्णित सशर्त अभिव्यक्ति पायथन 2.5 में नई है, जैसा कि यहां वर्णित है: https://docs.python.org/whatsnew/2.5.html#pep-308 । धन्यवाद, हैन!


और इसके बारे में क्या: next(iter(get_list()), None) ? यहां सबसे तेज़ नहीं हो सकता है, लेकिन मानक है (पायथन 2.6 से शुरू) और संक्षेप में।


और-या चाल का उपयोग करना:

a = get_list()
return a and a[0] or None

जिज्ञासा से, मैंने दो समाधानों पर समय चलाया। समाधान जो लूप के लिए समय-समय पर समाप्त होने के लिए रिटर्न स्टेटमेंट का उपयोग करता है, मेरी मशीन पर पाइथन 2.5.1 के साथ थोड़ा अधिक महंगा है, मुझे संदेह है कि इसे पुन: स्थापित करने के साथ करना है।

import random
import timeit

def index_first_item(some_list):
    if some_list:
        return some_list[0]


def return_first_item(some_list):
    for item in some_list:
        return item


empty_lists = []
for i in range(10000):
    empty_lists.append([])

assert empty_lists[0] is not empty_lists[1]

full_lists = []
for i in range(10000):
    full_lists.append(list([random.random() for i in range(10)]))

mixed_lists = empty_lists[:50000] + full_lists[:50000]
random.shuffle(mixed_lists)

if __name__ == '__main__':
    ENV = 'import firstitem'
    test_data = ('empty_lists', 'full_lists', 'mixed_lists')
    funcs = ('index_first_item', 'return_first_item')
    for data in test_data:
        print "%s:" % data
        for func in funcs:
            t = timeit.Timer('firstitem.%s(firstitem.%s)' % (
                func, data), ENV)
            times = t.repeat()
            avg_time = sum(times) / len(times)
            print "  %s:" % func
            for time in times:
                print "    %f seconds" % time
            print "    %f seconds avg." % avg_time

ये समय मुझे मिल गया है:

empty_lists:
  index_first_item:
    0.748353 seconds
    0.741086 seconds
    0.741191 seconds
    0.743543 seconds avg.
  return_first_item:
    0.785511 seconds
    0.822178 seconds
    0.782846 seconds
    0.796845 seconds avg.
full_lists:
  index_first_item:
    0.762618 seconds
    0.788040 seconds
    0.786849 seconds
    0.779169 seconds avg.
  return_first_item:
    0.802735 seconds
    0.878706 seconds
    0.808781 seconds
    0.830074 seconds avg.
mixed_lists:
  index_first_item:
    0.791129 seconds
    0.743526 seconds
    0.744441 seconds
    0.759699 seconds avg.
  return_first_item:
    0.784801 seconds
    0.785146 seconds
    0.840193 seconds
    0.803380 seconds avg.

मुहावरे के बारे में, nth नामक एक इटारेटोलस नुस्खा है

Itertools व्यंजनों से:

def nth(iterable, n, default=None):
    "Returns the nth item or a default value"
    return next(islice(iterable, n, None), default)

यदि आप एक-लाइनर चाहते हैं, तो उस पुस्तकालय को स्थापित करने पर विचार करें जो आपके लिए इस नुस्खा को लागू करता है, उदाहरण के लिए more_itertools :

import more_itertools as mit

mit.nth([3, 2, 1], 0)
# 3

mit.nth([], 0)                                             # default is `None`
# None

एक और उपकरण उपलब्ध है जो केवल पहले आइटम को लौटाता है, जिसे more_itertools.first कहा जाता है।

mit.first([3, 2, 1])
# 3

mit.first([], default=None)
# None

ये itertools सामान्य रूप से सूचियों के लिए, किसी भी पुनरावर्तनीय के लिए पैमाने पर।


यदि आप स्वयं को सूची समझ से पहली चीज़ (या कोई नहीं) को खींचने की कोशिश कर रहे हैं तो आप ऐसा करने के लिए जनरेटर पर स्विच कर सकते हैं:

next((x for x in blah if cond), None)

प्रो: काम करता है अगर ब्लाह अनुक्रमणीय नहीं है Con: यह अपरिचित वाक्यविन्यास है। आईपीथॉन में सामान को फ़िल्टर करने और फ़िल्टर करने के दौरान यह उपयोगी है।


शायद सबसे तेज़ समाधान नहीं, लेकिन किसी ने इस विकल्प का उल्लेख नहीं किया:

dict(enumerate(get_list())).get(0)

अगर get_list() वापस आ सकता है तो आप इसका उपयोग None कर सकते हैं:

dict(enumerate(get_list() or [])).get(0)

लाभ:

-एक पंक्ति

- आप बस get_list() एक बार कॉल करें

-समझने में आसान


सबसे पायथन बेवकूफ तरीका अगले () को इटरेटर पर उपयोग करना है क्योंकि सूची इष्टतम है । जैसा कि 13 दिसंबर, 2011 को टिप्पणी में @ जेएफएसबीस्टियन ने टिप्पणी की थी।

next(iter(the_list), None) यह कोई नहीं देता है the_list खाली है। अगला देखें () पायथन 2.6+

या यदि आप निश्चित रूप से जानते हैं कि the_list खाली नहीं है:

iter(the_list).next() iterator.next () पायथन 2.2+ देखें


सी-स्टाइल टर्नरी ऑपरेटरों के बराबर बेवकूफ पायथन नहीं है

cond and true_expr or false_expr

अर्थात।

list = get_list()
return list and list[0] or None

(get_list() or [None])[0]

यह काम करना चाहिए।

बीटीडब्ल्यू मैंने चर list उपयोग नहीं किया, क्योंकि यह बिल्टिन list() फ़ंक्शन को ओवरराइट करता है।

संपादित करें: मेरे पास थोड़ा सा सरल था, लेकिन पहले यहां गलत संस्करण था।


def head(iterable):
    try:
        return iter(iterable).next()
    except StopIteration:
        return None

print head(xrange(42, 1000)  # 42
print head([])               # None

बीटीडब्ल्यू: मैं आपके सामान्य कार्यक्रम प्रवाह को इस तरह से कुछ में पुन: कार्य करूंगा:

lists = [
    ["first", "list"],
    ["second", "list"],
    ["third", "list"]
]

def do_something(element):
    if not element:
        return
    else:
        # do something
        pass

for li in lists:
    do_something(head(li))

(जब भी संभव हो पुनरावृत्ति से बचें)


if mylist != []:

       print(mylist[0])

   else:

       print(None)

try:
    return a[0]
except IndexError:
    return None




python-2.4