পাইথন - প্রাথমিক ক্ষমতা সহ একটি তালিকা তৈরি করুন


187

এর মতো কোড প্রায়শই ঘটে:

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

আপনি যদি আপনার তালিকায় হাজার হাজার উপাদান যুক্ত করতে চলেছেন তবে এটি সত্যিই ধীর, কারণ নতুন উপাদানগুলির সাথে তাল মিলিয়ে তালিকার জন্য ক্রমাগত আকার পরিবর্তন করতে হবে।

জাভাতে, আপনি প্রাথমিক ক্ষমতা সহ একটি অ্যারেলিস্ট তৈরি করতে পারেন। আপনার তালিকাটি কত বড় হবে সে সম্পর্কে আপনার যদি ধারণা থাকে তবে এটি আরও কার্যকর হবে।

আমি বুঝতে পারি যে এর মতো কোডটি প্রায়শই একটি তালিকা বোঝার জন্য পুনরায় ফ্যাক্টর করা যেতে পারে। যদি / যখন লুপটি খুব জটিল হয় তবে এটি অপরিবর্তনীয়। পাইথন প্রোগ্রামারদের জন্য আমাদের সমতুল্য কি আছে?


12
যতদূর আমি জানি, তারা অ্যারেলিস্টগুলির সাথে সমান যে তারা প্রতিবারের আকার দ্বিগুণ করে। এই ক্রিয়াকলাপের সূক্ষ্ম সময় স্থির। এটি আপনি যে ভাবেন ঠিক তেমন পারফরম্যান্সের হিট নয়।
এমএমসিডোল

আপনি ঠিক মত মনে হচ্ছে!
ক্লাদিউ

10
সম্ভবত প্রাক-প্রারম্ভিককরণটি ওপি-র দৃশ্যের জন্য কঠোরভাবে প্রয়োজন হয় না, তবে কখনও কখনও এটি অবশ্যই প্রয়োজন হয়: আমার কাছে বেশ কয়েকটি প্রাক-ইনডেক্সযুক্ত আইটেম রয়েছে যা একটি নির্দিষ্ট সূচীতে beোকানো দরকার, তবে সেগুলি ক্রম থেকে বেরিয়ে আসে। সূচিপত্রগুলি এড়াতে আমার আগে তালিকার বাড়ানো দরকার। এই প্রশ্নের জন্য ধন্যবাদ।
নিল ট্রাফ্ট

1
@ ক্লডিউ গৃহীত উত্তরগুলি বিভ্রান্তিমূলক। এর অধীনে সর্বোচ্চ-আপোভিত মন্তব্যটি কেন তা ব্যাখ্যা করে। আপনি অন্য একটি উত্তর গ্রহণ বিবেচনা করবেন?
নিল গোকলি 31'18

উত্তর:


126
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
যদি পূর্বনির্ধারণ পদ্ধতি (আকার * [কিছুই নয়]) নিজেই অদক্ষ হয়? পাইথন ভিএম কি আসলেই তালিকাকে একবারে বরাদ্দ দেয়, বা ধীরে ধীরে বৃদ্ধি করে, ঠিক যেমন অ্যাপেন্ড () করবে?
হরিদসভ

9
আরে। এটি সম্ভবত পাইথনে প্রকাশ করা যেতে পারে তবে এখনও কেউ এটি এখানে পোস্ট করেননি। হরিদসভের বক্তব্যটি হ'ল আমরা কেবল ধরে নিচ্ছি যে 'ইনট * তালিকা' কেবল আইটেমের মাধ্যমে তালিকার আইটেমের সাথে যুক্ত হবে না। এই অনুমানটি সম্ভবত বৈধ, তবে হরিদসভের বক্তব্যটি ছিল আমাদের এটি পরীক্ষা করা উচিত। যদি এটি বৈধ না হয়, তবে এটি ব্যাখ্যা করবে যে আপনি যে দুটি ফাংশন দেখিয়েছেন তা প্রায় অভিন্ন সময় নেয় কেন - কারণ প্রচ্ছদের অধীনে, তারা ঠিক একই জিনিস করছে, তাই প্রকৃতপক্ষে এই প্রশ্নের বিষয়টিকে পরীক্ষা করে দেখেনি। শুভেচ্ছান্তে!
জোনাথন হার্টলি

135
এটি বৈধ নয়; আপনি প্রতিটি পুনরাবৃত্তির সাথে একটি স্ট্রিং ফর্ম্যাট করছেন, যা আপনি যাচাই করার চেষ্টা করছেন তার তুলনায় চিরতরে লাগে। অতিরিক্ত হিসাবে, প্রদত্ত যে 4% এখনও পরিস্থিতির উপর নির্ভর করে তাত্পর্যপূর্ণ হতে পারে, এবং এটি একটি অল্প মূল্যবান ...
ফিলিপ গিন

39
@ ফিলিপ যেমন উপসংহারটি দেখায় এখানে বিভ্রান্তিকর। স্টাইল ফর্ম্যাটিং অপারেশন ব্যয়বহুল হওয়ায় এখানে পূর্বনির্ধারণের কোনও গুরুত্ব নেই। আমি লুপে একটি সস্তার অপারেশন দিয়ে পরীক্ষা করে দেখেছি যে প্রাকপরিমাণটি প্রায় দ্বিগুণ দ্রুত।
কিথ

11
অনেকগুলি উত্স সহ ভুল উত্তরগুলি হ'ল সমস্ত অশুভের আর একটি মূল।
হাশিমোটো

79

পাইথন তালিকাগুলির কোনও পূর্ব-বরাদ্দ নেই। আপনার যদি সত্যিই একটি তালিকা তৈরি করতে হয় এবং এডিংয়ের ওভারহেড এড়ানো প্রয়োজন হয় (এবং আপনার যা যা করা উচিত তা যাচাই করা উচিত), আপনি এটি করতে পারেন:

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 জেনারেটর। অনেক অ্যালগরিদমগুলি পূর্ণ-পদার্থযুক্ত তালিকার পরিবর্তে জেনারেটরের সাথে কাজ করতে কিছুটা সংশোধন করা যেতে পারে।
এসলট

জেনারেটর একটি ভাল ধারণা, সত্য। আমি জায়গাটিতে স্থাপনের পাশাপাশি এটি করার একটি সাধারণ উপায় চাইছিলাম। আমার মনে হয় পার্থক্যটি সামান্য, থোগুহ।
ক্লাদিউ

50

সংক্ষিপ্ত সংস্করণ: ব্যবহার

pre_allocated_list = [None] * size

কোনও তালিকা প্রাক-বরাদ্দ করা (যেটি ধীরে ধীরে সংযোজন করে তালিকা গঠনের পরিবর্তে তালিকার 'আকার' উপাদানগুলিকে সম্বোধন করতে সক্ষম হওয়া)। এমনকি বড় তালিকাতেও এই অপারেশনটি খুব দ্রুত। নতুন উপাদানগুলিকে বরাদ্দ করা হবে যা পরবর্তীতে উপাদানগুলির তালিকাতে নির্ধারিত হবে অনেক বেশি সময় লাগবে এবং আপনার কর্মক্ষমতা-ভিত্তিতে বাধা হয়ে দাঁড়াবে।

দীর্ঘ সংস্করণ:

আমি মনে করি ইনিশিয়েশন সময়টি আমলে নেওয়া উচিত। যেহেতু অজগরটিতে সবকিছুই একটি রেফারেন্স, আপনি প্রতিটি উপাদানকে কোনওটি বা কোনও স্ট্রিংয়ে সেট করে রাখেন তা বিবেচ্য নয় - এটি কেবলমাত্র একটি রেফারেন্স। যদিও আপনি প্রতিটি উপাদানের রেফারেন্সের জন্য নতুন অবজেক্ট তৈরি করতে চান তবে এটি আরও বেশি সময় নেবে।

পাইথন ৩.২ এর জন্য:

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] = ()

যেমন আপনি দেখতে পাচ্ছেন, কেবল একই নয় কোনও বস্তুর উল্লেখের জন্য একটি বড় তালিকা তৈরি করতে খুব কম সময় লাগে।

প্রস্তুতি বা প্রসারিত করতে বেশি সময় লাগে (আমি কোনও গড় গড়াই নি, তবে কয়েকবার এটি চালানোর পরে আমি আপনাকে বলতে পারি যে প্রসারিত এবং সংযোজন মোটামুটি একই সময় নেয়)।

প্রতিটি উপাদানের জন্য নতুন অবজেক্ট বরাদ্দ করা - এটাই সর্বাধিক সময় নেয়। এবং এস.লোটের উত্তরটি তা করে - প্রতিবার একটি নতুন স্ট্রিং ফর্ম্যাট করে। যা কঠোরভাবে প্রয়োজন হয় না - আপনি যদি কিছু জায়গা প্রাক-বরাদ্দ করতে চান তবে কেবল কোনওটির একটি তালিকা তৈরি করুন, তারপরে ইচ্ছামত উপাদানগুলির তালিকা তৈরি করতে ডেটা বরাদ্দ করুন। যে কোনও উপায়ে তালিকা সংযোজন / প্রসারিত করার চেয়ে ডেটা উত্পন্ন করতে আরও সময় লাগে, আপনি তালিকা তৈরির সময় তৈরি করেছেন কিনা, বা তার পরে। তবে আপনি যদি খুব কম জনবহুল তালিকা চান তবে কোনওটির তালিকা দিয়ে শুরু করা অবশ্যই দ্রুততর।


হুঁ মজার। তাই উত্তর হতে ফোঁটা - এটি সত্যিই ব্যাপার স্বল্পতা আপনি একটি তালিকায় উপাদান রাখবেন কোনো অপারেশন করছেন, কিন্তু আপনি ব্যবহার করা উচিত যদি সত্যিই মাত্র সব একই উপাদান একটি বড় তালিকা চান []*পদ্ধতির
Claudiu

26

এর জন্য পাইথোনিক উপায়টি হ'ল:

x = [None] * numElements

অথবা পূর্বনির্ধারিত মানটি যা আপনি প্রিপআপ করতে চান, যেমন

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

[সম্পাদনা করুন: ক্রেতা সাবধান নীতি দ্য [Beer()] * 99সিনট্যাক্স সৃষ্টি এক Beer এবং তারপর একই একক ক্ষেত্রটিকেই 99 রেফারেন্স সহ একটি বিন্যাস মান]

পাইথনের ডিফল্ট পদ্ধতিটি বেশ দক্ষ হতে পারে, যদিও উপাদানগুলির সংখ্যা বৃদ্ধি করার সাথে সাথে সেই দক্ষতা হ্রাস পায়।

তুলনা করা

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 doAllocon চেয়ে ভাল করে)।

এখানে ডোঅ্যাপেন্ড এবং ডোঅলোকোটের মধ্যে ব্যবধানটি উল্লেখযোগ্যভাবে বৃহত্তর।

স্পষ্টতই, এখানে পার্থক্যগুলি কেবলমাত্র তখনই প্রযোজ্য যদি আপনি কয়েকবারের চেয়ে বেশি সময় এটি করে থাকেন বা আপনি যদি ভারী বোঝাই ব্যবস্থায় এটি করছেন যেখানে সেই সংখ্যাগুলি প্রশস্ততার অর্ডার দ্বারা বেরিয়ে যেতে চলেছে বা আপনি যদি এর সাথে লেনদেন করছেন যথেষ্ট বড় তালিকা।

এখানে বক্তব্য: সেরা অভিনয়ের জন্য এটি অজগর উপায়ে করুন।

তবে আপনি যদি সাধারণ, উচ্চ-স্তরের পারফরম্যান্স নিয়ে চিন্তিত হন তবে পাইথন হ'ল ভুল ভাষা। পাইথন ফাংশন কলগুলির সর্বাধিক মৌলিক সমস্যাটি পাইথন বৈশিষ্ট্যগুলির মতো পাইথন বৈশিষ্ট্যগুলির কারণে languagesতিহ্যগতভাবে অন্যান্য ভাষার তুলনায় 300x পর্যন্ত কম ছিল ( https://wiki.python.org/moin/PythonSpeed/PerformanceTips#Data_Agregation#Data_Agregation )।


@ নীলসনবার্থ সি ++ এর নেইtimeit
কেএফসনে

পাইথন রয়েছে timeit, যা আপনার পাইথন কোড টাইম করার সময় ব্যবহার করা উচিত; আমি সি ++ এর কথা বলছি না, স্পষ্টতই।
নিলস ভন বার্থ

4
এটি সঠিক উত্তর নয়। bottles = [Beer()] * 9999 বিয়ার অবজেক্ট তৈরি করে না। পরিবর্তে, এর সাথে 99 টি উল্লেখ সহ একটি বিয়ার অবজেক্ট তৈরি করে। আপনি যদি এটিকে পরিবর্তন করতে চান তবে তালিকার সমস্ত উপাদানকে পরিবর্তিত করা হবে, (bottles[i] is bootles[j]) == Trueপ্রত্যেকটির জন্য কারণ i != j. 0<= i, j <= 99
এরস্তো

@ এরেস্তো আপনি উত্তরটি সঠিক হিসাবে না বলে বিচার করেছেন কারণ লেখক একটি তালিকা পূরণের জন্য উদাহরণ হিসাবে উদাহরণ ব্যবহার করেছেন? প্রথমত, কেউই 99 বিয়ার অবজেক্ট তৈরি করার প্রয়োজন হয় না (বনাম একটি জিনিস এবং 99 রেফারেন্স হিসাবে)। প্রিপোপুলেশনের ক্ষেত্রে (তিনি কী সম্পর্কে কথা বলেছেন) দ্রুততর ভাল, কারণ পরে মানটি প্রতিস্থাপন করা হবে। দ্বিতীয়ত, উত্তর মোটেও রেফারেন্স বা মিউটেশন সম্পর্কে নয়। আপনি বড় ছবিটি মিস করছেন।
ইয়ংওয়েই উ

@ ইয়ংওয়েইউইউ আপনি সত্যই ঠিক বলেছেন। এই উদাহরণটি পুরো উত্তরটিকে ভুল করে না, এটি কেবল বিভ্রান্তিকর হতে পারে এবং এটি কেবল উল্লেখ করার মতো।
এরস্টো

8

অন্যরা যেমন উল্লেখ করেছেন, এর সাথে একটি তালিকা প্রাক-বীজের সবচেয়ে সহজ উপায় NoneType অবজেক্টের ।

এটি বলা হচ্ছে, পাইথন তালিকাগুলি আসলে এটির সিদ্ধান্ত নেওয়ার আগে যেভাবে কাজ করে তা বুঝতে হবে। তালিকার সিপিথন বাস্তবায়নে অন্তর্নিহিত অ্যারেটি সর্বদা ওভারহেড রুমের সাথে ক্রমান্বয়ে বৃহত্তর আকারে তৈরি করা হয় ( 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

আমি @ এস.লোটের কোড দৌড়েছি এবং প্রাক বরাদ্দকরণের মাধ্যমে একই 10% পারফরম্যান্স বৃদ্ধি করেছি। একটি জেনারেটর ব্যবহার করে @ জেরেমির ধারণার চেষ্টা করেছিলেন এবং জিনের পারফেক্টটি ডও অ্যালোকটের চেয়ে ভাল দেখতে সক্ষম হয়েছেন। আমার প্রজেক্টের জন্য 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% উন্নতির বিষয়"? সত্যি? আপনি করতে পারেন প্রমাণ সেই তালিকাটি বরাদ্দ হয় বোতলের? আমি এটি আরও দেখতে চাই। আপনার কী এমন কোনও ব্লগ আছে যেখানে আপনি ব্যাখ্যা করতে পারলেন যে এটি কীভাবে সাহায্য করেছিল?
এস .লট

2
@ এস.লট আকারের ক্রম দ্বারা আকারটিকে বাড়িয়ে দেওয়ার চেষ্টা করুন; পারফরম্যান্স 3 মাত্রার অর্ডার কমিয়ে দেয় (সি ++ এর সাথে তুলনায় যেখানে পারফরম্যান্স মাত্রার একক আদেশের চেয়ে কিছুটা কমবে)।
কেএফসনে

2
এটি ক্ষেত্রে হতে পারে কারণ অ্যারে বাড়ার সাথে সাথে এটি মেমরির আশেপাশে সরে যেতে হতে পারে। (কীভাবে সেখানে একের পর এক অবজেক্টগুলি সংরক্ষণ করা হয় তা ভেবে দেখুন))
এভেজেনি সার্জিয়েভ

3

পাইথনে প্রাক-বরাদ্দের বিষয়ে উদ্বেগ উত্থাপিত হয় যদি আপনি নাম্পের সাথে কাজ করছেন, যার সি-এর মতো আরও অ্যারে রয়েছে। এই উদাহরণে, প্রাক-বরাদ্দের উদ্বেগগুলি ডেটার আকৃতি এবং ডিফল্ট মান সম্পর্কে about

আপনি যদি বৃহত তালিকায় সংখ্যার গণনা করছেন এবং পারফরম্যান্স চান তবে নির্লজ্জ বিবেচনা করুন।


0

কিছু অ্যাপ্লিকেশনগুলির জন্য, অভিধান আপনি যা সন্ধান করছেন তা হতে পারে। উদাহরণস্বরূপ, ফাইন্ড_টোটিয়েন্ট পদ্ধতিতে, আমার কাছে শূন্য সূচক না থাকায় ডিকশনারিটি ব্যবহার করা আমার পক্ষে আরও সুবিধাজনক বলে মনে হয়েছে।

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

আমি যা বুঝি তা থেকে পাইথন তালিকাগুলি ইতিমধ্যে অ্যারেলিস্টগুলির সাথে বেশ মিল। তবে আপনি যদি এই পরামিতিগুলি টুইট করতে চান তবে আমি নেটটিতে এই পোস্টটি পেয়েছি যা আকর্ষণীয় হতে পারে (মূলত, কেবল নিজের ScalableListএক্সটেনশনটি তৈরি করুন ):

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

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