试图用Python编写尽可能高效的优先级队列的面向对象实现,我遇到了一个有趣的行为。下面的代码工作正常
from heapq import heappush
class PriorityQueue(list):
__slots__ = ()
def push(self, item):
heappush(self, item)
然而,我真的不想编写一个用于调用heappush
的包装器方法,因为它会为调用函数带来额外的开销。我推断,由于heappush
签名使用list
作为第一个参数,同时将push
类属性与heappush
函数混淆,后者成为一个完整的类实例方法。然而,我的假设被证明是错误的,下面的代码给出了一个错误
from heapq import heappush
class PriorityQueue(list):
__slots__ = ()
push = heappush
PriorityQueue().push(0)
# TypeError: heappush expected 2 arguments, got 1
但是转到cpython
{a1}源代码,只需将heappush
实现复制到范围中并应用相同的逻辑即可
from heapq import _siftdown
def heappush(heap, item):
"""Push item onto heap, maintaining the heap invariant."""
heap.append(item)
_siftdown(heap, 0, len(heap) - 1)
class PriorityQueue(list):
__slots__ = ()
push = heappush
pq = PriorityQueue()
pq.push(0)
pq.push(-1)
pq.push(3)
print(pq)
# [-1, 0, 3]
Python
如何决定哪个函数适合绑定为实例方法,哪个不适合李>cpython/Lib/heapq.py
中的heappush
与heapq
模块中的实际heappush
之间有什么区别?它们实际上是不同的,因为下面的代码给出了一个错误from dis import dis
from heapq import heappush
dis(heappush)
# TypeError: don't know how to disassemble builtin_function_or_method objects
Python
将本机heappush
绑定为实例方法?一些元类魔法李>谢谢大家!
也许这就是python调用函数的方式。当您尝试
print(type(heappush))
时,您会注意到差异对于问题1,用于标识哪个函数是哪个类型(即
staticmethod
,classmethod
)的修饰符类似于调用并处理函数,并将处理后的函数返回到该名称。因此,确定它的数据应该在函数的某个属性中。在我找到它的位置后,问题3可能会被解决关于问题2。导入内置函数时,它的类型为
builtin_function_or_method
。但是如果复制并粘贴它,它是在代码中定义的,所以它只是function
。这可能会导致解释器将其称为静态方法,而不是实例方法所发生的事情是,Python在标准库中提供了许多算法的纯Python实现,即使它包含相同算法的加速本机代码实现
heapq库就是其中之一——如果您选择链接到的文件,但接近结尾,您将看到代码片段,它看起来是否有本机版本,并覆盖Python版本,其中包含您复制和粘贴的代码-https://github.com/python/cpython/blob/76cd81d60310d65d01f9d7b48a8985d8ab89c8b4/Lib/heapq.py#L580
本机版本的
heappush
被加载到模块中,除了获取实际的文件源代码之外,没有简单的方法可以获取对原始Python函数的引用现在,重点是:为什么本机函数不能作为类方法工作? heappush的类型是
builtin_function_or_method
,与纯Python函数的function
相比,主要区别之一是第二种对象类型具有__get__
方法。这个__get__
使得Python定义的函数可以作为“描述符”工作:当从实例检索属性时,调用__get__
方法。对于普通函数,此调用记录self
参数,并在调用实际函数时将其注入因此,编写一个“instancemethod”修饰符是很容易的,它将使内置函数作为Python函数工作,并可用作方法。但是,创建部分函数或lambda函数的开销应该超过您试图消除的额外函数调用的开销-因此您不应该从中获得速度增益,尽管它可能读起来更优雅:
相关问题 更多 >
编程相关推荐