标签: python-internals

列表是否理解为Python 3中的`list(generator expression)`的语法糖?

在Python 3中,列表理解只是语法糖,用于生成list函数的生成器表达式?

例如是以下代码:

squares = [x**2 for x in range(1000)]
Run Code Online (Sandbox Code Playgroud)

实际上在后台转换成以下内容?

squares = list(x**2 for x in range(1000))
Run Code Online (Sandbox Code Playgroud)

我知道输出是相同的,并且Python 3修复了列表推导所具有的周围命名空间的令人惊讶的副作用,但就CPython解释器所做的事情而言,前者转换为后者,或者是否有任何区别在如何执行代码?

背景

我发现,在评论部分等价的这一主张这个问题,和快速谷歌搜索显示了同样的要求正在作出这里.

在Python 3.0文档中的新内容中也提到了这一点,但措辞有些含糊:

还要注意,列表推导具有不同的语义:它们更接近于list()构造函数中的生成器表达式的语法糖,特别是循环控制变量不再泄漏到周围的范围中.

python list-comprehension generator-expression python-3.x python-internals

33
推荐指数
3
解决办法
2249
查看次数

为什么Python 3.6 alpha中的文字格式化字符串如此之慢?(现在固定在3.6稳定)

我从Python Github存储库下载了一个Python 3.6 alpha版本,我最喜欢的一个新功能是文字字符串格式化.它可以像这样使用:

>>> x = 2
>>> f"x is {x}"
"x is 2"
Run Code Online (Sandbox Code Playgroud)

这似乎与formatstr实例上使用该函数做同样的事情.但是,我注意到的一件事是,与仅调用相比,这种文字字符串格式化实际上非常慢format.以下是timeit关于每种方法的内容:

>>> x = 2
>>> timeit.timeit(lambda: f"X is {x}")
0.8658502227130764
>>> timeit.timeit(lambda: "X is {}".format(x))
0.5500578542015617
Run Code Online (Sandbox Code Playgroud)

如果我使用字符串作为timeit参数,我的结果仍然显示模式:

>>> timeit.timeit('x = 2; f"X is {x}"')
0.5786435347381484
>>> timeit.timeit('x = 2; "X is {}".format(x)')
0.4145195760771685
Run Code Online (Sandbox Code Playgroud)

如您所见,使用format几乎占用了一半的时间.我希望文字方法更快,因为涉及的语法更少.幕后发生了什么导致文字方法如此慢?

python performance python-internals python-3.6 f-string

32
推荐指数
2
解决办法
3447
查看次数

为什么str.strip()比str.strip('')快得多?

可以通过两种方式分割白色空间str.strip.您可以发出不带参数的调用str.strip(),默认情况下使用空格分隔符或自己显式提供参数str.strip(' ').

但是,为什么在定时时这些功能的表现如此不同?

使用具有有意量的空格的示例字符串:

s = " " * 100 + 'a' + " " * 100
Run Code Online (Sandbox Code Playgroud)

时间s.strip()和时间s.strip(' ')分别为:

%timeit s.strip()
The slowest run took 32.74 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 3: 396 ns per loop

%timeit s.strip(' ')
100000 loops, best of 3: 4.5 µs per loop
Run Code Online (Sandbox Code Playgroud)

strip需要396nsstrip(' ')采用4.5 …

python string performance python-3.x python-internals

31
推荐指数
2
解决办法
2634
查看次数

了解Python中大整数的内存分配

Python如何为大整数分配内存?

一个int类型的大小28 bytes和随着我不断增加的值int,大小以增量为单位增加4 bytes.

  1. 为什么28 bytes最初的价值低至何1

  2. 为什么增量4 bytes

PS:我在x86_64(64位机器)上运行Python 3.5.2.关于(3.0+)解释器如何处理如此庞大的数字的任何指针/资源/ PEP都是我正在寻找的.

代码说明尺寸:

>>> a=1
>>> print(a.__sizeof__())
28
>>> a=1024
>>> print(a.__sizeof__())
28
>>> a=1024*1024*1024
>>> print(a.__sizeof__())
32
>>> a=1024*1024*1024*1024
>>> print(a.__sizeof__())
32
>>> a=1024*1024*1024*1024*1024*1024
>>> a
1152921504606846976
>>> print(a.__sizeof__())
36
Run Code Online (Sandbox Code Playgroud)

python int python-3.x python-internals

31
推荐指数
2
解决办法
2834
查看次数

yield from 与 for 循环中的yield

我的理解yield from是,它类似于yield从可迭代对象中获取每个项目。然而,我在以下示例中观察到不同的行为。

我有Class1

class Class1:
    def __init__(self, gen):
        self.gen = gen
        
    def __iter__(self):
        for el in self.gen:
            yield el
Run Code Online (Sandbox Code Playgroud)

和 Class2 的不同之处仅在于yield将 for 循环替换为yield from

class Class2:
    def __init__(self, gen):
        self.gen = gen
        
    def __iter__(self):
        yield from self.gen
Run Code Online (Sandbox Code Playgroud)

下面的代码从给定类的实例中读取第一个元素,然后在 for 循环中读取其余元素:

a = Class1((i for i in range(3)))
print(next(iter(a)))
for el in iter(a):
    print(el)
Run Code Online (Sandbox Code Playgroud)

Class1这会为和产生不同的输出Class2。对于Class1输出是

0
1
2
Run Code Online (Sandbox Code Playgroud)

Class2输出为

0
Run Code Online (Sandbox Code Playgroud)

现场演示

yield from产生不同行为的背后机制是什么?

python yield generator python-internals yield-from

31
推荐指数
1
解决办法
2823
查看次数

在python3.6中,集合的顺序是像dicts一样

由于dictPython 3.6 中的实现发生了变化,现在默认排序.现在还set保留秩序吗?

我找不到任何关于它的信息,但由于这两种数据结构在它们工作的方式非常相似,我认为可能就是这种情况.

我知道dict在所有情况下都无法订购s,但它们大多数情况下都是如此.如Python文档中所述:

这个新实现的顺序保留方面被认为是一个实现细节,不应该依赖它

python cpython set python-internals python-3.6

30
推荐指数
2
解决办法
6716
查看次数

使用Python 3打印没有括号的错误消息

当我尝试print在Python 3.4中使用不带括号的简单名称时,我得到:

>>> print max
Traceback (most recent call last):
  ...
  File "<interactive input>", line 1
    print max
            ^
SyntaxError: Missing parentheses in call to 'print'
Run Code Online (Sandbox Code Playgroud)

好的,现在我明白了,我只是忘了移植我的Python 2代码.

但是现在当我尝试打印函数的结果时:

>>> print max([1,2])
Traceback (most recent call last):
    ...
    print max([1,2])
            ^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)

要么:

print max.__call__(23)
        ^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)

(请注意,在这种情况下,光标指向第一个点之前的字符.)

消息不同(并且稍有误导,因为标记位于max函数下方).

为什么Python不能提前检测到问题?

注意:这个问题的灵感来自于围绕这个问题的困惑:Pandas read.csv语法错误,由于误导性的错误消息,一些Python专家错过了真正的问题.

python syntax-error python-3.x python-internals

30
推荐指数
4
解决办法
2524
查看次数

检查空字符串是否在另一个字符串时,为什么返回True?

我有限的大脑无法理解为什么会这样:

>>> print '' in 'lolsome'
True
Run Code Online (Sandbox Code Playgroud)

在PHP中,等效比较返回false:

var_dump(strpos('', 'lolsome'));
Run Code Online (Sandbox Code Playgroud)

python string python-internals

29
推荐指数
4
解决办法
2349
查看次数

Python 3.10 和其他版本的线程差异

对于一些简单的线程相关代码,即:

\n
import threading\n\n\na = 0\nthreads = []\n\n\ndef x():\n    global a\n    for i in range(1_000_000):\n        a += 1\n\n\nfor _ in range(10):\n    thread = threading.Thread(target=x)\n    threads.append(thread)\n    thread.start()\n\n\nfor thread in threads:\n    thread.join()\n\n\nprint(a)\nassert a == 10_000_000\n
Run Code Online (Sandbox Code Playgroud)\n

根据 Python 版本,我们得到了不同的行为。

\n

对于 3.10,输出为:

\n
\xe2\x9d\xaf python3.10 b.py\n10000000\n
Run Code Online (Sandbox Code Playgroud)\n

对于 3.9,输出为:

\n
\xe2\x9d\xaf python3.9 b.py\n2440951\nTraceback (most recent call last):\n  File "/Users/romka/t/threads-test/b.py", line 24, in <module>\n    assert a == 10_000_000\nAssertionError\n
Run Code Online (Sandbox Code Playgroud)\n

由于我们没有获取任何锁,对我来说,3.9 的结果是显而易见的并且是预期的。问题是为什么 3.10 得到了“正确”的结果,而不应该得到“正确”的结果?

\n

我正在查看 Python 3.10 的变更日志,没有任何与线程或 GIL 相关的内容可以带来这样的结果。

\n

python multithreading python-multithreading python-internals

28
推荐指数
1
解决办法
5146
查看次数

python生成器垃圾收集

我认为我的问题与有关,但并不完全相似.考虑以下代码:

def countdown(n):
    try:
        while n > 0:
            yield n
            n -= 1
    finally:
        print('In the finally block')

def main():
    for n in countdown(10):
        if n == 5:
            break
        print('Counting... ', n)
    print('Finished counting')

main()
Run Code Online (Sandbox Code Playgroud)

此代码的输出是:

Counting...  10      
Counting...  9       
Counting...  8       
Counting...  7       
Counting...  6       
In the finally block 
Finished counting  
Run Code Online (Sandbox Code Playgroud)

是否保证在"完成计数"之前打印"在最后一个块中"这一行?或者这是因为cPython实现细节,当引用计数达到0时,对象将被垃圾收集.

另外我对如何好奇finally的块countdown执行发电机?例如,如果我将代码更改main

def main():
    c = countdown(10)
    for n in c:
        if n == 5:
            break
        print('Counting... ', n)
    print('Finished …
Run Code Online (Sandbox Code Playgroud)

python generator python-internals

27
推荐指数
2
解决办法
1315
查看次数