gpt4 book ai didi

python - Python 中的 Pointfree 函数组合

转载 作者:太空狗 更新时间:2023-10-29 20:44:13 30 4
gpt4 key购买 nike

我有一些谓词,例如:

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))

现在的问题是:这样的组合能不能写成pointfree样式,例如:

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

这当然没有达到预期的效果,因为 lambda 函数的真值是 Trueandor 是短路运算符.我想到的最接近的事情是定义一个类 P,它是一个简单的谓词容器,它实现了 __call__() 并具有方法 and_()or_() 来组合谓词。 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)

相当于上面的 lambda 函数。这更接近我想要的,但它也不是无点的(点现在是谓词本身而不是它们的参数)。现在第二个问题是:在 Python 中组合谓词是否有比使用 P 类而不使用 (lambda) 函数更好或更短的方法(可能没有括号和点)?

最佳答案

您可以通过向 P 类添加 __and__ 方法来覆盖 Python 中的 &(按位与)运算符。然后你可以这样写:

P(is_divisible_by_13) & P(is_palindrome)

甚至

P(is_divisible_by_13) & is_palindrome

同样,您可以通过添加 __or__ 方法和 ~(按位求反)运算符来覆盖 |(按位或)运算符添加一个 __not__ 方法。请注意,您不能覆盖内置的 andornot 运算符,因此这可能尽可能接近您的目标。您仍然需要一个 P 实例作为最左边的参数。

为了完整性,您还可以覆盖就地变体(__iand____ior__)和右侧变体(__rand__ >, __ror__) 这些运算符。

代码示例(未经测试,请随时更正):

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):
def func(obj):
return self.pred(obj) and predicate(obj)
return P(func)

def __or__(self, predicate):
def func(obj):
return self.pred(obj) or predicate(obj)
return P(func)

让您更接近无点必杀技的另一个技巧是以下装饰器:

from functools import update_wrapper

def predicate(func):
"""Decorator that constructs a predicate (``P``) instance from
the given function."""
result = P(func)
update_wrapper(result, func)
return result

然后您可以使用 predicate 装饰器标记您的谓词,使它们自动成为 P 的实例:

@predicate
def is_divisible_by_13(number):
return number % 13 == 0

@predicate
def is_palindrome(number):
return str(number) == str(number)[::-1]

>>> pred = (is_divisible_by_13 & is_palindrome)
>>> print [x for x in xrange(1, 1000) if pred(x)]
[494, 585, 676, 767, 858, 949]

关于python - Python 中的 Pointfree 函数组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9184632/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com