Доступ к имени и присвоение имени различны. В вашем случае вы просто получаете доступ к имени.
Если вы назначаете переменную внутри функции, эта переменная считается локальной, если вы не объявляете ее глобальной. В отсутствие этого предполагается, что он глобальный.
>>> x = 1 # global
>>> def foo():
print x # accessing it, it is global
>>> foo()
1
>>> def foo():
x = 2 # local x
print x
>>> x # global x
1
>>> foo() # prints local x
2
Очень легкий иметь размеры...
В небольшом количестве кода обработки жесткого цикла, где я знаю, длина фиксируется , я использую массивы для того дополнительного крошечного бита микрооптимизации; массивы могут быть незначительно быстрее , если Вы используете индексатор / для формы - но IIRC полагают, что это зависит от типа данных в массиве. Но если Вы потребность для микрооптимизирования сохраните его простым и используйте List<T>
и т.д.
, Конечно, это только применяется при чтении всех данных; словарь был бы более быстрым для основанных на ключе поисков.
Вот мои результаты с помощью "интервала" (второе число является контрольной суммой, чтобы проверить, что они все сделали ту же работу):
(отредактированный для исправления ошибки)
List/for: 1971ms (589725196)
Array/for: 1864ms (589725196)
List/foreach: 3054ms (589725196)
Array/foreach: 1860ms (589725196)
на основе тестовой буровой установки:
using System;
using System.Collections.Generic;
using System.Diagnostics;
static class Program
{
static void Main()
{
List<int> list = new List<int>(6000000);
Random rand = new Random(12345);
for (int i = 0; i < 6000000; i++)
{
list.Add(rand.Next(5000));
}
int[] arr = list.ToArray();
int chk = 0;
Stopwatch watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
int len = list.Count;
for (int i = 0; i < len; i++)
{
chk += list[i];
}
}
watch.Stop();
Console.WriteLine("List/for: {0}ms ({1})", watch.ElapsedMilliseconds, chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
for (int i = 0; i < arr.Length; i++)
{
chk += arr[i];
}
}
watch.Stop();
Console.WriteLine("Array/for: {0}ms ({1})", watch.ElapsedMilliseconds, chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
foreach (int i in list)
{
chk += i;
}
}
watch.Stop();
Console.WriteLine("List/foreach: {0}ms ({1})", watch.ElapsedMilliseconds, chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
foreach (int i in arr)
{
chk += i;
}
}
watch.Stop();
Console.WriteLine("Array/foreach: {0}ms ({1})", watch.ElapsedMilliseconds, chk);
Console.ReadLine();
}
}
Начиная с List<> массивы использования внутренне, основная производительность должна быть тем же. Две причины, почему Список мог бы быть немного медленнее:
, Чтобы проверить, имеет ли это какое-либо значение для Вас, это является, вероятно, лучшим, корректируют отправленные функции синхронизации к списку размера, который Вы планируете использовать и видеть, как результаты для Вашего особого случая.
Измерения хороши, но Вы собираетесь получить существенно отличающиеся результаты в зависимости от того, что Вы делаете точно в Вашем внутреннем цикле. Измерьте свою собственную ситуацию. Если Вы используете многопоточность, которая один является нетривиальным действием.
[ Видят также этот вопрос ]
, я изменил ответ Marc, чтобы использовать фактические случайные числа и на самом деле сделать ту же работу во всех случаях.
Результаты:
for foreach Array : 1575ms 1575ms (+0%) List : 1630ms 2627ms (+61%) (+3%) (+67%) (Checksum: -1000038876)
Скомпилированный как Выпуск под VS 2008 SP1. Работая, не отлаживая на Q6600@2.40GHz.NET 3,5 SP1.
Код:
class Program
{
static void Main(string[] args)
{
List<int> list = new List<int>(6000000);
Random rand = new Random(1);
for (int i = 0; i < 6000000; i++)
{
list.Add(rand.Next());
}
int[] arr = list.ToArray();
int chk = 0;
Stopwatch watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
int len = list.Count;
for (int i = 0; i < len; i++)
{
chk += list[i];
}
}
watch.Stop();
Console.WriteLine("List/for: {0}ms ({1})", watch.ElapsedMilliseconds, chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
int len = arr.Length;
for (int i = 0; i < len; i++)
{
chk += arr[i];
}
}
watch.Stop();
Console.WriteLine("Array/for: {0}ms ({1})", watch.ElapsedMilliseconds, chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
foreach (int i in list)
{
chk += i;
}
}
watch.Stop();
Console.WriteLine("List/foreach: {0}ms ({1})", watch.ElapsedMilliseconds, chk);
chk = 0;
watch = Stopwatch.StartNew();
for (int rpt = 0; rpt < 100; rpt++)
{
foreach (int i in arr)
{
chk += i;
}
}
watch.Stop();
Console.WriteLine("Array/foreach: {0}ms ({1})", watch.ElapsedMilliseconds, chk);
Console.WriteLine();
Console.ReadLine();
}
}
если Вы просто вытаскиваете единственное значение из любого (не в цикле) тогда, оба делают проверку границ (Вы находитесь в управляемом коде, помнят), это - просто список, делает это дважды. См. примечания позже для того, почему это вероятно не грандиозное предприятие.
, Если Вы используете свое собственное для (международный интервал i = 0; я < x. [Длина/Количество]; я ++), тогда основное отличие следующие:
при использовании foreach тогда, основное отличие следующие:
проверка границ часто не является никаким грандиозным предприятием (особенно, если Вы находитесь на CPU с глубоким конвейером и предсказанием ветвлений - норма для больше всего в эти дни), но только Ваше собственное профилирование может сказать Вам, если это - проблема. Если Вы находитесь в частях Вашего кода, где Вы избегаете выделений "кучи" (хорошими примерами являются библиотеки или в реализациях хэш-кода), тогда обеспечение переменной вводится как Список не, IList избежит той ловушки. Как всегда профиль, если это имеет значение.
Я думаю, что производительность будет весьма схожа. Издержки, которые включены при использовании Списка по сравнению с Массивом, по моему скромному мнению, когда Вы добавляете объекты к списку, и когда список должен увеличить размер массива, который это использует внутренне, когда способность массива достигнута.
предположим у Вас есть Список со Способностью 10, тогда Список увеличится, это - способность, как только Вы хотите добавить 11-й элемент. Можно уменьшить влияние производительности путем инициализации Способности списка к количеству объектов, которые это будет содержать.
, Но, чтобы выяснить, выполняет ли итерация по Списку с такой скоростью, как итерации по массиву, почему Вы не сравниваете ее?
int numberOfElements = 6000000;
List<int> theList = new List<int> (numberOfElements);
int[] theArray = new int[numberOfElements];
for( int i = 0; i < numberOfElements; i++ )
{
theList.Add (i);
theArray[i] = i;
}
Stopwatch chrono = new Stopwatch ();
chrono.Start ();
int j;
for( int i = 0; i < numberOfElements; i++ )
{
j = theList[i];
}
chrono.Stop ();
Console.WriteLine (String.Format("iterating the List took {0} msec", chrono.ElapsedMilliseconds));
chrono.Reset();
chrono.Start();
for( int i = 0; i < numberOfElements; i++ )
{
j = theArray[i];
}
chrono.Stop ();
Console.WriteLine (String.Format("iterating the array took {0} msec", chrono.ElapsedMilliseconds));
Console.ReadLine();
В моей системе; итерация по массиву заняла 33 мс; итерация по списку заняла 66 мс.
Честно говоря, я не ожидал, что изменение будет так очень. Так, я поместил свое повторение в цикл: теперь, я выполняю оба повторения 1000 раз. Результаты:
итерация Списка заняла 67 146 мс, выполняя итерации массива, взял 40 821 msec
Теперь, изменение больше не является настолько большим, но все еще...
Поэтому я запустил Отражатель.NET и метода get индексатора класса Списка, похож на это:
public T get_Item(int index)
{
if (index >= this._size)
{
ThrowHelper.ThrowArgumentOutOfRangeException();
}
return this._items[index];
}
, Как Вы видите при использовании индексатора Списка Список выполняет проверку, не выходите ли Вы из границ внутреннего массива. Эта дополнительная проверка идет со стоимостью.
Действительно при выполнении некоторых сложных вычислений в цикле тогда производительность индексатора массива по сравнению с индексатором списка может быть столь незначительно маленькой, что в конечном счете, это не имеет значения.