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


188

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

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

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

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

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


12
जहाँ तक मुझे पता है, वे ArrayLists के समान हैं जिसमें वे हर बार अपना आकार दोगुना करते हैं। इस ऑपरेशन का परिशोधन समय स्थिर है। यह उतना बड़ा प्रदर्शन नहीं है जितना आप सोचेंगे।
21

लगता है जैसे तुम सही हो!
क्लाउडीयू

11
शायद ओपी के परिदृश्य के लिए पूर्व-प्रारंभिककरण की सख्त आवश्यकता नहीं है, लेकिन कभी-कभी निश्चित रूप से इसकी आवश्यकता होती है: मेरे पास कई पूर्व-अनुक्रमित आइटम हैं जिन्हें एक विशिष्ट सूचकांक में सम्मिलित करने की आवश्यकता है, लेकिन वे क्रम से बाहर आते हैं। IndexErrors से बचने के लिए मुझे सूची को आगे बढ़ाने की आवश्यकता है। इस सवाल के लिए धन्यवाद।
नील ट्रैफ्ट

1
@ कोलुडु स्वीकार किया गया जवाब भ्रामक है। इसके तहत सबसे ज्यादा उठी टिप्पणी बताती है कि क्यों। क्या आप अन्य उत्तरों में से एक को स्वीकार करने पर विचार करेंगे?
नील गोकली

जवाबों:


125
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

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

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


18
क्या होगा यदि उपदेश विधि (आकार * [कोई नहीं]) अक्षम हो? क्या अजगर वीएम वास्तव में सूची को एक बार में आवंटित करता है, या इसे धीरे-धीरे बढ़ता है, जैसे कि एपेंड () होगा?
haridsv

9
अरे। यह संभवत: अजगर में व्यक्त किया जा सकता है, लेकिन किसी ने अभी तक इसे यहां पोस्ट नहीं किया है। haridsv की बात यह थी कि हम सिर्फ 'int * लिस्ट' मान रहे हैं, यह सिर्फ आइटम के द्वारा लिस्ट में नहीं आता। यह धारणा संभवत: मान्य है, लेकिन haridsv की बात यह थी कि हमें इसकी जाँच करनी चाहिए। यदि यह मान्य नहीं था, तो यह बताएगा कि जिन दो कार्यों को आपने दिखाया था वे लगभग समान समय लेते हैं - क्योंकि कवर के तहत, वे वास्तव में एक ही काम कर रहे हैं, इसलिए वास्तव में इस प्रश्न के विषय का परीक्षण नहीं किया है। सादर!
जोनाथन हार्टले

136
यह मान्य नहीं है; आप प्रत्येक पुनरावृत्ति के साथ एक स्ट्रिंग का प्रारूपण कर रहे हैं, जो आपके परीक्षण के लिए हमेशा के सापेक्ष लेता है। इसके अतिरिक्त, यह देखते हुए कि स्थिति के आधार पर 4% अभी भी महत्वपूर्ण हो सकता है, और यह एक कम आंका गया है ...
फिलिप गिनी

40
जैसा कि @Philip बताते हैं कि यहां निष्कर्ष भ्रामक है। प्रीरेक्लोकेशन यहां मायने नहीं रखता क्योंकि स्ट्रिंग फॉर्मेटिंग ऑपरेशन महंगा है। मैंने लूप में एक सस्ते ऑपरेशन के साथ परीक्षण किया और पाया कि उपदेशात्मकता लगभग दोगुनी है।
कीथ

12
कई अपवित्रों के साथ गलत जवाब सभी बुराई की एक और जड़ है।
हाशिमोटो

80

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

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

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


7
सूचियों के बजाय +1 जेनरेटर। कई एल्गोरिदम को पूर्ण-भौतिक सूची के बजाय जनरेटर के साथ काम करने के लिए थोड़ा संशोधित किया जा सकता है।
एस.लॉट

जनरेटर एक अच्छा विचार है, सच है। मैं सेटिंग में इन-प्लेस के अलावा इसे करने का सामान्य तरीका चाहता था। मुझे लगता है कि अंतर मामूली है, thoguh है।
क्लाउडीयू

50

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

pre_allocated_list = [None] * size

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

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

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

पायथन 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] = ()

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

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

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


हां दिलचस्प। तो उत्तर घुन होना - यह वास्तव में कोई फर्क नहीं पड़ता है अगर आप किसी सूची में तत्वों को डालने के लिए कोई ऑपरेशन कर रहे हैं, लेकिन अगर आप वास्तव में सभी समान तत्वों की एक बड़ी सूची चाहते हैं, तो आपको []*दृष्टिकोण का उपयोग करना चाहिए
Claudiu

26

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

x = [None] * numElements

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

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

[संपादित करें: कैविट एम्प्टर एक [Beer()] * 99वाक्य रचना बनाता है Beer और फिर एक एकल उदाहरण के लिए ९९ संदर्भों के साथ एक सरणी को पॉप्युलेट करता है]

जब आप तत्वों की संख्या बढ़ाते हैं तो पायथन का डिफ़ॉल्ट दृष्टिकोण काफी कुशल हो सकता है।

तुलना

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 i7 पर, 64-बिट पायथन देता है

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

जबकि C ++ देता है (MSVC के साथ निर्मित, 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 के बीच का अंतर काफी बड़ा है।

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

यहाँ बिंदु: यह सबसे अच्छा प्रदर्शन के लिए pythonic तरीका है।

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


@NilsvonBarth C ++ में नहीं हैtimeit
kfsone

अजगर के पास है timeit, जिसका उपयोग आपको अपने पायथन कोड को करते समय करना चाहिए; मैं सी ++ के बारे में बात नहीं कर रहा हूं, जाहिर है।
निल्स वॉन बर्थ

4
यह सही उत्तर नहीं है। bottles = [Beer()] * 9999 बीयर ऑब्जेक्ट्स नहीं बनाता है। इसके बजाय, 99 संदर्भों के साथ एक बीयर ऑब्जेक्ट बनाता है। यदि आप इसे म्यूट करेंगे, तो सूची के सभी तत्व उत्परिवर्तित हो जाएंगे, (bottles[i] is bootles[j]) == Trueप्रत्येक के लिए कारण i != j. 0<= i, j <= 99
erestesto

@erhesto आपने उत्तर को सही नहीं माना है, क्योंकि लेखक ने सूची भरने के लिए उदाहरण के रूप में संदर्भों का उपयोग किया है? सबसे पहले, किसी को 99 बीयर ऑब्जेक्ट (एक वस्तु और 99 संदर्भ के रूप में) बनाने की आवश्यकता नहीं है। प्रीपोपुलेशन (वह किस बारे में बात करता है) के मामले में, तेजी से बेहतर है, क्योंकि मूल्य को बाद में बदल दिया जाएगा। दूसरा, इसका उत्तर संदर्भ या उत्परिवर्तन के बारे में बिल्कुल नहीं है। आपको बड़ी तस्वीर याद आ रही है।
योंगवेई वू

@YongweiWu तुम वास्तव में सही हो। यह उदाहरण पूरे उत्तर को गलत नहीं बनाता है, यह केवल भ्रामक हो सकता है और यह केवल उल्लेख के लायक है।
erestesto

8

जैसा कि दूसरों ने उल्लेख किया है, 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/


4

मैंने @ s.lott का कोड चलाया और पूर्व-आवंटन द्वारा समान 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

5
"मेरे प्रोज के लिए 10% सुधार के मामले"? वास्तव में? आप कर सकते हैं साबित है कि सूची आवंटन है टोंटी? मैं उस पर और देखना चाहता हूं। क्या आपके पास एक ब्लॉग है जहां आप बता सकते हैं कि यह वास्तव में कैसे मदद करता है?
S.Lott

2
@ S.Lott परिमाण के एक क्रम से आकार को उछालने का प्रयास करें; प्रदर्शन परिमाण के 3 क्रमों से गिरता है (C ++ की तुलना में जहाँ प्रदर्शन परिमाण के एक ही क्रम से थोड़ा अधिक घटता है)।
kfsone

2
यह मामला हो सकता है क्योंकि जैसे-जैसे एक सरणी बढ़ती है, इसे स्मृति में चारों ओर ले जाना पड़ सकता है। (यह सोचें कि एक के बाद एक वस्तुओं को वहाँ कैसे संग्रहीत किया जाता है।)
एवगेनी सर्गेव

3

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

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


0

कुछ अनुप्रयोगों के लिए, एक शब्दकोष वह हो सकता है जिसे आप खोज रहे हैं। उदाहरण के लिए, 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])

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

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


-1

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

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.