有没有什么理由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.array和pandas.Seriestypes,结果有意无法转换为boolean,因为它不清楚自然语义应该是什么(False意味着容器是空的,还是意味着它中的所有项都是False?).
但是在这里,python不需要做任何事情,因为 …
经过Mark Shannon对Python对象的优化,普通对象和带槽的对象有什么不同吗?据我所知,在正常用例中进行此优化后,对象没有字典。新的 Python 对象是否已经完全不需要使用槽了?
我想知道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)
我收到以下错误: …
我听说__slots__通过避免字典查找使对象更快.我的困惑来自于Python是一种动态语言.在静态语言中,我们a.test通过执行编译时优化来避免字典查找,以便在我们运行的指令中保存索引.
现在,在Python中,a可以很容易地成为另一个具有字典或不同属性集的对象.看起来我们仍然需要进行字典查找 - 唯一的区别似乎是我们只需要一个类的字典,而不是每个对象的字典.
有了这个理性,
__slots__避免字典查找?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 …
所以我使用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
以下大O是if statement什么?
if "pl" in "apple":
...
Run Code Online (Sandbox Code Playgroud)
如果字符串"pl"在字符串"apple"中找到,python如何确定的总体大O是多少?
或字符串搜索中的任何其他子字符串.
这是测试子字符串是否在字符串中的最有效方法吗?它使用相同的算法.find()吗?
最近我读了"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语言参考在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) 方法有一个属性,__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 ×10
python-internals ×10
python-2.7 ×3
python-3.x ×3
slots ×2
cpython ×1
exception ×1
locals ×1
python-2.6 ×1
python-2.x ×1
python-3.11 ×1
super ×1