Comments 18
Эффективные и не эффективные методы кодинга на Python
Перевод — уровень Бог. Простите, речь шла действительно про эффективные методики кодинга (т.е. как писать больше кода за единицу времени)? Или скорее про вкус? Оригинал не читал, но предполагаю, что имелись в виду "Практики написания хорошего или плохого кода на Python" или "Хорошие или неудачные шаблоны кода на Python" (т.е. речь именно про "хороший качественный" и "дурно пахнущий, не очевидный, тяжелый в поддерживании" код)
В примере с параметрами по умолчанию можно ещё короче написать:
def f(value, seq=None):
seq = seq or []
...
Короче, но неверно:
def f(value, seq=None):
seq = seq or []
seq.append(value)
return seq
x = []
f(1, x)
print(x) # []
Мне казалось, что в примере в статье как раз хотели избавиться от лишнего побочного эффекта. Если использовать возвращаемое значение, то всё Ок.
А если не использовать? В любом случае, эти 2 функции неэквивалентны, а Ваша реализация к тому же имеет очень неочевидный побочный эффект. Не надо так делать, экономия одной строчки этого не стоит.
def f(value, seq=[]):
return [*seq, value]
Ну или со старым питоном
def f(value, seq=[]):
return seq+[value]
>>> def f(value, seq=None):
... if not seq:
... seq = []
... seq.append(value)
... return seq
>>> a = [1, 2]
>>> f(3, a)
[1, 2, 3]
>>> a
[1, 2, 3]
В вашем варианте список остается без изменения
>>> def f(value, seq=[]):
... return [*seq, value]
>>> a = [1, 2]
>>> f(3, a)
[1, 2, 3]
>>> a
[1, 2]
Но «перевернуть» последовательность – более компактный способ:
for item in x[::-1]:
Подскажите, pls, кто знает потроха питона. А что кроется внутри взятия инверсии массива?
Порождается в памяти новый массив который заполняется из x? И ли это как то очень умно понимается интерпретатором и лишней (относительно классического прохода по индексу в массиве) работы не делается?
Если порождается в памяти массив и выполняется работа по его инверсии, то совет использовать такую запись для таких целей очень вредный.
Питон и так не быстр..
Впрочем сам не поленился проверить…
Вредный совет.
Экономия на написании кода (сомнительная) и бессмысленный для данной задачи расход памяти и ресурсов.
Порождается еще один массив в памяти.
import tracemalloc
def display(info, snapshot, key_type='lineno', limit=3):
snapshot = snapshot.filter_traces((
tracemalloc.Filter(False, "<frozen importlib._bootstrap>"),
tracemalloc.Filter(False, "<unknown>"),
))
top_stats = snapshot.statistics(key_type)
total = sum(stat.size for stat in top_stats)
print(info+": size: %.1f KiB" % (total / 1024))
def test():
display("1", tracemalloc.take_snapshot())
x = [1] * (10 ** 6)
sum = 0
display("2",tracemalloc.take_snapshot())
test = True
for item in x[::-1]:
if test:
display("3",tracemalloc.take_snapshot())
test = False
sum += item
display("4",tracemalloc.take_snapshot())
del x
display("5",tracemalloc.take_snapshot())
if __name__ == '__main__':
tracemalloc.start()
test()
1: size: 0.0 KiB
2: size: 3910.8 KiB
3: size: 7830.2 KiB
4: size: 3926.5 KiB
5: size: 22.6 KiB
Да, конечно, x[::-1]
возвращает новый массив, отсортированный в обратном порядке, применять его только для итерации не стоит, для этого есть reversed()
:
# x[::-1]:
1: size: 0.0 KiB
2: size: 7818.2 KiB
3: size: 15647.6 KiB
4: size: 7842.5 KiB
5: size: 34.3 KiB
# reversed(x):
1: size: 0.0 KiB
2: size: 7818.2 KiB
3: size: 7835.1 KiB
4: size: 7842.5 KiB
5: size: 34.3 KiB
Эффективные и не эффективные методы кодинга на Python