Комбинация безточечных функций в Python

У меня есть некоторые предикаты, например:

is_divisible_by_13 = lambda i: i % 13 == 0
is_palindrome = lambda x: str(x) == str(x)[::-1]

и хотите логически объединить их, как в:

filter(lambda x: is_divisible_by_13(x) and is_palindrome(x), range(1000,10000))

Теперь возникает вопрос: может ли такая комбинация быть записана в безточечном стиле, например:

filter(is_divisible_by_13 and is_palindrome, range(1000,10000))

Это, конечно, не дает желаемого эффекта, потому что значение истинности лямбда-функций равно True , а и и или являются операторами замыкания. Ближайшее, что я придумал, - это определить класс P , который представляет собой простой контейнер предикатов, который реализует __ call __ () и имеет методы и _ () и или _ () для объединения предикатов. Определение из P выглядит следующим образом:

import copy

class P(object):
    def __init__(self, predicate):
        self.pred = predicate

    def __call__(self, obj):
        return self.pred(obj)

    def __copy_pred(self):
        return copy.copy(self.pred)

    def and_(self, predicate):
        pred = self.__copy_pred()
        self.pred = lambda x: pred(x) and predicate(x)
        return self

    def or_(self, predicate):
        pred = self.__copy_pred()
        self.pred = lambda x: pred(x) or predicate(x)
        return self

С помощью P я теперь могу создать новый предикат, который представляет собой комбинацию таких предикатов:

P(is_divisible_by_13).and_(is_palindrome)

, который эквивалентен приведенной выше лямбда-функции . Это ближе к тому, что я бы сказал ke, но он также не является бессмысленным (теперь точки являются самими предикатами, а не их аргументами).Теперь второй вопрос: есть ли лучший или более короткий способ (может быть, без скобок и точек) для объединения предикатов в Python, чем использование классов вроде P и без использования (лямбда) функций?

9
задан Marcin 20 July 2013 в 16:56
поделиться