दिलचस्प पोस्ट
PHP – एक फाइल को सर्वर पर एक अलग फ़ोल्डर में ले जाएँ जावा में वस्तुओं कास्टिंग करना त्रुटि: फ़ंक्शन नहीं मिल सका … आर में फ्लेक्स आधार और चौड़ाई के बीच अंतर क्या हैं? C फ़ंक्शन किसी खास स्थान पर पाठ में मौजूदा टेक्स्ट को ओवर-लिस्ट किए बिना सम्मिलित करने के लिए सी ++ 03 में 'ऑटो' कीवर्ड का उपयोग करने के लिए कोई कारण है? खिड़कियों पर सिमलिंक? सीएसआरएफ सत्यापन असफल रहा। अनुरोध को निरस्त कर दिया गया क्या स्थानीय कार्य घोषणाओं के लिए कोई फायदा है? घटकों का स्विफ्ट संस्करणसियरीकृतब्रास्ट्रिंग कनाडा के पोस्टल कोड सत्यापन स्प्रिंग एक्सएमएल कॉन्फ़िगरेशन में दिए गए प्रकार की सभी बीन्स कैसे एकत्र और इंजेक्षन करें wpf में फ़ाइल पथ की सूची से ट्रीदृश्य को पॉप्युलेट करें सी # स्ट्रिंग से वर्ण निकालें Qt में क्रॉस-थ्रेड सिग्नल कैसे निकल जाए?

पायथन – प्रारंभिक क्षमता के साथ एक सूची बनाएं

अक्सर ऐसा कोड होता है:

l = [] while foo: #baz l.append(bar) #qux 

यह वास्तव में धीमी है अगर आप अपनी सूची में हजारों तत्व जोड़ना चाहते हैं, क्योंकि सूची को नए तत्वों के अनुरूप करने के लिए लगातार आकार बदलना होगा

जावा में, आप एक प्रारंभिक क्षमता के साथ एक ArrayList बना सकते हैं। यदि आपके पास कुछ विचार है कि आपकी सूची कितनी बड़ी होगी, यह बहुत अधिक कुशल होगी

मैं समझता हूं कि इस तरह से कोड अक्सर सूची की समझ में पुन: सकारात्मक हो सकता है। यदि / के लिए लूप बहुत जटिल है, हालांकि, यह अव्यावहारिक है। क्या हमारे लिए पायथन प्रोग्रामर के बराबर है?

Solutions Collecting From Web of "पायथन – प्रारंभिक क्षमता के साथ एक सूची बनाएं"

 def doAppend( size=10000 ): result = [] for i in range(size): message= "some unique object %d" % ( i, ) result.append(message) return result def doAllocate( size=10000 ): result=size*[None] for i in range(size): message= "some unique object %d" % ( i, ) result[i]= message return result 

परिणाम (144 गुना प्रत्येक समारोह का मूल्यांकन करें और अवधि औसत)

 simple append 0.0102 pre-allocate 0.0098 

निष्कर्ष यह मुश्किल से मायने रखता है

सभी बुराईयो की जड़ समयपूर्व इष्टतमीकरण है।

पायथन सूचियों में कोई अंतर्निहित पूर्व-आवंटन नहीं है। अगर आपको वास्तव में एक सूची बनाने की ज़रूरत है, और जोड़ने की उपरि से बचने की आवश्यकता है (और आपको यह सत्यापित करना चाहिए कि आप करते हैं), तो आप यह कर सकते हैं:

 l = [None] * 1000 # Make a list of 1000 None's for i in xrange(1000): # baz l[i] = bar # qux 

शायद आप इसके बजाय जनरेटर का उपयोग करके सूची से बच सकते हैं:

 def my_things(): while foo: #baz yield bar #qux for thing in my_things(): # do something with thing 

इस तरह, सूची हर मेमोरी में सभी संग्रहीत नहीं होती है, केवल आवश्यकतानुसार उत्पन्न होती है।

लघु संस्करण: उपयोग करें

 pre_allocated_list = [None] * size 

एक सूची को पहले से आवंटित करने के लिए (जो कि सूची के 'आकार' तत्वों को संबोधित करने में सक्षम होने के बजाय, धीरे-धीरे सूची को जोड़कर) यह कार्रवाई बहुत बड़ी है, बड़ी सूचियों पर भी। नई वस्तुओं को आवंटित करना जो बाद में तत्वों को सूचीबद्ध करने के लिए सौंपे जाएंगे, उन्हें बहुत अधिक समय लगेगा और आपके प्रोग्राम में बाधा उत्पन्न होगी, प्रदर्शन-वार

दीर्घ संस्करण:

मुझे लगता है कि आरंभीकरण के समय को ध्यान में रखा जाना चाहिए। चूंकि अजगर में सब कुछ एक संदर्भ है, इससे कोई फर्क नहीं पड़ता कि आप प्रत्येक तत्व को कोई भी या कुछ स्ट्रिंग में सेट करते हैं – या तो यह केवल एक संदर्भ है यद्यपि यह अधिक समय लगेगा यदि आप संदर्भ के लिए प्रत्येक तत्व के लिए नया ऑब्जेक्ट बनाना चाहते हैं।

पायथन 3.2 के लिए:

 import time import copy def print_timing (func): def wrapper (*arg): t1 = time.time () res = func (*arg) t2 = time.time () print ("{} took {} ms".format (func.__name__, (t2 - t1) * 1000.0)) return res return wrapper @print_timing def prealloc_array (size, init = None, cp = True, cpmethod=copy.deepcopy, cpargs=(), use_num = False): result = [None] * size if init is not None: if cp: for i in range (size): result[i] = init else: if use_num: for i in range (size): result[i] = cpmethod (i) else: for i in range (size): result[i] = cpmethod (cpargs) return result @print_timing def prealloc_array_by_appending (size): result = [] for i in range (size): result.append (None) return result @print_timing def prealloc_array_by_extending (size): result = [] none_list = [None] for i in range (size): result.extend (none_list) return result def main (): n = 1000000 x = prealloc_array_by_appending(n) y = prealloc_array_by_extending(n) a = prealloc_array(n, None) b = prealloc_array(n, "content", True) c = prealloc_array(n, "content", False, "some object {}".format, ("blah"), False) d = prealloc_array(n, "content", False, "some object {}".format, None, True) e = prealloc_array(n, "content", False, copy.deepcopy, "a", False) f = prealloc_array(n, "content", False, copy.deepcopy, (), False) g = prealloc_array(n, "content", False, copy.deepcopy, [], False) print ("x[5] = {}".format (x[5])) print ("y[5] = {}".format (y[5])) print ("a[5] = {}".format (a[5])) print ("b[5] = {}".format (b[5])) print ("c[5] = {}".format (c[5])) print ("d[5] = {}".format (d[5])) print ("e[5] = {}".format (e[5])) print ("f[5] = {}".format (f[5])) print ("g[5] = {}".format (g[5])) if __name__ == '__main__': main() 

मूल्यांकन:

 prealloc_array_by_appending took 118.00003051757812 ms prealloc_array_by_extending took 102.99992561340332 ms prealloc_array took 3.000020980834961 ms prealloc_array took 49.00002479553223 ms prealloc_array took 316.9999122619629 ms prealloc_array took 473.00004959106445 ms prealloc_array took 1677.9999732971191 ms prealloc_array took 2729.999780654907 ms prealloc_array took 3001.999855041504 ms x[5] = None y[5] = None a[5] = None b[5] = content c[5] = some object blah d[5] = some object 5 e[5] = a f[5] = [] g[5] = () 

जैसा कि आप देख सकते हैं, बस किसी भी वस्तु के संदर्भों की एक बड़ी सूची बना कर किसी भी वस्तु को बहुत कम समय लगता है

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

प्रत्येक तत्व के लिए नई ऑब्जेक्ट को आवंटित करना – यही है जो सबसे अधिक समय लेता है। और एस लोट्ट का उत्तर ऐसा करता है – हर बार एक नई स्ट्रिंग प्रारूपित करता है जो सख्ती से जरूरी नहीं है – यदि आप कुछ स्थान पूर्व-आवंटित करना चाहते हैं, तो बस किसी की सूची बनाएं, फिर इच्छा के तत्वों को सूचीबद्ध करने के लिए डेटा असाइन करें। किसी सूची को जोड़ने / जोड़ने की तुलना में डेटा उत्पन्न करने के लिए किसी भी तरह से अधिक समय लगता है, चाहे वह सूची बनाते समय या उसके बाद उत्पन्न हो लेकिन यदि आप कम-से-कम आबादी वाली सूची चाहते हैं, तो किसी की सूची से शुरू करना निश्चित रूप से तेज है

इस के लिए पायथनिक तरीका है:

 x = [None] * numElements 

या आप जिस भी डिफ़ॉल्ट मान को तैयार करना चाहते हैं, उदाहरण के लिए

 bottles = [Beer()] * 99 sea = [Fish()] * many vegetarianPizzas = [None] * peopleOrderingPizzaNotQuiche 

अजगर का डिफ़ॉल्ट दृष्टिकोण बहुत ही कुशल हो सकता है, हालांकि यह कि क्षमता घटता है क्योंकि आप तत्वों की संख्या में वृद्धि करते हैं।

तुलना

 import time class Timer(object): def __enter__(self): self.start = time.time() return self def __exit__(self, *args): end = time.time() secs = end - self.start msecs = secs * 1000 # millisecs print('%fms' % msecs) Elements = 100000 Iterations = 144 print('Elements: %d, Iterations: %d' % (Elements, Iterations)) def doAppend(): result = [] i = 0 while i < Elements: result.append(i) i += 1 def doAllocate(): result = [None] * Elements i = 0 while i < Elements: result[i] = i i += 1 def doGenerator(): return list(i for i in range(Elements)) def test(name, fn): print("%s: " % name, end="") with Timer() as t: x = 0 while x < Iterations: fn() x += 1 test('doAppend', doAppend) test('doAllocate', doAllocate) test('doGenerator', doGenerator) 

साथ में

 #include <vector> typedef std::vector<unsigned int> Vec; static const unsigned int Elements = 100000; static const unsigned int Iterations = 144; void doAppend() { Vec v; for (unsigned int i = 0; i < Elements; ++i) { v.push_back(i); } } void doReserve() { Vec v; v.reserve(Elements); for (unsigned int i = 0; i < Elements; ++i) { v.push_back(i); } } void doAllocate() { Vec v; v.resize(Elements); for (unsigned int i = 0; i < Elements; ++i) { v[i] = i; } } #include <iostream> #include <chrono> using namespace std; void test(const char* name, void(*fn)(void)) { cout << name << ": "; auto start = chrono::high_resolution_clock::now(); for (unsigned int i = 0; i < Iterations; ++i) { fn(); } auto end = chrono::high_resolution_clock::now(); auto elapsed = end - start; cout << chrono::duration<double, milli>(elapsed).count() << "ms\n"; } int main() { cout << "Elements: " << Elements << ", Iterations: " << Iterations << '\n'; test("doAppend", doAppend); test("doReserve", doReserve); test("doAllocate", doAllocate); } 

मेरे विंडोज 7 आई 7 पर, 64-बिट पायथन देता है

 Elements: 100000, Iterations: 144 doAppend: 3587.204933ms doAllocate: 2701.154947ms doGenerator: 1721.098185ms 

जबकि सी ++ देता है (एमएसवीसी, 64-बिट, अनुकूलन सक्षम के साथ बनाया गया)

 Elements: 100000, Iterations: 144 doAppend: 74.0042ms doReserve: 27.0015ms doAllocate: 5.0003ms 

सी ++ डिबग बिल्ड का उत्पादन:

 Elements: 100000, Iterations: 144 doAppend: 2166.12ms doReserve: 2082.12ms doAllocate: 273.016ms 

यहां बताया गया है कि पायथन के साथ आप 7-8% प्रदर्शन सुधार प्राप्त कर सकते हैं, और अगर आपको लगता है कि आप उच्च-प्रदर्शन ऐप (या यदि आप कुछ लिख रहे हैं जो वेब सेवा या किसी चीज़ में उपयोग किया जाता है) लिख रहे हैं, तो उस पर सूँघना नहीं है, लेकिन आपको भाषा की अपनी पसंद पर पुनर्विचार करने की आवश्यकता हो सकती है।

इसके अलावा, यहां पायथन कोड वास्तव में पायथन कोड नहीं है। वास्तव में पायथनॉसेक कोड पर स्विच करना बेहतर प्रदर्शन देता है:

 import time class Timer(object): def __enter__(self): self.start = time.time() return self def __exit__(self, *args): end = time.time() secs = end - self.start msecs = secs * 1000 # millisecs print('%fms' % msecs) Elements = 100000 Iterations = 144 print('Elements: %d, Iterations: %d' % (Elements, Iterations)) def doAppend(): for x in range(Iterations): result = [] for i in range(Elements): result.append(i) def doAllocate(): for x in range(Iterations): result = [None] * Elements for i in range(Elements): result[i] = i def doGenerator(): for x in range(Iterations): result = list(i for i in range(Elements)) def test(name, fn): print("%s: " % name, end="") with Timer() as t: fn() test('doAppend', doAppend) test('doAllocate', doAllocate) test('doGenerator', doGenerator) 

जो देता है

 Elements: 100000, Iterations: 144 doAppend: 2153.122902ms doAllocate: 1346.076965ms doGenerator: 1614.092112ms 

(32-बिट doGenerator में doAllocate से बेहतर होता है)

यहां doAppend और doAllocate के बीच का अंतर काफी बड़ा है।

जाहिर है, यहां पर मतभेद वास्तव में केवल तभी लागू होते हैं यदि आप कई बार मुनाफ़े से अधिक कर रहे हैं या यदि आप इसे भारी लोड किए गए सिस्टम पर कर रहे हैं, जहां उन नंबरों को परिमाण के आदेश से बढ़ाया जा रहा है, या यदि आप काफी बड़ी सूचियां

यहां बिंदु: सर्वोत्तम प्रदर्शन के लिए यह अजगर का तरीका है।

लेकिन अगर आप सामान्य, उच्च-स्तरीय प्रदर्शन के बारे में चिंतित हैं, तो अजगर गलत भाषा है सबसे मूलभूत समस्या यह है कि पायथन फंक्शन कॉल पारंपरिक रूप से अन्य भाषाओं की तुलना में 300x तक धीमी गति से हो रही है, क्योंकि सजावट आदि जैसे पाइथन सुविधाओं ( https://wiki.python.org/moin/PythonSpeed/PerformanceTips#Data_Aggregation#Data_Aggregation )।

मैं @ एस। लोट्स कोड चलाया और प्री-आवंटन के द्वारा समान 10% की बढ़ोतरी का उत्पादन किया। जनरेटर का प्रयोग करके जेरेमी के विचार की कोशिश की, और doAllocate के मुकाबले जीन के बेहतर देखने में सक्षम था मेरे प्रोजेक्शन के लिए 10% सुधार का मामला है, इसलिए सभी के लिए धन्यवाद, क्योंकि यह एक गुच्छा में मदद करता है।

 def doAppend( size=10000 ): result = [] for i in range(size): message= "some unique object %d" % ( i, ) result.append(message) return result def doAllocate( size=10000 ): result=size*[None] for i in range(size): message= "some unique object %d" % ( i, ) result[i]= message return result def doGen( size=10000 ): return list("some unique object %d" % ( i, ) for i in xrange(size)) size=1000 @print_timing def testAppend(): for i in xrange(size): doAppend() @print_timing def testAlloc(): for i in xrange(size): doAllocate() @print_timing def testGen(): for i in xrange(size): doGen() testAppend() testAlloc() testGen() testAppend took 14440.000ms testAlloc took 13580.000ms testGen took 13430.000ms 

पायथन में पूर्व-आवंटन के बारे में चिंताएं उत्पन्न होती हैं यदि आप संख्यात्मक के साथ काम कर रहे हैं, जिसमें अधिक सी-जैसे सरणियां हैं इस उदाहरण में, पूर्व आवंटन की चिंताएं डेटा के आकार और डिफ़ॉल्ट मान के बारे में हैं।

यदि आप बड़े पैमाने पर सूचियों पर संख्यात्मक गणना कर रहे हैं और प्रदर्शन चाहते हैं, तो अंडाकार पर विचार करें

जैसा कि अन्य लोगों ने उल्लेख किया है, कोई भी NoneType ऑब्जेक्ट के साथ प्री-बीड की सूची का सबसे आसान तरीका

कहा जा रहा है, आपको यह समझने चाहिए कि वास्तव में यह तय करने से पहले पायथन की सूची वास्तव में काम करने के लिए आवश्यक है। एक सूची के CPython कार्यान्वयन में, अंतर्निहित सरणी हमेशा ओवरहेड रूम के साथ, उत्तरोत्तर बड़े आकार ( 4, 8, 16, 25, 35, 46, 58, 72, 88, 106, 126, 148, 173, 201, 233, 269, 309, 354, 405, 462, 526, 598, 679, 771, 874, 990, 1120, etc) , ताकि सूची का आकार बदलने के लगभग इतनी बार ऐसा न हो।

इस व्यवहार की वजह से, अधिकांश list.append() फ़ंक्शन O(1) एपेंड के लिए जटिलता है, केवल इन सीमाओं में से एक को पार करते समय जटिलता बढ़ती जा रही है, उस बिंदु पर जटिलता O(n) । यह व्यवहार एस लोट के उत्तर में निष्पादन समय में न्यूनतम वृद्धि की ओर जाता है।

स्रोत: http://www.laurentluce.com/posts/python-list-implementation/

मैं जो समझता हूं, अजगर सूचियां पहले से ही ArrayLists के समान हैं I लेकिन अगर आप उन मापदंडों को सुधारना चाहते हैं तो मुझे यह पोस्ट नेट पर मिली, जो कि दिलचस्प हो सकती है (मूलतः, सिर्फ अपनी ScalableList एक्सटेंशन बनाएं):

http://mail.python.org/pipermail/python-list/2000-May/035082.html

कुछ एप्लिकेशन के लिए, एक शब्दकोश हो सकता है जिसे आप खोज रहे हैं। उदाहरण के लिए, find_totient विधि में, मुझे कोई शब्दकोश प्रयोग करने में अधिक सुविधाजनक पाया गया क्योंकि मेरे पास शून्य सूचकांक नहीं था

 def totient(n): totient = 0 if n == 1: totient = 1 else: for i in range(1, n): if math.gcd(i, n) == 1: totient += 1 return totient def find_totients(max): totients = dict() for i in range(1,max+1): totients[i] = totient(i) print('Totients:') for i in range(1,max+1): print(i,totients[i]) 

इस समस्या को एक पूर्ववत सूची के साथ हल किया जा सकता है:

 def find_totients(max): totients = None*(max+1) for i in range(1,max+1): totients[i] = totient(i) print('Totients:') for i in range(1,max+1): print(i,totients[i]) 

मुझे लगता है कि यह उतना ही सुरुचिपूर्ण नहीं है और बगों से ग्रस्त है क्योंकि मैं कोई नहीं रोक रहा हूं, जो अपवाद फेंक सकता है अगर मैं गलती से उन्हें गलत तरीके से इस्तेमाल कर सकता हूं, और क्योंकि मुझे किन मामलों के बारे में सोचने की ज़रूरत है जो नक्शा मुझे बचने देता है

यह सच है कि डिक्शनरी के रूप में कुशल नहीं होगा, लेकिन जैसा कि दूसरों ने टिप्पणी की है, गति में छोटे अंतर हमेशा महत्वपूर्ण रखरखाव के खतरे के लायक नहीं होते हैं।