Bunun için Pythonic yolu:
x = [None] * numElements
veya önceden basmak istediğiniz varsayılan değerden herhangi biri, ör.
bottles = [Beer()] * 99
sea = [Fish()] * many
vegetarianPizzas = [None] * peopleOrderingPizzaNotQuiche
[DÜZENLEME: Uyarı Emptor[Beer()] * 99
sözdizimi oluşturur tek Beer
ve aynı bir örneğine 99 referansları ile bir dizi doldurur]
Python'un varsayılan yaklaşımı oldukça verimli olabilir, ancak eleman sayısını artırdıkça bu verimlilik azalır.
Karşılaştırmak
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)
ile
#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);
}
Windows 7 i7 cihazımda 64 bit Python
Elements: 100000, Iterations: 144
doAppend: 3587.204933ms
doAllocate: 2701.154947ms
doGenerator: 1721.098185ms
C ++ verirken (MSVC, 64 bit, Optimizasyonlar etkin)
Elements: 100000, Iterations: 144
doAppend: 74.0042ms
doReserve: 27.0015ms
doAllocate: 5.0003ms
C ++ hata ayıklama derlemesi üretir:
Elements: 100000, Iterations: 144
doAppend: 2166.12ms
doReserve: 2082.12ms
doAllocate: 273.016ms
Buradaki nokta, Python ile% 7-8 performans artışı elde edebileceğiniz ve yüksek performanslı bir uygulama yazdığınızı düşünüyorsanız (veya bir web hizmetinde veya başka bir şeyde kullanılan bir şey yazıyorsanız) koklamayacak, ancak dil seçiminizi yeniden düşünmeniz gerekebilir.
Ayrıca, buradaki Python kodu gerçekten Python kodu değildir. Burada gerçekten Pythonesque koduna geçmek daha iyi performans sağlar:
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)
Hangi verir
Elements: 100000, Iterations: 144
doAppend: 2153.122902ms
doAllocate: 1346.076965ms
doGenerator: 1614.092112ms
(32 bit doGenerator'da doAllocate'den daha iyi sonuç verir).
Burada doAppend ve doAllocate arasındaki boşluk önemli ölçüde daha büyük.
Açıkçası, buradaki farklar gerçekten sadece bunu bir avuçtan daha fazla yapıyorsanız veya bunu, bu sayıların büyüklük derecelerine göre ölçekleneceği ağır yüklü bir sistemde yapıyorsanız veya bununla uğraşıyorsanız geçerlidir. oldukça büyük listeler.
Buradaki nokta: En iyi performans için pythonic bir yol yapın.
Ancak genel, üst düzey performans konusunda endişeleniyorsanız, Python yanlış dildir. En temel sorun, dekoratörler vb . Gibi Python özellikleri nedeniyle Python işlev çağrılarının geleneksel olarak diğer dillerden 300 kat daha yavaş olmasıdır ( https://wiki.python.org/moin/PythonSpeed/PerformanceTips#Data_Aggregation#Data_Aggregation ).