标签: python-internals

对相同对象的慢等式评估(x == x)

有没有什么理由x == x不能快速评估?我希望__eq__能检查它的两个参数是否相同,如果是,则立即返回True.但它没有这样做:

s = set(range(100000000))
s == s # this doesn't short-circuit, so takes ~1 sec
Run Code Online (Sandbox Code Playgroud)

对于内置插件,x == x总是返回True我认为?对于用户定义的类,我想有人可能会定义__eq__不满足此属性,但是有没有合理的用例呢?

我想之所以x == x能够快速评估是因为它是在一个巨大的性能损失非常大的参数memoizing功能:

from functools import lru_cache
@lru_cache()
def f(s):
    return sum(s)
large_obj = frozenset(range(50000000))
f(large_obj) # this takes >1 sec every time
Run Code Online (Sandbox Code Playgroud)

请注意,@ lru_cache 对大型对象反复慢的原因并不是因为它需要计算__hash__(这只是执行一次然后由@jsbueno 指出的硬缓存),但因为__eq__ 每次都需要执行字典的哈希表确保它在桶中找到正确的对象(哈希的相等性显然是不够的).

更新:

对于三种情况,似乎值得分别考虑这个问题.

1)用户定义的类型(即,不是内置/标准库).

正如@donkopotamus指出的那样,有些情况下x == x不应该评估为True.例如,for numpy.arraypandas.Seriestypes,结果有意无法转换为boolean,因为它不清楚自然语义应该是什么(False意味着容器是空的,还是意味着它中的所有项都是False?).

但是在这里,python不需要做任何事情,因为 …

python python-3.x python-internals

15
推荐指数
1
解决办法
273
查看次数

Python 3.11 对象像槽一样轻吗?

经过Mark Shannon对Python对象的优化,普通对象和带槽的对象有什么不同吗?据我所知,在正常用例中进行此优化后,对象没有字典。新的 Python 对象是否已经完全不需要使用槽了?

python slots python-internals python-3.11

15
推荐指数
1
解决办法
586
查看次数

Python 3中的super()是如何实现的?

我想知道Python 3中的新超级是如何实现的.

在我做了一个小例子之后,这个问题就出现在了我脑海中,我得到了一个奇怪的错误.我正在使用Pyutilib组件架构(PCA),我已经制作了自定义元类来驱动另一个类的创建:

from pyutilib.component.core import implements, SingletonPlugin, PluginMeta, Interface

class IPass(Interface):
    pass

class __MetaPlugin(PluginMeta):
    def __new__(cls, name, baseClasses, classdict):
        print(cls, name, baseClasses, classdict)
        if baseClasses:
            baseClasses += (SingletonPlugin,)
        return PluginMeta.__new__(cls, name, baseClasses, classdict)

class Pass(metaclass=__MetaPlugin):
    implements(IPass)

    def __init__(self, inputs=[], outputs=[]):
        self.inputs = []
        self.outputs = []


class A(Pass):
    def __init__(self):
        print(self.__class__) # <class '__main__.A'>
        print(self.__class__.__class__) # <class '__main__.__MetaPlugin'>
        print(PluginMeta.__class__) # <class 'type'>
        super().__init__() # SystemError: super(): empty __class__ cell
        #Pass.__init__(self) - this works

a = A()
Run Code Online (Sandbox Code Playgroud)

我收到以下错误: …

python metaprogramming super python-3.x python-internals

14
推荐指数
2
解决办法
2179
查看次数

__slots__如何避免字典查找?

我听说__slots__通过避免字典查找使对象更快.我的困惑来自于Python是一种动态语言.在静态语言中,我们a.test通过执行编译时优化来避免字典查找,以便在我们运行的指令中保存索引.

现在,在Python中,a可以很容易地成为另一个具有字典或不同属性集的对象.看起来我们仍然需要进行字典查找 - 唯一的区别似乎是我们只需要一个类的字典,而不是每个对象的字典.

有了这个理性,

  1. 如何__slots__避免字典查找?
  2. 插槽是否可以更快地访问对象?

python slots python-internals

14
推荐指数
2
解决办法
3499
查看次数

Python 2使用什么方法来打印元组?

Python的print声明通常似乎打印repr()其输入.元组似乎不是例外:

>>> print (1, 2, 3)
(1, 2, 3)
>>> print repr((1, 2, 3))
(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)

但是当我弄乱CPython的内部时,我偶然发现了一些奇怪的行为.简而言之:如果您使用Python 2来创建自引用元组,则直接打印它的行为与打印其repr()/ str()/ unicode()表示完全不同.

>>> print outer   # refer to the link above
((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
... many lines later ...
((((((((((Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
MemoryError: stack overflow
>>> print repr(outer)
((...),)
>>> print str(outer)
((...),)
>>> print unicode(outer)
((...),)
Run Code Online (Sandbox Code Playgroud)

到底是print做什么的?为了尝试自己回答这个问题,我提到了语言参考:

6.6.该print声明

print …

python cpython self-reference python-2.7 python-internals

14
推荐指数
1
解决办法
421
查看次数

为什么locals()会返回一个奇怪的自引用列表?

所以我使用locals()来获取函数中的一些参数.很好地工作:

def my_function(a, b):
    print locals().values()

>>> my_function(1,2)
[1, 2]
Run Code Online (Sandbox Code Playgroud)

标准的东西.但现在让我们介绍一下列表理解:

def my_function(a, b):
    print [x for x in locals().values()]

>>> my_function(1,2)
[[...], 1, 2]
Run Code Online (Sandbox Code Playgroud)

EHH?为什么要插入自引用?

python list-comprehension python-2.6 locals python-internals

14
推荐指数
1
解决办法
444
查看次数

python的运行时if字符串中的子字符串

以下大O是if statement什么?

if "pl" in "apple":
   ...
Run Code Online (Sandbox Code Playgroud)

如果字符串"pl"在字符串"apple"中找到,python如何确定的总体大O是多少?

或字符串搜索中的任何其他子字符串.

这是测试子字符串是否在字符串中的最有效方法吗?它使用相同的算法.find()吗?

python time-complexity python-internals

14
推荐指数
2
解决办法
8507
查看次数

int()对象如何在python2中使用"=="运算符而不使用__eq __()方法?

最近我读了"Fluent python"并理解了==operator 如何使用python对象,使用__eq__()方法.但它如何与intpython2中的实例一起使用?

>>> a = 1
>>> b = 1
>>> a == b
True
>>> a.__eq__(b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__eq__'
Run Code Online (Sandbox Code Playgroud)

在python3中都a.__eq__(b)返回True

python python-2.7 python-internals

14
推荐指数
2
解决办法
693
查看次数

为什么除了对象捕获Python中的所有东西?

python语言参考在7.4节中说明:

对于带有表达式的except子句,将计算该表达式,如果结果对象与异常"兼容",则子句匹配该异常.如果对象是异常对象的类或基类,或者包含与异常兼容的项的元组,则该对象与异常兼容.

那么,为什么不except object:抓住一切?object是所有异常类的基类,因此except object:应该能够捕获每个异常.

例如,这应该抓住了 AssertionError

print isinstance(AssertionError(), object) # prints True
try:
    raise AssertionError()
except object:
    # This block should execute but it never does.
    print 'Caught exception'
Run Code Online (Sandbox Code Playgroud)

python exception python-2.x python-internals

14
推荐指数
1
解决办法
456
查看次数

为什么__self__的内置函数会返回它所属的内置模块?

方法有一个属性,__self__用于保存在调用基础函数时要传递的实例.显然,内置函数也是如此.

在Python 3中,它们包含模块对象:

>>> len.__self__
<module 'builtins' (built-in)>
>>> sys.getrefcount.__self__  # also for other builtin modules
<module 'sys' (built-in)>
Run Code Online (Sandbox Code Playgroud)

另一方面,在Python 2中,它们包含None:

>>> type(len.__self__)
<type 'NoneType'>
>>> sys.getrefcount.__self__
<type 'NoneType'>
Run Code Online (Sandbox Code Playgroud)

有谁知道为什么这里有差异?除此之外,为什么这些甚至有一个__self__并且不像缺少__self__属性的Python级模块函数:

>>> from pprint import pprint
>>> pprint.__self__
AttributeError: 'function' object has no attribute '__self__'
Run Code Online (Sandbox Code Playgroud)

python python-2.7 python-3.x python-internals

14
推荐指数
1
解决办法
403
查看次数