标签: python-internals

如何用"with"调用tempfile.mkstemp()? - 或者为什么不用__exit __()返回fd?

对我来说,最惯用的方式tempfile.mkstemp()是:

with tempfile.mkstemp() as fd, filename:
    pass
Run Code Online (Sandbox Code Playgroud)

然而,这显然(?)提高了 AttributeError: __exit__

os.close(fd)使用try-finally明确调用是解决这个问题的一种简单方法,但感觉就像违反一样 - 应该有一个 - 最好只有一个 - 明显的方法来做到这一点.

有没有办法"修复"这个tempfile或者有没有理由说明为什么这样实现?

python with-statement temporary-files python-internals

11
推荐指数
2
解决办法
4592
查看次数

切片`a`(例如`a [1:] == a [: - 1]`)是否创建了`a`的副本?

我的一个朋友向我展示了以下Python代码:

a[1:] == a[:-1]
Run Code Online (Sandbox Code Playgroud)

如果所有项目a都相同,则返回True .

我认为代码很难从一见钟情中理解,而且 - 它在内存使用方面效率低下,因为a将为比较创建两个副本.

我用Python dis来看看幕后发生了什么a[1:]==a[:-1]:

>>> def stanga_compare(a):
...     return a[1:]==a[:-1]
...
>>> a=range(10)
>>> stanga_compare(a)
False
>>> a=[0 for i in range(10)]
>>> stanga_compare(a)
True

>>> dis.dis(stanga_compare)
  2           0 LOAD_FAST                0 (a)
              3 LOAD_CONST               1 (1)
              6 SLICE+1
              7 LOAD_FAST                0 (a)
             10 LOAD_CONST               2 (-1)
             13 SLICE+2
             14 COMPARE_OP               2 (==)
             17 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)

归结为两个切片命令 - SLICE+1SLICE+2.文档不清楚这些操作码是否实际创建了一个新副本a,或仅仅是对它的引用.

  • SLICE命令是否复制a …

python cpython memory-efficient python-internals

11
推荐指数
1
解决办法
320
查看次数

python元组的内部结构

>>> a=1
>>> b=1
>>> id(a)
140472563599848
>>> id(b)
140472563599848
>>> x=()
>>> y=()
>>> id(x)
4298207312
>>> id(y)
4298207312
>>> x1=(1)
>>> x2=(1)
>>> id(x1)
140472563599848
>>> id(x2)
140472563599848
Run Code Online (Sandbox Code Playgroud)

直到这一点,我认为只有一个不可变对象的副本,并且将由所有变量共享(指向).

但是当我尝试时,以下步骤我明白我错了.

>>> x1=(1,5)
>>> y1=(1,5)
>>> id(x1)
4299267248
>>> id(y1)
4299267320
Run Code Online (Sandbox Code Playgroud)

任何人都可以向我解释内幕吗?

python tuples python-internals

11
推荐指数
1
解决办法
229
查看次数

为什么新样式类和旧样式类在这种情况下有不同的行为?

我找到了一些有趣的东西,这里有一段代码:

class A(object):
    def __init__(self):
        print "A init"

    def __del__(self):
        print "A del"

class B(object):
    a = A()
Run Code Online (Sandbox Code Playgroud)

如果我运行此代码,我会得到:

A init
Run Code Online (Sandbox Code Playgroud)

但是,如果我更改class B(object)class B(),我会得到:

A init
A del
Run Code Online (Sandbox Code Playgroud)

我在__del__ doc中找到了一个注释:

无法保证为解释器退出时仍然存在的对象调用del()方法.

然后,我想这是因为当解释器存在时B.a仍然引用(由类引用B).

所以,我del B在解释器手动存在之前添加了一个,然后我发现它a.__del__()被调用了.

现在,我对此感到有些困惑.为什么a.__del__()在使用旧样式时调用?为什么新旧风格的行为有不同的行为?

我在这里发现了类似的问题,但我认为答案还不够明确.

python python-2.x python-3.x python-internals

11
推荐指数
1
解决办法
279
查看次数

字符串字符标识悖论

我完全坚持这个

>>> s = chr(8263)
>>> x = s[0]
>>> x is s[0]
False
Run Code Online (Sandbox Code Playgroud)

这怎么可能?这是否意味着通过索引访问字符串字符会创建相同字符的新实例?我们来试验:

>>> L = [s[0] for _ in range(1000)]
>>> len(set(L))
1
>>> ids = map(id, L)
>>> len(set(ids))
1000
>>>
Run Code Online (Sandbox Code Playgroud)

哎呀浪费字节;)或者它是否意味着str.__getitem__有一个隐藏的功能?有人可以解释一下吗?

但这并不是我的惊喜:

>>> s = chr(8263)
>>> t = s
>>> print(t is s, id(t) == id(s))
True True
Run Code Online (Sandbox Code Playgroud)

这很清楚:t是别名s,所以它们代表相同的对象和身份重合.但同样,以下是可能的:

>>> print(t[0] is s[0])
False
Run Code Online (Sandbox Code Playgroud)

s并且t是同一个对象那又怎样?

但更糟糕的是

>>> print(id(t[0]) == id(s[0]))
True
Run Code Online (Sandbox Code Playgroud)

t[0]并且s[0]没有被垃圾收集,被 …

python string python-internals

11
推荐指数
1
解决办法
413
查看次数

python 2 vs python 3随机性能,特别是`random.sample`和`random.shuffle`

python随机模块的性能问题,特别是,random.samplerandom.shuffle提出了这个问题.在我的计算机上,我得到以下结果:

> python  -m timeit -s 'import random' 'random.randint(0,1000)'
1000000 loops, best of 3: 1.07 usec per loop
> python3 -m timeit -s 'import random' 'random.randint(0,1000)'
1000000 loops, best of 3: 1.3 usec per loop
Run Code Online (Sandbox Code Playgroud)

在python3和python2中,性能下降超过20%.它变得更糟.

> python  -m timeit -s 'import random' 'random.shuffle(list(range(10)))'
100000 loops, best of 3: 3.85 usec per loop
> python3 -m timeit -s 'import random' 'random.shuffle(list(range(10)))'
100000 loops, best of 3: 8.04 usec per loop

> python  -m timeit …
Run Code Online (Sandbox Code Playgroud)

python random optimization python-3.x python-internals

11
推荐指数
1
解决办法
1246
查看次数

Python:哪些类型支持弱引用?

码:

from weakref import WeakSet
se = WeakSet()
se.add(1)
Run Code Online (Sandbox Code Playgroud)

输出:

TypeError: cannot create weak reference to 'int' object
Run Code Online (Sandbox Code Playgroud)

Doc:

一些内置类型(如list和dict)不直接支持弱引用,但可以通过子类化添加支持:

...

其他内置类型(如tuple和int)即使在子类化时也不支持弱引用(这是一个实现细节,并且可能在各种Python实现中有所不同).

这表达不足以解释:

  • 为什么有些内置类型不支持弱引用?

  • 那些支持弱引用的类型究竟是什么?


添加一些想法:

对于上面的例子,你可以一个用户定义的包装类内包装的INT,而包装类支持弱引用(那些谁是熟悉Java会记得intInteger):

from weakref import WeakSet
se = WeakSet()

class Integer:
    def __init__(self, n=0):
        self.n = n

i = 1
I = Integer(1)

se.add(i)   # fail
se.add(I)   # ok
Run Code Online (Sandbox Code Playgroud)

我不知道为什么Python不常用的内置类型(提供自动换行int,str等等),而是简单地说,他们不支持弱引用.这可能是由于性能问题,但不能弱化这些内置类型大大减少了它的使用.

python weak-references python-internals

11
推荐指数
1
解决办法
592
查看次数

设置弹出(Python)

让我们说你有一套:

foo = {1, 2, 3, 4, 5}
Run Code Online (Sandbox Code Playgroud)

在我正在阅读的书中,Pro Python,它说使用foo.pop()将弹出该选择中的任意数字.但是......当我尝试它时,它pops 1, then 2, then 3...是否随意做,或者这只是巧合?

python algorithm hashtable set python-internals

10
推荐指数
2
解决办法
1216
查看次数

写一个发电机或返回发电机?

在容器类中,当我想迭代其项目(或其项目的变换或其项目的子集)时,我可以编写生成器(如f)或返回生成器(如g):

class SomeContainer:
    def __init__(self):
        self.data = [1, 'two', 3, 'four']

    def f(self):
        for e in self.data: yield e + e

    def g(self):
        return (e + e for e in self.data)

sc = SomeContainer()
for x in sc.f(): print(x)
for x in sc.g(): print(x)
Run Code Online (Sandbox Code Playgroud)

我不需要通过信息将信息传递给发生器send.

显然两种方式都表现相同(在表面).

  1. 哪种方法更可取,为什么?

  2. 哪种方法可以减少开销,或者具有其他我未能发现的优势?

python generator python-3.x python-internals

10
推荐指数
1
解决办法
128
查看次数

Python:更好地理解迭代器和`join()`

join()函数接受iterable作为参数.但是,我想知道为什么:

text = 'asdfqwer'
Run Code Online (Sandbox Code Playgroud)

这个:

''.join([c for c in text])
Run Code Online (Sandbox Code Playgroud)

明显快于:

''.join(c for c in text)
Run Code Online (Sandbox Code Playgroud)

长字符串也是如此(即text * 10000000).

使用长字符串观察两个执行的内存占用,我认为它们都在内存中创建一个且只有一个字符列表,然后将它们连接成一个字符串.所以我猜也许区别仅在于如何join()从生成器创建这个列表以及Python解释器在看到它时如何做同样的事情[c for c in text].但是,我只是在猜测,所以我希望有人确认/否认我的猜测.

python python-internals

10
推荐指数
1
解决办法
220
查看次数