- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
因此在 itertools 配方部分,他们有一段代码如下所示:
seen = set()
seen_add = seen.add
我想知道类似的想法是否可以弥合 in
和 __contains__
之间的一些性能差距。例如,使用以下代码:
seen = set()
seen_add = seen.add
in_seen = seen.__contains__
for item in iterable:
in_seen(item)
对比
seen = set()
seen_add = seen.add
in_seen = seen.__contains__ # make identical in beginning
for item in iterable:
item in seen
因此,如果我正确地读取了 dis 的输出,问题就变成了“x in y
是否比 func(x)
快?”
编辑:对于那些说这无关紧要的人,我没有将其用作优化。我试图通过将这个元素分开来更好地理解语言。
最佳答案
我们说的最多是几十纳秒,所以通常这并不重要。而且,即使是这样,事情也比表面上看起来更复杂。
将 seen.__contains__
预绑定(bind)为 seen_contains
会比调用 seen.__contains__
更快,但不如仅使用 (更明显和惯用的)in seen
而不是。
那么,为什么这与 seen_adds
不同?
在 seen.add()
的情况下,您正在显式创建和调用绑定(bind)方法,没有办法解决这个问题。因此,创建绑定(bind)方法一次,而不是每次……通常仍然不值得,但在极少数情况下,当您需要节省纳秒时,这是一个胜利。
在 in seen
的情况下,您并未显式创建绑定(bind)方法,您只是在评估运算符。在 CPython 中,如果 seen
是 Python 类的一个实例,那将隐式创建一个绑定(bind)方法——但如果它是一个内置类的实例,它只会直接查找在 C 插槽中调用方法并调用它。因此,虽然您通过一次创建绑定(bind)方法而不是一遍又一遍地创建绑定(bind)方法来节省时间,但它仍然不如通过绑定(bind)方法调用 C 函数而不是直接调用它所浪费的时间多。
当然,在不同的 Python 实现中——或者只是使用非内置的不同类型——情况可能会有所不同。
如果这真的很重要(通常不会),您当然应该使用您关心的平台、Python 实现和类型对其进行测试。
但是,纯粹作为示例,我将在我的 MacBook Pro 上使用 64 位 python.org CPython 3.7 和 set
对其进行测试:
In [778]: s = {1, 2, 3}
In [779]: sc = s.__contains__
In [780]: %timeit 4 in s
33.9 ns ± 0.444 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [781]: %timeit s.__contains__(4)
69.3 ns ± 0.936 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [782]: %timeit sc(4)
47.6 ns ± 0.866 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
正如预期的那样,sc
挽回了我们浪费的一些时间,但不是全部。
但是使用纯 Python 类型:
In [787]: class Set:
...: def __contains__(self, n):
...: return 1 <= n < 4
In [788]: s = Set()
In [789]: sc = s.__contains__
In [790]: %timeit 4 in s
129 ns ± 5.69 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [791]: %timeit s.__contains__(4)
124 ns ± 1.14 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [792]: %timeit sc(4)
108 ns ± 1.19 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
… 4 in s
比 s.__contains__(4)
稍微慢(因为它基本上只是一个围绕调用的包装器) ,并创建绑定(bind)方法使其更快。
因此,对于表示相同值的两种不同类型,我们得到了完全相反的结果。
同样,这些情况中最大的差异仍然只有 35ns。
作为旁注,预绑定(bind)方法对局部变量的帮助比对全局变量的帮助更大。 (局部变量查找比属性查找快得多;全局变量查找只比属性查找快一点点。)这在单行代码中很难证明,但如果这是您的实际预期用途,您应该自己测试。
请记住,所有这些都只适用于 CPython。
当我在 PyPy 3.5.3/5.10.1 中运行完全相同的代码时,set
得到 6.39/6.29/6.31ns,Set< 得到 1.52/1.51/1.50ns/
.
请注意,几乎所有细节都完全相反:__contains__
比 in
快于 set
,预绑定(bind)它实际上减慢了速度而不是加快了速度,非内置 Set
快了 4 倍而不是慢了 3 倍。为什么?我可以做出一些猜测,但每当我尝试深入研究 PyPy 的 JIT 以获得可靠的答案时,三天后我出来时除了了解到 Armin Rigo 是一个 18 级巫师之外什么都没有。
(另请注意,仅切换 Python 解释器所产生的差异比我们可以在该语言中进行的任何微优化都要大一个数量级。)
关于python - `in` 比 `__contains__` 有多少优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52010120/
这是我的代码: class a(object): d='ddd' def __contains__(self): if self.d:return True b=a()
是否可以将列表中的“__ 包含 __”函数传递给多个参数?我想检查至少我在列表中的项目之一是否存在于不同的列表中。 例如:[0,1,4,8,87,6,4,7,5,'a','f','er','fa','
我有一个这样定义的简单类: class User(object): def __init__(self, id=None, name=None): self.id = id
我写了一个 python 程序,它使用 contains 语法的多个实例来查看字典和列表。 if not test_map[var].__contains__(string): 看来我最好还是使用 :
一般性问题 我想知道是否存在与 __contains__ 相反的 Python(即类似 __notcontains__ 的东西)。 我的例子 我需要它用于以下代码: df_1 = df[(df.id1
class a(object): def a(self): return True __contains__=a b=a() print 2 in b#why erro
因此在 itertools 配方部分,他们有一段代码如下所示: seen = set() seen_add = seen.add 我想知道类似的想法是否可以弥合 in 和 __contains__ 之
我的 Sentence 类中有 contains 方法,它检查一个单词是否在一个句子中(在我的例子中是字符串) 我尝试检查我的 functionTesting 是否 hello 存在于 hello w
列表类的 __contains__ 方法是检查对象本身是否是列表的元素,还是检查列表是否包含与给定参数等效的元素? 你能给我一个例子来证明吗? 最佳答案 >>> a = [[]] >>> b = []
我需要在 Python 中模拟枚举,并通过编写如下类来实现: class Spam(Enum): k = 3 EGGS = 0 HAM = 1 BAKEDBEANS =
我有一个工作文件[如下],但我想知道前三行是否有更好的解决方案。 我在一个文件夹中有几个文件,还有一个脚本根据特定的和保存的 处理它们在每个文件的名称中。但是,我被告知我不应该使用 __contai
我得到了一个数组: temp = np.empty(5, dtype=np.ndarray) temp[0] = np.array([0,1]) 我想检查 np.array([0,1]) in tem
文档说 __contains__ 应该 如果 item 在 self 中则返回 true,否则返回 false。但是,如果该方法返回一个非 bool 值 x,似乎 python 会自动将其转换为 bo
对于内置的 python 容器(list、tuple 等),in 运算符等同于 any(y == item for item in container) 需要注意的是前一种方法更快(更漂亮): In
从__contains__文档中借用文档 print set.__contains__.__doc__ x.__contains__(y) y in x. 这似乎适用于原始对象,如 int、base
>>> x = numpy.array([[1, 2], ... [3, 4], ... [5, 6]]) >>> [1, 7] i
前几天我第一次在一个类上实现了 __contains__ 方法,结果出乎我的意料。我怀疑 in 有一些微妙之处操作符我不懂,希望有人能赐教。 在我看来,in 运算符不只是简单地包装对象的 __cont
我有一个 Nx3 numpy 数组,其中列出了一个曲面的 N 个三角形面的 3 个顶点,以及一个 Nx1 数组,其中包含与每个面对应的值。 我想(尽可能最好地)将这些“面”值转换为“顶点”值,例如通过
我无法理解如何在我的类中正确设置包含 方法。我知道当你调用它时它会自动使用运算符“in”,我只是不明白如何正确设置它。 我必须使用它来查看 anotherCircle 是否包含在特定圆圈中(均来自用户
我正在对 OrderedDict(Cpython,2.7.3)进行子类化以表示数据文件。 __getitem__ 从数据文件中提取一个字段并将其设置在当前实例上,类似于我在下面发布的代码。现在我想覆盖
我是一名优秀的程序员,十分优秀!