def safe_filter(x):
            if x is None:
                return ''
            else
                return x
        row = map(safe_filter, row)
Можно ли это записать в одну строку? (python 2.4)
Уже подсказали в #pythonua )
row = [{None: ''}.get(x, x) for x in row]
Мне стало интересно как поставленную задачу реализовать в моей стилистике.
Всё оказалось просто: map(lambda x: (x is not None and x) or "", row). Хотя, согласен, менее красиво.
Решил проверить на скорость и обнаружил...

Python 2.5.2 (r252:60911, Mar 13 2008, 07:28:35)
on linux2
>>> List = range(1000) + [None]*100
>>> import random
>>> random.shuffle(List)
>>> import timeit
>>> timeit.Timer('map(lambda x: (x is not None and x) or "", List)', 'from __main__ import List').timeit(10000)
11.695267200469971
>>> timeit.Timer('[{None: ""}.get(x, x) for x in List]', 'from __main__ import List').timeit(10000)
21.314514017105103
>>>
Python 2.4.3 (#1, Nov 24 2006, 14:55:15)
on linux2
>>> timeit.Timer('map(lambda x: (x is not None and x) or "", List)', 'from __main__ import List').timeit(10000)
14.910423994064331
>>> timeit.Timer('[{None: ""}.get(x, x) for x in List]', 'from __main__ import List').timeit(10000)
24.059360027313232
Результаты перепроверил неоднократно.
У меня PIII - 1000MHz, шина памяти 133MHz. Средняя заточка всея софта ('-O2').
...так кто ж ты, наконец?
-- Я -- часть той силы, что вечно хочет зла
и вечно совершает благо.
Извините что лезу...

Но тут бесспорно lambda лучше, ибо это функция, а не объект с вызовом его же метода... { } => объект и все его методы....

Мысли в слух Ж)

P.S. функция поди тоже объект... только с меньшим количеством методов


dir({})

Last edited April 4, 2008, 8:28 p.m.

ZZZ
Мне стало интересно как поставленную задачу реализовать в моей стилистике.
Всё оказалось просто: map(lambda x: (x is not None and x) or "", row).
Твой вариант работает не корректно.
Он вместо нуля тоже ставит '', и вместо False.
Если же ты эту часть сделаешь через get тоже - то она будет работать медленнее чем на списковых включениях. (IMHO)

Last edited April 4, 2008, 9:57 p.m.

SHIZA
Твой вариант работает не корректно.
Он вместо нуля тоже ставит '', и вместо False.
Если же ты эту часть сделаешь через get тоже - то она будет работать медленнее чем на списковых включениях. (IMHO)
Ты прав, но для строк пойдёт.
Но почему именно get? Стоит немножко напрячь мозги и... TADAAA!!!
>>> map(lambda x: x or ((x is not None or '') and x), [0.0, 0, 1, 2, 3, None, 4, False, (), []])
[0.0, 0, 1, 2, 3, '', 4, False, (), []]
Так лучше?
Не поленился даже протестить. Так, для приличия...

Python 2.5.2 (r252:60911, Mar 13 2008, 07:28:35)
on linux2
>>> List = range(1000) + [None]*100
>>> import random
>>> random.shuffle(List)
>>> import timeit
>>> timeit.Timer('map(lambda x: x or ((x is not None or "") and x), List)', 'from __main__ import List').timeit(10000)
9.3463799953460693
>>> timeit.Timer('map(lambda x: x or ((x is not None or "") and x), List)', 'from __main__ import List').timeit(10000)
9.2854440212249756
>>> timeit.Timer('map(lambda x: x or ((x is not None or "") and x), List)', 'from __main__ import List').timeit(10000)
9.2770500183105469
Мне кажется, что это того стоит.

P.S. Тем кто читал этот пост до правки (между часом и двумя тридцати ночи) большое сорри. Затупил. Спать больше надо... а пить меньше...

Last edited April 5, 2008, 5:29 a.m.

...так кто ж ты, наконец?
-- Я -- часть той силы, что вечно хочет зла
и вечно совершает благо.
я предпочту тормозной, но более читаемый вариант )
lorien
я предпочту тормозной, но более читаемый вариант )
В большенстве случаев я тоже, но вот столкнувшись с подобной промлемой на сервере, я выберу скорость. Да и от размера списка зависит -- десять секунд или двадцать... В два раза как-никак...

P.S. Ещё раз сорри за глючный пост...
...так кто ж ты, наконец?
-- Я -- часть той силы, что вечно хочет зла
и вечно совершает благо.
ну чтож, тогда предлагаю такой вариант:

Меряем скорость:
import random
import timeit

row = range(1000) + [None]*100
random.shuffle(row)

#[{None: ''}.get(x, x) for x in row]
print timeit.Timer("[{None: ''}.get(x, x) for x in row]", 'from __main__ import row').timeit(10000)

#map(lambda x: x or ((x is not None or '') and x), row)
print timeit.Timer("map(lambda x: x or ((x is not None or '') and x), row)", 'from __main__ import row').timeit(10000)

#[x or ((x is not None or '') and x) for x in row]
print timeit.Timer("[x or ((x is not None or '') and x) for x in row]", 'from __main__ import row').timeit(10000)
6.94056367499
4.07628818747
1.47561380008

Разница почти в 3 раза =)

Last edited April 5, 2008, 2:59 p.m.

SHIZA
Разница почти в 3 раза =)
>>> timeit.Timer('[x or ((x is not None or "") and x) for x in List]', 'from __main__ import List').timeit(10000)
4.5568611621856689
Ты жжёшь! Ну прямо Мичурин какой-то... :-)


Пока был в оффлайне, надумал такую штуку. Я поставил тебе вопрос: почему первый вариант такой тормозной? А ведь всё как всегда элементарно! Для кажной обработки у нас создаётся новый словарь. При том, чем больше этот словарь, тем больше тормоз:
>>> timeit.Timer('[{None: ""}.get(x, x) for x in List]', 'from __main__ import List').timeit(10000)
21.343222856521606
>>> timeit.Timer('[{None: "", 1:2}.get(x, x) for x in List]', 'from __main__ import List').timeit(10000)
26.878964185714722
>>> timeit.Timer('[{None: "", 1:2, 2:3}.get(x, x) for x in List]', 'from __main__ import List').timeit(10000)
31.339015960693359
Если же создать этот словарь заранее, то по скорости оно почти сравняется с моим вариантом.
>>> __ = {None: ''}; timeit.Timer('[__.get(x, x) for x in List]', 'from __main__ import List, __').timeit(10000)
12.067402124404907
>>> __ = {None: ''}; timeit.Timer('[__.get(x, x) for x in List]', 'from __main__ import List, __').timeit(10000)
12.022394895553589
>>> __ = {None: '', 1:2, 2:3}; timeit.Timer('[__.get(x, x) for x in List]', 'from __main__ import List, __').timeit(10000)
12.213709115982056
>>> __ = {None: '', 1:2, 2:3}; timeit.Timer('[__.get(x, x) for x in List]', 'from __main__ import List, __').timeit(10000)
12.240325212478638
До SHIZA, конечно, далеко, но зато гораздо более функционально.
Я думаю, что это, довольно действенный метод, для создания списка из любого iterable, с заменой значений.

P.S. Думаю, что тема исчерпана...
...так кто ж ты, наконец?
-- Я -- часть той силы, что вечно хочет зла
и вечно совершает благо.