python确定变量类型_Python如何确定变量的类型?

CPython的动态、运行时调度(与Java的静态编译时调度相比)只是Java比纯CPython快的原因之一:Java中有jit编译、不同的垃圾收集策略、本地类型(如int、double)与CPython中不可变数据结构的存在等等。在

我前面的superficial experiments已经表明,动态调度只负责大约30%的运行-你不能用这个来解释某些重要因素的速度差异。在

为了使这个答案不那么抽象,让我们看一个例子:def add(x,y):

return x+y

查看字节码:

^{pr2}$

它给出了:2 0 LOAD_FAST 0 (x)

2 LOAD_FAST 1 (y)

4 BINARY_ADD

6 RETURN_VALUE

我们可以看到在字节码的级别上,x和{}是整数还是浮点数或其他东西没有区别-解释器不关心。在

Java的情况完全不同:int add(int x, int y) {return x+y;}

以及float add(float x, float y) {return x+y;}

将导致完全不同的操作码,并且调用调度将在编译时发生-根据编译时已知的静态类型选择正确的版本。在

通常的CPython解释器不必知道确切的参数类型:内部有一个基“类/接口”(显然C中没有类,所以它被称为“协议”,但是对于知道C++或java”接口的人来说,它可能是正确的心智模型,从中派生出所有其他类。这个基类称为PyObject和here is the description of its protocol.。只要函数是这个协议/接口的一部分,CPython解释器就可以调用它,而不知道确切的类型,并且调用将被分派给正确的实现(很多类似于C++中的“虚”函数)。在

在纯Python方面,似乎变量没有类型:a=1

a="1"

但是,在内部,a有一个类型,它是PyObject*,这个引用可以绑定到一个整数(1)和一个unicode字符串("1"),因为它们都是从PyObject中“继承”的。在

CPython解释器不时地试图找出引用的正确类型,同样对于上面的例子-当它看到BINARY_ADD-opcode时,following C-code将被执行:case TARGET(BINARY_ADD): {

PyObject *right = POP();

PyObject *left = TOP();

PyObject *sum;

...

if (PyUnicode_CheckExact(left) &&

PyUnicode_CheckExact(right)) {

sum = unicode_concatenate(left, right, f, next_instr);

/* unicode_concatenate consumed the ref to left */

}

else {

sum = PyNumber_Add(left, right);

Py_DECREF(left);

}

Py_DECREF(right);

SET_TOP(sum);

if (sum == NULL)

goto error;

DISPATCH();

}

在这里,解释器查询两个对象是否都是unicode字符串,如果是这种情况,则使用一个特殊的方法(可能更有效,因为它试图在适当的地方更改不可变的unicode对象,请参见这个SO-answer),否则工作被分派到PyNumber-协议。在

显然,解释器还必须知道创建对象时的确切类型,例如,a="1"或{}使用了不同的“类”,但正如我们所看到的,它不是唯一的地方。在

因此,解释器在运行时转换类型,但大多数情况下它不必这么做-目标可以通过动态调度来实现。在

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值