对我来说,最惯用的方式tempfile.mkstemp()是:
with tempfile.mkstemp() as fd, filename:
pass
Run Code Online (Sandbox Code Playgroud)
然而,这显然(?)提高了 AttributeError: __exit__
os.close(fd)使用try-finally明确调用是解决这个问题的一种简单方法,但感觉就像违反一样 - 应该有一个 - 最好只有一个 - 明显的方法来做到这一点.
有没有办法"修复"这个tempfile或者有没有理由说明为什么这样实现?
我的一个朋友向我展示了以下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+1和SLICE+2.文档不清楚这些操作码是否实际创建了一个新副本a,或仅仅是对它的引用.
a …>>> 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)
任何人都可以向我解释内幕吗?
我找到了一些有趣的东西,这里有一段代码:
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__()在使用旧样式时调用?为什么新旧风格的行为有不同的行为?
我在这里发现了类似的问题,但我认为答案还不够明确.
我完全坚持这个
>>> 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随机模块的性能问题,特别是,random.sample并random.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) 码:
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会记得int和Integer):
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等等),而是简单地说,他们不支持弱引用.这可能是由于性能问题,但不能弱化这些内置类型大大减少了它的使用.
让我们说你有一套:
foo = {1, 2, 3, 4, 5}
Run Code Online (Sandbox Code Playgroud)
在我正在阅读的书中,Pro Python,它说使用foo.pop()将弹出该选择中的任意数字.但是......当我尝试它时,它pops 1, then 2, then 3...是否随意做,或者这只是巧合?
在容器类中,当我想迭代其项目(或其项目的变换或其项目的子集)时,我可以编写生成器(如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.
显然两种方式都表现相同(在表面).
哪种方法更可取,为什么?
哪种方法可以减少开销,或者具有其他我未能发现的优势?
该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 ×10
python-internals ×10
python-3.x ×3
algorithm ×1
cpython ×1
generator ×1
hashtable ×1
optimization ×1
python-2.x ×1
random ×1
set ×1
string ×1
tuples ×1