为什么[0]是一个不同的函数,但0不是?

问题描述 投票:3回答:1

我检查了.__code__对象的两个函数,我认为它们对于各种表达式而言是不同的,但发现是相同的。据我所知,如果代码对象相同,它们将编译为相同的字节码,因此是“相同”的函数。

下表是在; pass之前插入的内容,这些内容使g具有不同的__code__。由于f是“不执行任何操作”功能,因此建议对[[从不执行“相同”下的所有内容,包括长运算。此外,元组是“相同”的,但列表和字符串是“ diff”的-因此我们可能得出的结论是,未评估涉及unmutableliteralunssigned表达式。但是接着是1/0,由于引发异常可能是“例外”-那么10**9910**9到底是什么? 10**99不会引发异常,可以分配。

我无法从剖析中看出很多; “ same”和“ diff”的执行时间几乎没有区别。但是,当它们

可以

被区分时,总是带有“ diff”。如果“相同”从不执行,那么Python如何确定要执行或不执行什么?如果它们确实执行,它们的代码对象如何相同?


相同:

    [0(0,)TrueFalseNone
  • 10 ** 9
  • ()
  • -314159.265358 ** (1/12345) / 2.718281828 + 500 - 7j
  • Diff

    • [[0]{0: 0}
    • 10 ** 99
    • [[]{}""

  • 比较代码

  • def compare(fn1, fn2): for name in dir(fn1.__code__): if (name.startswith("co_") and name not in ("co_filename", "co_name", "co_firstlineno")): v1 = getattr(fn1.__code__, name) v2 = getattr(fn2.__code__, name) if v1 == v2: print(name.ljust(18), "same") else: print(name.ljust(18), "diff", v1, v2) def f(): pass def g(): 10 ** 99; pass
    以下内容有所不同:co_name(始终),co_filename(IPython),co_firstlineno(来自文件)-但不影响“执行”的内容,如果有误,请纠正我;与docs不同,co_code应该有所不同。    
    python python-3.x cpython
    1个回答
    1
    投票
    “ diff”组的所有文字不是常数([]{})或不适合预评估(例如10 ** 99小于其值)。 “相同”组的所有表达式求值为常数,可以将其丢弃。检查字节码表明表达式已完全删除:

    >>> # CPython 3.7.4 >>> def g(): 10/1; pass >>> dis.dis(g) 1 0 LOAD_CONST 0 (None) 2 RETURN_VALUE

    值得注意的是,

    删除的表达式均未更改可观察的行为。 Python实现是否消除了不可观察的行为,纯粹是实现细节。具有副作用的表达式,例如1/0,不会被删除。

    >>> # CPython 3.7.4 >>> def g(): 10/0; pass >>> dis.dis(g) 1 0 LOAD_CONST 1 (10) 2 LOAD_CONST 2 (0) 4 BINARY_TRUE_DIVIDE 6 POP_TOP 8 LOAD_CONST 0 (None) 10 RETURN_VALUE
    对于所示的表达式,字节码在CPython 3.7.4,CPython 3.8.2,PyPy 3.6.9 [PyPy 7.3.0]上是相同的。

    在CPython 3.4.3上,对常量表达式求值,但不丢弃。

    >>> # CPython 3.4.3 >>> def g(): 10/1; pass >>> dis.dis(g) 1 0 LOAD_CONST 3 (10.0) 3 POP_TOP 4 LOAD_CONST 0 (None) 7 RETURN_VALUE

    © www.soinside.com 2019 - 2024. All rights reserved.