Модуль Python в неделю | functools

Python GitHub Язык программирования функциональное программирование

Адрес столбца:Один модуль 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…

Карнавальная ночь.GitHub.IO/2016/10/26/…

pymotw.com/3/