एक सूचकांक चर के बिना एन बार कुछ करने का पायथोनिक तरीका?


161

हर दिन मैं अजगर को ज्यादा से ज्यादा प्यार करता हूं।

आज, मैं कुछ कोड लिख रहा था जैसे:

for i in xrange(N):
    do_something()

मुझे कुछ समय एन करना था। लेकिन हर बार i(सूचकांक चर) के मूल्य पर निर्भर नहीं था । मुझे एहसास हुआ कि मैं एक चर बना रहा था जिसका मैंने कभी उपयोग नहीं किया ( i), और मैंने सोचा कि "निश्चित रूप से उस बेकार सूचकांक चर की आवश्यकता के बिना ऐसा करने का एक अधिक पायथोनिक तरीका है।"

तो ... सवाल यह है: क्या आप जानते हैं कि इस सरल कार्य को और अधिक (पाइथोनिक) सुंदर तरीके से कैसे किया जाए?


7
मैंने सिर्फ _ वैरिएबल के बारे में सीखा है, लेकिन अन्यथा मैं उस तरीके पर विचार करूंगा जो आप इसे पाइथोनिक कर रहे हैं। मुझे नहीं लगता कि मैंने कभी भी लूप के लिए एक सरल तरीका देखा है जो किसी अन्य तरीके से किया गया हो, कम से कम अजगर में। हालांकि मुझे यकीन है कि विशिष्ट उपयोग के मामले हैं जहां आप इसे देखते हैं और कहते हैं "रुको, यह भयानक लग रहा है" - लेकिन सामान्य तौर पर, xrange पसंदीदा तरीका है (जहां तक ​​मैंने देखा है)।
वेन वर्नर


5
नोट: Python3 में xrange मौजूद नहीं है। rangeइसके बजाय उपयोग करें ।
जॉन हेनकेल

जवाबों:


110

लूपिंग की तुलना में थोड़ा तेज़ तरीका xrange(N)है:

import itertools

for _ in itertools.repeat(None, N):
    do_something()

3
कितना तेज? पायथन 3.1 में अभी भी कोई अंतर है?
हमीश ग्रुबीजन

15
@ हमीश: 2.6 के साथ मेरा परीक्षण 32% तेज (23.2 हमें बनाम 17.6 हमें एन = 1000 के लिए) कहता है। लेकिन यह वास्तव में समय वैसे भी है। मैं ओपी के कोड को डिफॉल्ट करूंगा क्योंकि यह तुरंत पढ़ने योग्य है (मेरे लिए)।
माइक बोर्स

3
गति के बारे में जानना अच्छा है। मैं निश्चित रूप से ओपी के कोड को अधिक पठनीय होने के बारे में माइक की भावना को प्रतिध्वनित करता हूं।
वेन वर्नर

@Wayne, मुझे लगता है कि आदत वास्तव में बहुत शक्तिशाली है - इस तथ्य के अलावा कि आप इसके अभ्यस्त हैं, क्यों "0 से N-1 तक गिना जाएगा [[और पूरी तरह से गिनती को अनदेखा करें]] निर्भर ऑपरेशन "आंतरिक रूप से किसी भी स्पष्ट" दोहराए जाने वाले एन ऑपरेशन के बाद "की तुलना में अधिक स्पष्ट होना चाहिए ...?
एलेक्स मार्टेली

4
क्या आप सुनिश्चित हैं कि गति वास्तव में प्रासंगिक है? क्या ऐसा नहीं है कि यदि आप उस पाश में कुछ भी महत्वपूर्ण करते हैं, तो यह संभावना है कि आपके द्वारा चुने गए पुनरावृति शैली में सैकड़ों या हजारों समय लगेगा?
हेनिंग

55

_ चर का उपयोग करें, जैसा कि मैंने सीखा जब मैंने यह सवाल पूछा था , उदाहरण के लिए:

# A long way to do integer exponentiation
num = 2
power = 3
product = 1
for _ in xrange(power):
    product *= num
print product

6
डाउनवॉटर नहीं, लेकिन ऐसा हो सकता है क्योंकि आप उत्तर में और अधिक विवरण जोड़ने के बजाय किसी अन्य पोस्ट का उल्लेख कर रहे हैं
डाउनगोट

5
@Downgoat: प्रतिक्रिया के लिए धन्यवाद। उस ने कहा, इस मुहावरे के बारे में कहने के लिए इतना कुछ नहीं है। एक अन्य पोस्ट के संदर्भ में मेरा कहना था कि एक खोज ने उत्तर का उत्पादन किया हो सकता है। मुझे यह विडंबना लगती है कि इस प्रश्न में कई बार दूसरे के रूप में उत्थान होता है।
ग्रीनमैट

39

मैं सिर्फ उपयोग करता हूं for _ in range(n), यह सीधे बिंदु पर है। यह पायथन 2 में बड़ी संख्या के लिए पूरी सूची उत्पन्न करने वाला है, लेकिन यदि आप पायथन 3 का उपयोग कर रहे हैं तो यह कोई समस्या नहीं है।


10

चूंकि फ़ंक्शन प्रथम श्रेणी का नागरिक है, आप छोटे आवरण (एलेक्स के उत्तर से) लिख सकते हैं

def repeat(f, N):
    for _ in itertools.repeat(None, N): f()

तब आप फ़ंक्शन को तर्क के रूप में पास कर सकते हैं।


@ हामिश: लगभग कुछ भी नहीं। (17.8 हमें प्रति पाश के तहत एलेक्स की उत्तर के लिए समान परिस्थितियों में, 0.2 अंतर के लिए)।
माइक बोर्स

9

द _ x जैसी ही बात है। हालाँकि यह एक अजगर मुहावरा है जिसका उपयोग एक पहचानकर्ता को इंगित करने के लिए किया जाता है जिसे आप उपयोग करने का इरादा नहीं रखते हैं। अजगर में ये पहचानकर्ता याद नहीं रखते हैं या अन्य भाषाओं में चर की तरह जगह आवंटित करते हैं। यह भूलना आसान है। वे सिर्फ नाम हैं जो वस्तुओं की ओर इशारा करते हैं, इस मामले में प्रत्येक पुनरावृत्ति पर एक पूर्णांक।


8

मुझे विभिन्न उत्तर वाकई बहुत खूबसूरत लगे (विशेषकर एलेक्स मार्टेली के) लेकिन मैं प्रदर्शन को पहले हाथ से निर्धारित करना चाहता था, इसलिए मैंने निम्नलिखित स्क्रिप्ट तैयार की:

from itertools import repeat
N = 10000000

def payload(a):
    pass

def standard(N):
    for x in range(N):
        payload(None)

def underscore(N):
    for _ in range(N):
        payload(None)

def loopiter(N):
    for _ in repeat(None, N):
        payload(None)

def loopiter2(N):
    for _ in map(payload, repeat(None, N)):
        pass

if __name__ == '__main__':
    import timeit
    print("standard: ",timeit.timeit("standard({})".format(N),
        setup="from __main__ import standard", number=1))
    print("underscore: ",timeit.timeit("underscore({})".format(N),
        setup="from __main__ import underscore", number=1))
    print("loopiter: ",timeit.timeit("loopiter({})".format(N),
        setup="from __main__ import loopiter", number=1))
    print("loopiter2: ",timeit.timeit("loopiter2({})".format(N),
        setup="from __main__ import loopiter2", number=1))

मैं एक वैकल्पिक समाधान के साथ भी आया जो मार्टेली के एक पर बनाता है और map()पेलोड फ़ंक्शन को कॉल करने के लिए उपयोग करता है। ठीक है, मैंने इसमें थोड़ा धोखा दिया कि मैंने पेलोड को एक पैरामीटर स्वीकार करने की आजादी ले ली, जो छूट जाता है: मुझे नहीं पता कि इसके आसपास कोई रास्ता है या नहीं। फिर भी, यहाँ परिणाम हैं:

standard:  0.8398549720004667
underscore:  0.8413165839992871
loopiter:  0.7110594899968419
loopiter2:  0.5891903560004721

इसलिए मैप का उपयोग करने से लूप के लिए मानक पर लगभग 30% और मार्टेली पर एक अतिरिक्त 19% का सुधार होता है।


4

मान लें कि आपने do_something को एक फ़ंक्शन के रूप में परिभाषित किया है , और आप इसे N बार प्रदर्शन करना चाहते हैं । शायद आप निम्नलिखित की कोशिश कर सकते हैं:

todos = [do_something] * N  
for doit in todos:  
    doit()

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

1
क्या यह समान फ़ंक्शन मान के लिए केवल N संदर्भों की सूची नहीं है?
Nick McCurdy

fn() for fn in itertools.repeat(do_something, N)सरणी को प्री-जेनरेट करने और सहेजने के बजाय बेहतर है ... यह मेरा पसंदीदा मुहावरा है।
F1Rumors

1
@tzot कृपालु स्वर क्यों? इस व्यक्ति ने उत्तर लिखने में प्रयास किया और अब भविष्य में योगदान करने से हतोत्साहित किया जा सकता है। यहां तक ​​कि अगर इसमें प्रदर्शन निहितार्थ हैं, तो यह एक कामकाजी विकल्प है और खासकर अगर एन छोटा है प्रदर्शन / मेमोरी निहितार्थ महत्वपूर्ण नहीं हैं।
davidscolgan

मुझे हमेशा आश्चर्य होता है कि पाइथन डेवलपर्स का प्रदर्शन कैसा रहा है :): हालांकि मैं मानता हूं कि यह मुहावरा नहीं है, और पाइथन को पढ़ने वाले किसी नए व्यक्ति को यह समझ में नहीं आ रहा है कि स्पष्ट रूप से क्या हो रहा है जब वह केवल एक इटरेटर का उपयोग कर रहा है
Asfand Qifi

1

पाश के दौरान एक सरल के बारे में क्या?

while times > 0:
    do_something()
    times -= 1

आपके पास पहले से ही चर है; इसका उपयोग क्यों नहीं करते?


1
मेरी केवल सोच यह है कि यह कोड की 3 पंक्तियाँ है बनाम एक (?)
एजेपी

2
@AJP - 4 लाइनों बनाम 2 लाइनों की तरह
ArtOfWarfare

तुलना (समय> 0) और घटाव (समय - = 1) को ओवरहेड्स में जोड़ता है ... तो लूप के लिए की तुलना में धीमा ...
F1Rumors

@ F1Rumors ने इसे मापा नहीं है, लेकिन मुझे आश्चर्य होगा कि अगर PyPy जैसे JIT कंपाइलर्स को इतने सरल लूप के लिए धीमा कोड उत्पन्न करना चाहिए।
फिलिप क्लेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.