Skip to main content

Python中的内涵集

项目描述

Python 的内涵(规则定义)集。

概述

定义集合有两种方式:内涵和外延。像set([1,3,5,'daisy'])这样的扩展集显式地枚举了集合的每个成员。

相反,内涵集是由规则定义的。例如“所有素数的集合”或“以'a'开头并以't'结尾的每个单词。内涵集通常是无限的。可能可以生成他们的成员列表,但这并不像“把你所有的东西都给我!”那么简单。 for循环。

一旦你知道你在寻找什么,内涵集无处不在。Python 并不直接表示它们,但正则表达式、许多列表推导以及各种测试和过滤操作都是内涵集概念的真正面孔。许多功能测试某物是否“合格”。例如os.path.isdir(d)测试d是否在合法目录集合中,isinstance(s, str)测试s是否是str对象集合的成员。即使是有条件的核心可以被解释为测试一个内涵集的成员资格——所有通过测试的项目的集合。

许多这样的测试都有时间方面的问题——它们确定一个值是否现在是一个成员。如果情况发生变化,答案可能会在未来发生变化。其他测试随着时间的推移是不变的。%%734永远不会是一个有效的 Python 标识符,无论它被测试多少次——除非整个 Python 世界的规则发生变化,也就是说。

内涵集是所有编程的一部分,即使它们没有明确表示或以该名称调用。``内涵``帮助 Python 程序直接表示内涵集。

用法

intensional定义了几个集合IntensionalSet子类,例如AnyEveryButNotEitherOr。这些大致对应于集合操作并集、交集、差集和对称差集(又名异或)。其中,Any是最有用的:

from intensional import *

name = 'Stephen'
if name in Any('Steve', 'Steven', 'Stephen'):
    print 'Good name!'

到目前为止,这里没有什么是您无法使用标准 Python数据类型完成的。所以让我们扩大到更通用的内涵集:

if name in Test("x.startswith('S')"):
    print "Your name starts with S!"

测试在其构造函数中采用 lambda 表达式或字符串。如果它是一个字符串,Test假定有趣的变量名称是x并使用自动提供的 lambda x:前缀编译字符串表达式。这使代码更简洁明了。现在这些集合开始变得更有趣了。:

starts_with_S =  Test("x.startswith('S')")
ends_with_n   =  Test("x.endswith('n')")

if name in Every(starts_with_S, ends_with_n):
    ...  # Stephen and Steven pass, but Steve does not

当然,这也可以呈现为:

if name in Test("x.startswith('S') and x.endswith('n')"):
    ...  # Stephen and Steven pass, but Steve does not

甚至:

S_something_n = starts_with_S & ends_with_n
if name in S_something_n:
    ...

类型会员

if x in Instances(int):
    ...

等同于:

if isinstance(x, int):
   ...

对于单数结构在语言上更自然的情况,Instances存在别名IsInstance 。第二个别名类型也可用。

设置操作

intensional支持 Python 的一些经典集合操作,但不是全部。有两个主要规则:

  • IntensionalSet尝试支持所有的collections.Set方法,例如 union()intersection()。但是IntensionalSet对象是不可变的,因此它们不支持像add()pop()|=collections.MutableSet定义的自变异操作。

  • 因为它们是由规则而不是明确的成员列表定义的,所以(通常)不可能确定IntensionalSet的基数(即len()),也不能遍历其所有成员,也不能测试相等性。IntensionalSet对象主要用于确定成员资格。

由于实现细节,IntensionalSet类与collections.Set平行,但不是真正的子类。

扩展

定义新的IntensionalSet子类很容易,这些子类以通用的、语言上“干净”的方式定义其他类型的逻辑测试,从而使代码更具可读性。例如,Instances内涵集定义如下:

class Instances(with_metaclass(MementoMetaclass, IntensionalSet)):
    """
    An object is in an IsInstance if it is an instance of the given types.
    """
    def __init__(self, *args):
        self.types = tuple(args)

    def __contains__(self, item):
        return isinstance(item, self.types)

__init__()只记住构造集合的参数,而__contains__()实现测试,回答:给定项目是否属于由这些参数构造的集合?

这里唯一的复杂性是with_metaclass(MementoMetaclass, IntensionalSet)短语,它只是一种兼容机制,可以在 Python 2 或 Python 3 中使用给定的元类定义一个类。

使用MementoMetaclass以便在构造后从缓存中获取集合对象,而不是在后续提及时进行冗余重建。这是一个有用的性能调整。例如,对于正则表达式,它允许Re.__init__()集合构造函数只编译一次正则表达式,即使程序包含许多提及 Re(<some regular exprssion>)。更高的性能是将构造集分配给名称/变量并通过该名称引用它们。这个:

integers = Instances(int)

if x in integers:
    ...

需要的工作量少于:

if x in Instances(int):
    ...

如果要经常执行测试,则首选。但是这个预先命名只是一个调整,而不是一个要求。

笔记

  • 使用pytesttox开始自动化多版本测试 。

  • 现在已成功打包并针对所有最新版本的 Python 进行了测试:2.6、2.7、3.2 和 3.3 加上一个不是很新的 (2.5) 和一个(PyPy 1.9,基于 Python 2.7.2 ) 以不同的方式实现。

  • 内涵只是一个更大的项目的一个方面,它重新思考如何测试项目的成员资格和/或从集合中选择项目。敬请关注!

  • 作者Jonathan EuniceTwitter 上的 @jeunice 欢迎您提出意见和建议。

安装

要安装最新版本:

pip install -U intensional

要在特定 Python 版本(本例中为 3.3)下进行easy_install :

python3.3 -m easy_install --upgrade intensional

(您可能需要在它们前面加上“sudo”来授权安装。如果它们已经安装,--upgrade标志会很有帮助;将它添加到包名称之前。)

项目详情


下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。

源分布

intensional-0.222.zip (21.6 kB 查看哈希)

已上传 source

intensional-0.222.tar.gz (12.2 kB 查看哈希)

已上传 source