标签: python-internals

Python字典"<"的含义是什么?

我注意到Python让我这样做:

>>> {1: "foo"} < {2: "bar"}
True
Run Code Online (Sandbox Code Playgroud)

它允许我为列表,deques等做同样的事情.什么是<在Python中应用于字典时的语义?

一般来说,在哪里可以找到<任何给定类型集合的语义?在大多数情况下,似乎没有在文档中找到.例如:

>>> help(dict.__cmp__)

Help on wrapper_descriptor:

__cmp__(...)
    x.__cmp__(y) <==> cmp(x,y)

>>> help(cmp)

Help on built-in function cmp in module __builtin__:

cmp(...)
    cmp(x, y) -> integer

    Return negative if x<y, zero if x==y, positive if x>y.
Run Code Online (Sandbox Code Playgroud)

我问,因为我有一个表格的元组列表(int, dict).我想根据第一个元素对这个数组进行排序,但如果第一个元素对于两个项目是相等的,那么我不关心第二个元素.我想知道是否myArray.sort()会做一些复杂的事情,包括在这种情况下通过dicts递归,或者它只返回一个任意值.

python python-2.7 python-internals

17
推荐指数
1
解决办法
718
查看次数

反转元组和反向列表之间有什么区别?

反转元组并反转列表会返回不同类型的对象:

>>> reversed((1,2))
<reversed at 0x7fffe802f748>
>>> reversed([1,2])
<list_reverseiterator at 0x7fffebdd4400>
Run Code Online (Sandbox Code Playgroud)

他们也一样dir.这两种类型都不是另一种类型的子类.

这是为什么?一个人可以做什么,另一个不能?

python python-internals reverse-iterator

17
推荐指数
2
解决办法
639
查看次数

为什么链接的运算符表达式比扩展的等效表达式慢?

在python中,可以以这种方式链接运算符:

a op b op c
Run Code Online (Sandbox Code Playgroud)

评估为

a op b and b op c 
Run Code Online (Sandbox Code Playgroud)

唯一的区别b是只评估一次(所以更像是t = eval(b); a op t and t op c).

从具有显式连接(使用)的等效版本可读且更简洁的观点来看,这是有利的and.

但是......我注意到链接表达式和等效表达式之间存在微小的性能差异,无论是3个操作数还是20个.当你计算这些操作时,这一点就变得很明显了.

import timeit 

timeit.timeit("a <= b <= c", setup="a,b,c=1,2,3")
0.1086414959972899

timeit.timeit("a <= b and b <= c", setup="a,b,c=1,2,3")
0.09434155100097996
Run Code Online (Sandbox Code Playgroud)

和,

timeit.timeit("a <= b <= c <= d <= e <= f", setup="a,b,c,d,e,f=1,2,3,4,5,6")
0.2151330839988077

timeit.timeit("a <= b and b <= c and c <= d and …
Run Code Online (Sandbox Code Playgroud)

python comparison python-internals

17
推荐指数
1
解决办法
374
查看次数

为什么一个类的主体在定义时被执行?

与函数相反,类的主体在定义时执行:

class A(object):
    print 'hello'
Run Code Online (Sandbox Code Playgroud)

日期:

hello
Run Code Online (Sandbox Code Playgroud)

为什么会这样?它与@classmethod/ @staticmethodmethods和class属性有关吗?

python class python-2.7 python-internals

16
推荐指数
2
解决办法
2760
查看次数

为什么函数(Python)的__code__是可变的

在昨天的一个问题中,在评论中,我开始知道在python __code__函数中的atrribute是可变的.因此我可以编写如下代码

def foo():
    print "Hello"

def foo2():
    print "Hello 2"

foo()
foo.__code__ = foo2.__code__
foo()
Run Code Online (Sandbox Code Playgroud)

产量

Hello
Hello 2
Run Code Online (Sandbox Code Playgroud)

我试过谷歌搜索,但要么因为没有信息(我非常怀疑这一点),或者关键字(__code__)不容易搜索,我找不到一个用例.

它似乎不是"因为Python中的大多数东西都是可变的"也是一个合理的答案,因为函数的其他属性 - __closure____globals__- 是显式只读的(来自Objects/funcobject.c):

static PyMemberDef func_memberlist[] = {
    {"__closure__",   T_OBJECT,     OFF(func_closure),
     RESTRICTED|READONLY},
    {"__doc__",       T_OBJECT,     OFF(func_doc), PY_WRITE_RESTRICTED},
    {"__globals__",   T_OBJECT,     OFF(func_globals),
     RESTRICTED|READONLY},
    {"__module__",    T_OBJECT,     OFF(func_module), PY_WRITE_RESTRICTED},
    {NULL}  /* Sentinel */
};
Run Code Online (Sandbox Code Playgroud)

为什么__code__在其他属性为只读时可写?

python internals python-internals

16
推荐指数
1
解决办法
1478
查看次数

为什么在Python 3中__dict__实例的大小要小得多?

在Python中,与包含该类相同属性的字典相比,为类实例创建的字典很小:

import sys

class Foo(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

f = Foo(20, 30)
Run Code Online (Sandbox Code Playgroud)

使用Python 3.5.2时,以下调用getsizeof生成:

>>> sys.getsizeof(vars(f))  # vars gets obj.__dict__
96 
>>> sys.getsizeof(dict(vars(f))
288
Run Code Online (Sandbox Code Playgroud)

288 - 96 = 192 字节已保存!

但是,另一方面,使用Python 2.7.12,相同的调用返回:

>>> sys.getsizeof(vars(f))
280
>>> sys.getsizeof(dict(vars(f)))
280
Run Code Online (Sandbox Code Playgroud)

0 保存的字节数

在这两种情况下,词典显然具有完全相同的内容:

>>> vars(f) == dict(vars(f))
True
Run Code Online (Sandbox Code Playgroud)

所以这不是一个因素.此外,这也仅适用于Python 3.

那么,这里发生了什么?为什么__dict__Python 3中实例的大小如此之小?

python dictionary class python-3.x python-internals

16
推荐指数
1
解决办法
942
查看次数

什么是Python的序列协议?

Python使用魔术方法做了很多,其中大部分是一些协议的一部分.我熟悉"迭代器协议"和"数字协议",但最近偶然发现术语"序列协议".但即使经过一些研究,我也不确定"序列协议"是什么.

例如,C API函数PySequence_Check检查(根据文档)某个对象是否实现了"序列协议".该源代码表明这是一类,这不是一个字典,但实现__getitem__它的方法大致相同,在什么文件iter还指出:

[...]必须支持序列协议(__getitem__()整数参数从0开始的方法).[...]

但是开始的要求0不是"实施"的PySequence_Check.

然后还有的collections.abc.Sequence类型,它基本上是说实例必须实现__reversed__,__contains__,__iter____len__.

但是根据该定义,实现"序列协议"的类不一定是序列,例如序列具有长度的"数据模型"和抽象类garantuee.但是实现__getitem__(传递PySequence_Check)的类在使用时会抛出异常len(an_instance_of_that_class).

有人可以告诉我序列和序列协议之间的区别(如果除了阅读源代码之外还有协议的定义)以及何时使用哪个定义?

python cpython sequence python-internals

16
推荐指数
1
解决办法
1620
查看次数

有人可以解释一下staticmethod的源代码如何在python中工作

首先,我理解一般来说装饰工作是如何工作的.而且我知道@staticmethod在签名中剥离实例参数

class C(object):
    @staticmethod
    def foo():
        print 'foo'
C.foo    //<function foo at 0x10efd4050>
C().foo  //<function foo at 0x10efd4050>
Run Code Online (Sandbox Code Playgroud)

有效.

但是,我不明白如何staticmethod实现这一点的源代码.

在我看来,该包装方法时foostaticmethod,实例staticmethod被实例化,那么一些神奇的发生,使C.foo()合法的.

那么......那些魔法会发生什么?做了staticmethod什么?

我知道关于SO的巨大话题,staticmethods但没有一个能解决我的疑虑.但也许我没有点击魔术关键词.如果是的话,请告诉我.

对于寻找staticmethod源代码的人,请参阅https://hg.python.org/cpython/file/c6880edaf6f3/Objects/funcobject.c

python static-methods decorator python-internals python-decorators

15
推荐指数
1
解决办法
1617
查看次数

对相同对象的慢等式评估(x == x)

有没有什么理由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.arraypandas.Seriestypes,结果有意无法转换为boolean,因为它不清楚自然语义应该是什么(False意味着容器是空的,还是意味着它中的所有项都是False?).

但是在这里,python不需要做任何事情,因为 …

python python-3.x python-internals

15
推荐指数
1
解决办法
273
查看次数

Python 3.11 对象像槽一样轻吗?

经过Mark Shannon对Python对象的优化,普通对象和带槽的对象有什么不同吗?据我所知,在正常用例中进行此优化后,对象没有字典。新的 Python 对象是否已经完全不需要使用槽了?

python slots python-internals python-3.11

15
推荐指数
1
解决办法
586
查看次数