Оптимизация кода python без ссылки на переменную, которая ссылается на другую переменную и т. Д. - PullRequest
0 голосов
/ 19 февраля 2020

У меня есть вопрос оптимизации, когда я ссылаюсь на переменную, которая затем ссылается на переменную и т. Д. Каждый раз, когда я упоминаю последнюю переменную, которая содержит предыдущую переменную, весь код выполняется снова?

Например, мой код:

a = 5
b = 6
c = b * 2
d = a + c
e = c + d
f = e + d + c
g = f
h = g

А теперь в моем коде я говорю print(h), нужно ли все заново вычислять или python содержит все значения в памяти, когда я ссылаюсь на них? Я сталкивался с этим, когда работаю с SQL и pandas в python, когда я подключаюсь к базе данных, беру то, что мне нужно, преобразую данные, затем загружаю их в фрейм данных, создаю 3 новых фрейма данных кроме оригинального и упомянув об одном из этих трех фреймов данных, который имеет 1,000,000 строк и 50 столбцов, хранит ли python все эти миллионы записей в памяти?

Спасибо за ваши предложения, я предполагаю, что где-то есть хорошая статья, объясняющая это, но я не могу точно найти то, что ищу.

1 Ответ

1 голос
/ 19 февраля 2020

Ну, вы должны предложить исправленную версию вашей проблемы, чтобы построить минимальный пример. Здесь ваш код близок к минимальному, но, к сожалению, не связан с описанной проблемой.

Что касается памяти, это объекты, а не переменные. В Python переменная не больше, чем имя, которое ссылается на базовый объект. Просто объект завершает свое время жизни и может собирать мусор для освобождения памяти, как только он становится недоступным, т. Е. Как только никакая переменная не может получить к нему прямой или косвенный доступ.

Примеры:

a = "foo and bar"  # ok a addresses the string
b = a              # b addresses the same string (one single copy)
a += "s"           # oops...

Строка не является изменяемым типом. Последняя строка затем создает новую строку (с адресом a), в то время как b все еще обращается к старой. После b = None старая строка больше не будет доступна и будет собирать мусор.

a = [1, 2, 3, 4]   # ok a point to the list
b = a              # b addresses the same list
a.append(5)        # oops...

Список является изменяемым типом. a.append(5) изменяет объект, и a и b теперь обращаются к списку [1, 2, 3, 4, 5]. Просто используйте print(a,b), чтобы увидеть это ...


Теперь для вашего точного вопроса:

pandas лежащие в основе контейнеры - это массив numpy, который находится в памяти. Если в данный момент вы можете получить доступ к 3 отдельным фреймам данных, они будут присутствовать в памяти. Но ... pandas высоко оптимизирован. Это означает, что если вы используете субкадры данных и, в зависимости от подробностей, вы получите либо простую копию (дублирование в памяти), которую вы сможете изменить независимо от исходного кадра данных, либо представление (то же самое используемое количество памяти).

Давайте рассмотрим несколько pandas примеров:

Скажем, df - это кадр данных из 1 000 000 строк, содержащий только цифры c. Все эти строки загружаются в память.

После:

for i in range(2, 11):
    dg = df * i
    ...          # process dg

Для каждого шага вы создаете новую копию кадра данных, но она будет уничтожена на следующем шаге. Короче говоря, вы будете использовать в два раза больше памяти начального кадра данных

dfs = [df * i for i in range(2, 11)]
for dg in dfs:
    ...         # process dg

Здесь вы создадите 9 новых кадров данных, которые будут доступны через dfs, так что вы получите 10 отдельных кадров данных и вам потребуется в 10 раз больше начальной памяти.

...