Адрес столбца:Один модуль Python в неделю
В то же время, вы также можете обратить внимание на мой публичный аккаунт WeChat.AlwaysBeta, вас ждет еще больше захватывающего контента.
functools — очень простой, но важный модуль в Python, в основном некоторые функции, относящиеся к функциям Python более высокого порядка. Содержимого этого модуля не так много, см.официальная документациятакже знать.
Когда дело доходит до функций высшего порядка, это очень важная концепция в парадигме функционального программирования.Проще говоря, это функция, которая может принимать функции в качестве параметров или возвращать функции в качестве возвращаемых значений.Поскольку функции в Python являются классом объектов , очень легко поддерживать такие функциональные возможности.
Функции в модуле functools имеют толькоcmp_to_key
,partial
,reduce
,total_ordering
,update_wrapper
,wraps
,lru_cache
Эти:
назначен на границуreduce
этоfunctools.reduce
во встроенной библиотеке Python 2reduce
, это появляется здесь из-за диктатуры Гвидо, ему не нравится концепция «уменьшения карты» в функциональном программировании, поэтому он намереваетсяmap
иreduce
Две функции были вынесены из встроенной библиотеки и, наконец, перемещены вmap
Функция остается во встроенной библиотеке, но встроенная в Python 3map
Функция возвращает объект итератора, и Python 2 охотно сгенерирует список, поэтому будьте осторожны при его использовании.
Функция этой функции состоит в том, чтобы свести последовательность к выходу, и ее прототип выглядит следующим образом:
reduce(function, sequence, startValue)
Пример использования:
>>> def foo(x, y):
... return x + y
...
>>> l = range(1, 10)
>>> reduce(foo, l)
45
>>> reduce(foo, l, 10)
55
частичная функцияpartial
иpartialmethod
Используется для создания частичной функции, которая оборачивает вызываемый объект с некоторыми параметрами по умолчанию. Возвращаемый результат является вызываемым объектом и может обрабатываться как исходный объект, что упрощает вызовы функций.
Простой пример использования:
from functools import partial
def add(x, y):
return x + y
add_y = partial(add, 3) # add_y 是一个新的函数
add_y(4) # 7
Очень практичный пример:
def json_serial_fallback(obj):
"""
JSON serializer for objects not serializable by default json code
"""
if isinstance(obj, (datetime.datetime, datetime.date)):
return str(obj)
if isinstance(obj, bytes):
return obj.decode("utf-8")
raise TypeError ("%s is not JSON serializable" % obj)
json_dumps = partial(json.dumps, default=json_serial_fallback)
допустимыйjson_serial_fallback
Добавьте тест типа в функцию, чтобы указать, как json сериализовать объект Python.
partialmethod
Это декоратор, недавно представленный в Python 3.4, и его функции в основном аналогичныpartial
, но только для методов. Это легко понять на примере:
class Cell(object):
def __init__(self):
self._alive = False
@property
def alive(self):
return self._alive
def set_state(self, state):
self._alive = bool(state)
set_alive = partialmethod(set_state, True)
set_dead = partialmethod(set_state, False)
c = Cell()
c.alive # False
c.set_alive()
c.alive # True
Использование частичного метода в Python 2 можно определить следующим образом:
# Code from https://gist.github.com/carymrobbins/8940382
from functools import partial
class partialmethod(partial):
def __get__(self, instance, owner):
if instance is None:
return self
return partial(self.func, instance,
*(self.args or ()), **(self.keywords or {}))
Связанные с декоратором
Когда дело доходит до «принятия функции в качестве параметра и функции в качестве возвращаемого значения», в Python чаще всего используется декоратор. Связанные с декоратором функции в библиотеке functools:update_wrapper
,wraps
, также сWRAPPER_ASSIGNMENTS
иWRAPPER_UPDATES
Использование двух констант позволяет устранить некоторые негативные эффекты декораторов Python.
wraps
пример:
def decorator(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@decorator
def add(x, y):
return x + y
add # <function __main__.wrapper>
Вы можете увидеть имя оформленной функции, которая является__name__
собственность становитсяwrapper
, это побочный эффект декоратора, на самом делеadd
Функция становитсяdecorator(add)
,иwraps
Декораторы могут устранить эти побочные эффекты:
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@decorator
def add(x, y):
return x + y
add # <function __main__.add>
Исправленные свойства определены вWRAPPER_ASSIGNMENTS
середина:
>>> functools.WRAPPER_ASSIGNMENTS
('__module__', '__name__', '__doc__')
>>> functools.WRAPPER_UPDATES
('__dict__',)
update_wrapper
update_wrapper
роль иwraps
Аналогично, но мощнее, другими словами,wraps
Фактическиupdate_wrapper
специализация на самом делеwraps(wrapped)
эквивалентноpartial(update_wrapper, wrapped=wrapped, **kwargs)
.
Таким образом, приведенный выше код можно использовать сupdate_wrapper
Перепишите следующим образом:
def decorator(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return update_wrapper(wrapper, func)
для сравненияcmp_to_key
иtotal_ordering
cmp_to_key
существуетlist.sort
и встроенные функцииsorted
Существует ключевой параметр, который используется для указания того, какое значение элемента сравнивать, например, сравнение по длине строкового элемента:
>>> x = ['hello','abc','iplaypython.com']
>>> x.sort(key=len)
>>> x
['abc', 'hello', 'iplaypython.com']
То есть при сортировке функция, указанная ключом, будет сначала вызываться для каждого элемента, а затем сортироваться. в то же время,sorted
иlist.sort
Также был предоставлен параметр cmp, чтобы указать, как сравнивать два элемента, но в Python 3 этот параметр был удален.
cmp_to_key
— это функция, добавленная в Python 2.7 для преобразования функций сравнения в ключевые функции, чтобы их можно было использовать в функциях, которые принимают ключевую функцию в качестве аргумента. Напримерsorted()
,min()
,max()
,heapq.nlargest()
,itertools.groupby()
Ждать.
sorted(range(5), key=cmp_to_key(lambda x, y: y-x)) # [4, 3, 2, 1, 0]
total_ordering
total_ordering
Это также новая функция в Python 2.7, упрощающая написание функций сравнения. если вы определили__eq__
метод и__lt__
,__le__
,__gt__
или__ge__()
Один из них, другие методы сравнения могут быть сгенерированы автоматически. Официальный пример:
@total_ordering
class Student:
def __eq__(self, other):
return ((self.lastname.lower(), self.firstname.lower()) ==
(other.lastname.lower(), other.firstname.lower()))
def __lt__(self, other):
return ((self.lastname.lower(), self.firstname.lower()) <
(other.lastname.lower(), other.firstname.lower()))
dir(Student) # ['__doc__', '__eq__', '__ge__', '__gt__', '__le__', '__lt__', '__module__']
Посмотрите на другой пример:
from functools import total_ordering
@total_ordering
class Student:
def __init__(self, firstname, lastname):
self.firstname = firstname
self.lastname = lastname
def __eq__(self, other):
return ((self.lastname.lower(), self.firstname.lower()) ==
(other.lastname.lower(), other.firstname.lower()))
def __lt__(self, other):
return ((self.lastname.lower(), self.firstname.lower()) <
(other.lastname.lower(), other.firstname.lower()))
print dir(Student)
stu = Student("Huoty", "Kong")
stu2 = Student("Huoty", "Kong")
stu3 = Student("Qing", "Lu")
print stu == stu2
print stu > stu3
Выходной результат:
['__doc__', '__eq__', '__ge__', '__gt__', '__init__', '__le__', '__lt__', '__module__']
True
False
для кэшированияlru_cache
Этот декоратор недавно добавлен в Python 3. В Python 2, если вы хотите его использовать, вы можете установить стороннюю библиотеку.functools32
. Этот декоратор используется для кэширования результата вызова функции.Для функции, которую необходимо вызывать несколько раз и параметры которой одинаковы для каждого вызова, декоратор можно использовать для кэширования результата вызова, тем самым ускоряя выполнение программа. Пример:
from functools import lru_cache
@lru_cache(None)
def add(x, y):
print("calculating: %s + %s" % (x, y))
return x + y
print(add(1, 2))
print(add(1, 2)) # 直接返回缓存信息
print(add(2, 3))
Выходной результат:
calculating: 1 + 2
3
3
calculating: 2 + 3
5
Поскольку этот декоратор будет кэшировать различные результаты вызовов в памяти, вам нужно обратить внимание на проблему использования памяти, чтобы не занимать слишком много памяти, что повлияет на производительность системы.
Связанные документы:
blog.wind runner.what/Python/func…