标签: python-internals

如何获取PyObject的引用计数?

如何PyObject从C++ 获取a的引用计数?

有功能Py_INCREF,Py_DECREF并增加/减少它,但我没有找到任何返回对象的引用计数的函数.

我需要它用于调试目的.

c c++ python python-c-api python-internals

12
推荐指数
1
解决办法
3447
查看次数

str(list)如何工作?

为什么str(list)返回我们在控制台上看到列表的方式?str(list)工作怎么样?(对CPython代码的任何引用str(list))?

>>> x = ['abc', 'def', 'ghi']
>>> str(x)
"['abc', 'def', 'ghi']"
Run Code Online (Sandbox Code Playgroud)

要获得原始列表,str(list)我必须:

>>> from ast import literal_eval
>>> x = ['abc', 'def', 'ghi']
>>> str(x)
"['abc', 'def', 'ghi']"
>>> list(str(x))
['[', "'", 'a', 'b', 'c', "'", ',', ' ', "'", 'd', 'e', 'f', "'", ',', ' ', "'", 'g', 'h', 'i', "'", ']']
>>> literal_eval(str(x))
['abc', 'def', 'ghi']
Run Code Online (Sandbox Code Playgroud)

为什么不list(str(list))转动str(list)回原来的名单?

或者我可以使用:

>>> eval(str(x))
['abc', 'def', 'ghi']
Run Code Online (Sandbox Code Playgroud)

literal_eval …

python string eval list python-internals

12
推荐指数
2
解决办法
2万
查看次数

是否保证在创建类时定义"__module__"?

我正在阅读一些基本上看起来像这样的代码:

class Foo(object):
    class_name = __module__.replace('_', '-')
Run Code Online (Sandbox Code Playgroud)

对我来说,这看起来很奇怪(__module__那是什么?)所以我去了看python 数据模型.快速搜索显示这__module__是类对象和函数对象的属性.但是,__module__全局命名空间中没有可用的东西(只需要通过查看它并观察NameError结果就可以轻松验证...).

我决定将其用于实现特定的行为,但作为最后的检查,我决定使用其他实现进行测试.事实证明,此代码以1执行

  • Cpython 2.7.6
  • Cpython 3.4.0
  • jython 2.5.3
  • PyPy 2.2.1(Python 2.7.3)

我的问题是这种行为是否实际上是在语言参考中的任何地方定义的.我不确定我为什么__module__要这样做,但是我可以安全地依赖于类创建命名空间,还是所有实现者都决定以同样的方式执行此操作?

1所有linux,但我怀疑这很重要......

python python-internals

12
推荐指数
1
解决办法
1264
查看次数

为什么OrderedDict键视图比较顺序不敏感?

为什么OrderedDict键视图比较顺序不敏感?

>>> from collections import OrderedDict
>>> xy = OrderedDict([('x', None), ('y', None)])
>>> yx = OrderedDict([('y', None), ('x', None)])
>>> xy == yx
False
>>> xy.keys() == yx.keys()
True
Run Code Online (Sandbox Code Playgroud)

OrderedDict键视图应该表现得像OrderedSet,但它的行为相同dict.keys(就像通常一样set).

python2中的"问题"相同:

>>> xy.viewkeys() == yx.viewkeys()
True
Run Code Online (Sandbox Code Playgroud)

它们是不同的类型,(odict_keys是子类dict_keys)

>>> type(xy.keys())
odict_keys
>>> type({}.keys())
dict_keys
Run Code Online (Sandbox Code Playgroud)

并且已经存在一个可以轻易使用的顺序敏感键比较,但它显然仅用作对odict丰富比较的后检查.

这是设计决定还是错误?如果这是一个设计决定,我在哪里可以找到理由的讨论?

python ordereddictionary python-3.x python-internals

12
推荐指数
1
解决办法
1718
查看次数

在导入的__init__.py中,导入的行为会有所不同

__init__.py运行文件时,导入时的行为似乎与导入时的行为不同.

如果我们有以下文件:

run.py:

import test
Run Code Online (Sandbox Code Playgroud)

test/b.py:

class B(object):
    pass
Run Code Online (Sandbox Code Playgroud)

test/__init__.py:

from b import B
print B
print b
Run Code Online (Sandbox Code Playgroud)

如果我们运行,__init__.py我们会得到一个错误:

% python test/__init__.py

<class 'b.B'>
Traceback (most recent call last):
  File "test/__init__.py", line 6, in <module>
  print b
NameError: name 'b' is not defined
Run Code Online (Sandbox Code Playgroud)

但如果我们run.py这样做,那么我们不会:

% python run.py 
<class 'test.b.B'>
<module 'test.b' from '~/temp/test/b.py'>
Run Code Online (Sandbox Code Playgroud)

我希望这种行为是一样的.为什么这样做?

这只有在我们这样做的情况下才有效__init__.py.要是我们:

mv __init__.py a.py
touch __init__.py
Run Code Online (Sandbox Code Playgroud)

并使run.py:

import test.a
Run Code Online (Sandbox Code Playgroud)

然后我们得到了错误.

python python-import python-2.7 python-internals

12
推荐指数
1
解决办法
660
查看次数

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

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

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
查看次数

如何在内部存储和映射变量名称?

我阅读/sf/answers/1380476751/,似乎在CPython中,变量只是与引用相关联的名称.

声明x = 5有几件事情:

  1. 创建一个值为5的int对象(如果已存在,则找到该对象)
  2. 创建名称x(或与最后一个标记为'x'的对象取消关联)
  3. 对新(或找到)的int对象的引用计数增加1
  4. 名称x与创建(或找到)值为"5"的对象相关联.

但是,我仍然不清楚内部如何实现变量.

即:

  1. 创建名称x(或与最后一个标记为'x'的对象取消关联);

那个名字也不会占用内存空间吗?sys.sizeof(x)等于sys.sizeof(5),我得到的sys.sizeof(x)只能返回相关引用的大小,但那么名称的大小是x多少?

  1. 名称x与创建(或找到)值为'5'的对象相关联

这是如何在内部实施的?我认为在高级别它可以用a完成dict,其中键是变量名(str?),值是与之关联的引用.

python variables cpython python-internals

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

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
查看次数

对象相等(`==`)的默认行为在哪里定义?

根据object.__eq__()文档,默认(即在object类中)实现==如下:

True if x is y else NotImplemented
Run Code Online (Sandbox Code Playgroud)

仍然遵循的文档NotImplemented,我推断这NotImplemented意味着 Python 运行时将尝试以相反的方式进行比较。y.__eq__(x)即如果x.__eq__(y)返回则尝试NotImplemented(在运算符的情况下==)。

现在,在 python 3.9 中False打印以下代码:True

class A:
   pass
print(A() == A())
print(bool(NotImplemented))
Run Code Online (Sandbox Code Playgroud)

所以我的问题如下:文档在哪里提到了NotImplemented在上下文中的特殊行为__eq__

PS:我在CPython 源代码中找到了答案,但我想这必须/应该在文档中的某个位置。

python python-datamodel python-internals

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