2013-03-08 3 views
3

В documentation я нашелкак определить постоянную функцию

Функция Int(), которая всегда возвращает нуль, является просто частным случаем постоянных функций. Более быстрый и гибкий способ создания постоянных функций является использование itertools.repeat(), который может поставить любую постоянную значение (а не только ноль):

def constant_factory(value): 
    return itertools.repeat(value).next 

d = defaultdict(constant_factory('<missing>')) 
d.update(name='John', action='ran') 
'%(name)s %(action)s to %(object)s' % d 

'John ran to <missing>' 

Почему просто не использовать функцию лямбда получить постоянную функцию?

+0

В документации [https://docs.python.org/3.5/library/collections.html#defaultdict-examples) для python 3.5 используется 'lambda'. – Alexey

ответ

3

Класс itertools.repeat написан на C, и он немного быстрее, чем использование функции, написанной на Python. Вот некоторые испытания я сделал с различными реализациями постоянных функций значения, используя модуль timeit:

Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) 
[MSC v.1600 64 bit (AMD64)] on win32 
Type "copyright", "credits" or "license()" for more information. 
>>> import timeit 
>>> import itertools 
>>> itertools_version = itertools.repeat(10).__next__ 
>>> lambda_version = lambda:10 
>>> def function_version(): 
    return 10 
>>> def constant_factory(n): 
    return itertools.repeat(n).__next__ 
>>> factory_version = constant_factory(10) 
>>> timeit.timeit("for i in range(100): f()", 
        setup="from __main__ import itertools_version as f") 
7.115707915662512 
>>> timeit.timeit("for i in range(100): f()", 
        setup="from __main__ import lambda_version as f") 
11.479014911317307 
>>> timeit.timeit("for i in range(100): f()", 
        setup="from __main__ import function_version as f") 
11.561433023257619 
>>> timeit.timeit("for i in range(100): f()", 
        setup="from __main__ import factory_version as f") 
7.166709032038568 

Однако, подумай, если это скромное увеличение производительности стоит для вашей ситуации. Если это не критический код производительности, вы должны использовать любую реализацию, которую, по вашему мнению, легче всего понять, когда вы ее прочтете позже.

Если вы собираетесь использовать постоянную функцию один раз, я думаю, что лямбда будет вполне уместна. Если это то, что вы часто будете использовать, возможно, названная функция лучше. Если он вызывается во внутреннем цикле некоторой из наиболее чувствительной к времени логики, то вы используете связанный метод объекта itertools.repeat.

+0

@ manu-fatto: Я не уверен, что понимаю. Функция 'constant_factory' вызывается только один раз, так же как мой код вызывает только' itertools.repeat (10) 'once. Он возвращает функцию, которая вызывается снова и снова (которая должна возвращать одно и то же значение). Я добавлю для этого время, но это по сути то же самое, что и версия itertools, просто с дополнительным вызовом функции в установочном коде. – Blckknght

+0

Конечно, вы правы ... –

Смежные вопросы