标签: cpython

为什么这个 LCG 在 Python 2.7 中比在 Python 3.x 中快得多?

这是 Python 中的一个简单的线性同余生成器

def prng(n):
    # https://en.wikipedia.org/wiki/Lehmer_random_number_generator
    while True:
        n = n * 48271 % 0x7fffffff
        yield n

g = prng(123)
for i in range(10**8):
    next(g)

assert next(g) == 1062172093
Run Code Online (Sandbox Code Playgroud)

Python 2.7 比任何版本的 Python 3.x 都快。在 Linux 上生成 100M 项:

python2.7 g.py   14.60s user 0.65s system 99% cpu 15.260 total
python3.6 g.py   18.70s user 0.00s system 99% cpu 18.711 total
python3.7 g.py   18.10s user 0.04s system 99% cpu 18.193 total
python3.8 g.py   19.22s user 0.02s system 99% cpu …
Run Code Online (Sandbox Code Playgroud)

python performance cpython biginteger unsigned-integer

4
推荐指数
1
解决办法
318
查看次数

PYTHON:*函数*中的双下划线前缀参数

下面是在builtins.pyi


def max(__arg1: _T, __arg2: _T, *_args: _T, key: Callable[[_T], SupportsLessThan]) -> _T:

Run Code Online (Sandbox Code Playgroud)

我确实知道名称修饰的含义,并且知道名称修饰将影响类定义字段中的每个“__xxx”标识符。

所以我有三个问题:

  • 为什么参数“__arg1”“__arg2”使用“__xxx”模式而参数“key”不使用;
  • 函数参数或本例中专门使用的“__xxx”模式的功能和用途是什么;
  • 我觉得很难找到名称修改的实现,你能告诉我它在 cpython 源代码中的位置吗?

非常感谢。

进一步的工作:

def wat1(__a):
    def wat2(__b):
        return __b, __a
    return __a

print(wat1.__code__.co_varnames)
print(wat1.__code__.co_cellvars)
dis.dis(wat1)
Run Code Online (Sandbox Code Playgroud)

输出(linux python==3.10.8):

('__a', 'wat2')
('__a',)

21           0 LOAD_FAST                0 (__a)
              2 RETURN_VALUE

22           0 LOAD_FAST                0 (__b)
              2 LOAD_DEREF               0 (__a)
              4 BUILD_TUPLE              2
              6 RETURN_VALUE


Run Code Online (Sandbox Code Playgroud)

python cpython

4
推荐指数
1
解决办法
230
查看次数

巨大的 cpython switch case 语句移到哪里了?

不确定这是否偏离主题,但不知道有什么更好的地方可以问。其中cpython有一个非常巨大的switch case语句用于执行每个操作码。此开关盒先前已放置在_PyEval_EvalFrameDefault函数中。链接在这里。switch case 语句从这里开始。这是 cpython 的核心部分,每个对 cpython 内部结构感兴趣的人可能都会详细探索它。最近我在找它,但没有找到。在这个版本中_PyEval_EvalFrameDefault我找不到它。比上一篇短多了。我什至尝试通过在 IDE 中搜索操作码来找到此 switch 语句。但即便如此也无助于找到它在哪里。任何了解最新 cpython 开发变化的人都可以帮助我吗?提前致谢。

python cpython

4
推荐指数
1
解决办法
201
查看次数

关于python函数/方法调用有什么静态的吗?

询问有关反思的问题时,我问:

很好的答案.但说myobject.foo()和之间有区别x = getattr(myobject, "foo"); x();.即使它只是化妆品.在第一个中,foo()是静态编译的.在第二种情况下,字符串可以通过多种方式生成. - 乔1小时前

得到了答案:

呃,马铃薯/马铃薯...在python中,niether是静态编译的,所以它们或多或少相当. - SWeko 1小时前

我知道Python对象的成员存储在字典中,并且一切都是动态的,但我假设给出了以下代码:

class Thing():
  def m(self):
    pass

t = Thing()
Run Code Online (Sandbox Code Playgroud)

生成.pyc时,以下代码会以某种方式静态编译:

t.m()
Run Code Online (Sandbox Code Playgroud)

即编译器知道地址m(),因此在运行时没有点绑定.那个或运行时会缓存后续查找.

虽然这总是涉及到字典:

meth = getattr(t, "m")
meth()
Run Code Online (Sandbox Code Playgroud)

是否所有调用都被视为字典中的字符串查找?或者这两个例子实际上是相同的吗?

python binding cpython dynamic-binding

3
推荐指数
1
解决办法
400
查看次数

C(P)ython或D中的多平台gui应用程序

我非常喜欢D(2)语言,并希望将它用于多平台GUI应用程序,但我发现它的生态系统还没有完全发展.从Linux迁移到(Free)PC-BSD之后,我发现在端口中甚至没有准备好64位编译器,并且不确定是否有任何GUI库(QtD,gtkD,wxD)已准备好用于严肃的项目,我们希望尽快开始项目.

Otoh,我之前被推荐尝试使用Python,这是成熟的,有很多工具,GUI库等等但是有关于速度的问题 - 我们必须使用一个C lib来计算Ephemeris并编写几个可以使用该C-lib的库.

然而,对于Cython来说这可能是一个很好的(完美的)工作,所以我的问题是你如何考虑在Python(Qt,EFL)中编写GUI部分并使用Cython来处理性能关键的东西(绑定外部C lib并编写我们自己的图书馆)而不是(等待)D为严肃的项目做好准备?

python user-interface d cpython cython

3
推荐指数
2
解决办法
1375
查看次数

多处理模块是否修复了CPython多核用法?

在CPython中,线程模块不使用多个内核,因为它使用全局解释器锁.但是我最近发现标准库中的多处理模块据说可以回避GIL.所以我认为使用该模块可以在CPython中正确使用多个核心,但我想知道我是否正确.

我需要编写一个需要很好地利用多个内核的应用程序,但这不是性能关键所以我可以用Python编写它,但我需要知道这个模块是否允许我使用多个内核?

python multithreading cpython multiprocessing python-3.x

3
推荐指数
1
解决办法
361
查看次数

为什么CPython的hash(-1)!= -1

int.__hash__简单地返回值似乎是合理的。果然,这似乎是CPython实现它的方式:

>>> hash(1)
1
>>> hash(2)
2
>>> hash(123456789)
123456789
>>> hash(-123456789)
-123456789
Run Code Online (Sandbox Code Playgroud)

好吧,这对于所有大多数整数x都成立吗?

>>> [x for x in range(-10000, 10000) if hash(x) != x]
[-1]
Run Code Online (Sandbox Code Playgroud)

??

>>> hash(-1)
-2
Run Code Online (Sandbox Code Playgroud)

为什么是-1该规则的例外?

python hash cpython

3
推荐指数
1
解决办法
107
查看次数

在cpython中的_math.c中的ln2 const值

我在git(第25行)看_math.c:

#if !defined(HAVE_ACOSH) || !defined(HAVE_ASINH)
static const double ln2 = 6.93147180559945286227E-01;
static const double two_pow_p28 = 268435456.0; /* 2**28 */
Run Code Online (Sandbox Code Playgroud)

我注意到ln2值与ln2的wolframalpha值不同.(光头部分是差异)

ln2 = 0.693147180559945 286227(cpython)

ln2 = 0.693147180559945 3094172321214581(wolframalpha)

ln2 = 0.693147180559945 309417232121458(维基百科)

所以我的问题是为什么会有区别?我错过了什么?

python cpython

3
推荐指数
1
解决办法
448
查看次数

Python如何在内部存储日期时间?

我发现_datetimemodule.c哪个似乎是正确的文件,但我需要一些帮助,因为C不是我的力量.

>>> import datetime
>>> import sys
>>> d = datetime.datetime.now()
>>> sys.getsizeof(d)
48
>>> d = datetime.datetime(2018, 12, 31, 23, 59, 59, 123)
>>> sys.getsizeof(d)
48
Run Code Online (Sandbox Code Playgroud)

因此,时区不知道的日期时间对象需要48个字节.看着PyDateTime_DateTimeType,它似乎是一个PyDateTime_DateType和一个PyDateTime_TimeType.也许_PyDateTime_BaseTime呢?

通过查看代码,我的印象是每个字段都存储了一个组件YYYY-mm-dd HH:MM:ss,意思是:

  • 年份:例如int(例如int16_t16位)
  • 月:例如 int8_t
  • 一天:例如 int8_t
  • 小时:例如 int8_t
  • 分钟:例如 int8_t
  • 第二:例如 int8_t
  • 微秒:例如 uint16_t

但是,这将是2*16 + 5*8 = 72位= 9字节而不是48字节,因为Python告诉我.

我对datetime内部结构的假设在哪里错了?我怎么能在代码中看到这个?

(我想这可能在Python实现之间有所不同 - 如果是这样,请关注cPython)

c python memory datetime cpython

3
推荐指数
1
解决办法
354
查看次数

CPython:为什么+ = for strings会改变string变量的id

Cpython优化字符串增量操作,在为字符串初始化内存时,程序为其留下额外的扩展空间,因此,在递增时,原始字符串不会复制到新位置.我的问题是为什么字符串变量的id会发生变化.

>>> s = 'ab'
>>> id(s)
991736112104
>>> s += 'cd'
>>> id(s)
991736774080
Run Code Online (Sandbox Code Playgroud)

为什么string变量的id改变了.

python cpython python-3.x python-internals

3
推荐指数
2
解决办法
161
查看次数