`
iluoxuan
  • 浏览: 579854 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

从C/C++程序员角度看Python的动态类型

 
阅读更多

 

从C/C++程序员角度看Python的动态类型

IN: C/C++|PYTHON

102010

Python是一种功能强大且完善的动态高级语言,目前被广泛地应用在计算机开发的各个领域。作为动态语言,Python的一个特点就是它支持动态类型(Dynamic Typing)和强类型(Strong Typing)。

动态类型是指在编写代码的过程中,程序员不需要将某个变量声明为某种类型,而是解释器根据变量的赋值动态地分配内存、赋值并将该变量绑定到对象上。它不同于静态类型(Static Typing),后者对于从事C、C++、Java、C#等面向对象语言开发的人来说,再熟悉不过了。静态类型语言在声明变量的时候,需要指定该变量的类型,从而编译器在遇到该类型的对象时,会分配对应的空间并且赋值。让我们来看两个例子:

Python语言:
var = "string" #不需要指定变量var的类型,赋值即可 
var = 123      #可直接指向其他类型的对象,不需要转换对象类型
 
C++语言:
string str = "string"//需要指定变量的类型,编译器将为其分配内存空间 
str = 1;               //Error: string类没有重载整数的赋值

从上述例子中我们可以看出,在Python里类型并不与变量绑定,变量只是对象的一个别名,一个变量可以赋予任何类型的对象值——事实上Python的处理也是如此:类型与对象进行绑定,变量名只是对象的一个表示,在表达式中变量名将被展开成为对象进行求值。而C++等静态类型语言则不同,类型与变量绑定,当出现该变量时,编译器会根据变量的类型进行求值,程序员不能轻易地将不同类型的值赋予该变量。

强类型指的是运算符或者函数调用的合法与否依赖于操作数或者参数的类型是否为预期类型。比如"23" + 1这样的表达式就不被强类型语言接受。

Python的值传递方式是全局by-ref,这点与C#及Java类似。接下来本文就将以C/C++程序员的角度理解Python的动态类型机制。

前文中曾经提到,在Python中,类型并不与变量绑定,一个类型绑定一个对象,那么解释器在碰到一个变量的时候要如何解析该变量的类型和值呢?答案是通过给一个对象赋以额外的信息。在Python中,我们可以将一个对象看作是一个结构体:

C++语言:
typedef struct{ 
    Type* type
    int   refCount
    char* obj
} PyObj;

该结构体分成三个部分:type,指向一个类型对象,该对象表明当时对象的类型(在Python中,所有的值都是对象,包括类型、函数等);refCount,表示该对象的引用次数,当该对象的引用次数为0的时候,GC将会自动回收内存空间;obj,真正对象存放的地方。我猜测,其他动态类型语言的实现细节从整体上看应该也是如此布局。也正是由于在动态类型语言中,解释器要知道一个变量所指向对象的类型,必须先从变量所指的地址得到该对象的类型,再对该对象进行一系列的操作,因此效率相对于静态类型语言而言要低。因为静态类型语言的编译器维护一张符号表,在表中记录着变量对应的类型,可以很方便地将相应操作直接转变为机器码或者字节码,而不用在运行时检测对象类型,效率会提高许多。

那么Python的引用语义是如何实现的呢?答案同C++类似,使用指针机制,然而Python中变量并没有其绑定的类型,这点与void指针很像。我们都知道,在C/C++中如何解析一个指针所指向内存的内容是通过该指针的类型来完成的,而void指针可以指向任意一块内存空间,只是编译器不知道该如何解析而已。在Python中类似,在前文的例子中我们可以得到一个void指针var,对该变量的操作则是如前如述通过与对象绑定的额外的类型信息获得的。知道了这点之后就可以很容易地理解Python的共享引用:

1) 共享引用和In-place修改

观察这么一段代码:

>>> a = 3 
>>> b = a

此时变量a和b指向的是同一块内存地址:即整数3这个对象,转换成对应的C++代码可以是:

void *a = &3 // 此处3是常量,而Python中3是一个对象,注意区别 
void *b = a

从C++代码中很容易就得出a、b所指向地址相同的结论。因此在Python中处理共享引用一个可更改对象(如List、Dictionary和Set)时要特别小心,例如:

>>> L1 = [2, 3, 4]   # A mutable object 
>>> L2 = L1          # Make a reference to the same object 
>>> L1[0] = 24       # An in-place change 
>>> L1               # L1 is different 
[24, 3, 4] 
>>> L2               # But so is L2! 
[24, 3, 4]

由于L1、L2指向的同样一块内存空间,因此对L1的修改同样会引起L2指向对象的变化,可以使用将引用语义转换至拷贝语义来规避这种潜在的语义错误:

>>> L1 = [2, 3, 4] 
>>> L2 = L1[:]       # Make a copy of L1 
>>> L1[0] = 24 
>>> L1 
[24, 3, 4] 
>>> L2               # L2 is not changed 
[2, 3, 4]

2) 对象比较

在C++中,比较运算符“==”在其操作数为指针时,返回的结果是两个指针对指向的地址是否相同,当其操作数为对象时,则是比较数值是否相等或者根据重载的运算符的行为来定义。而在Python中,由于其引用语义实际是通过指针的机制来实现,对于比较两个变量的行为就要特别注意。一般地,==运算符比较的是两个变量的值是否相等,例如:

>>> L = [1, 2, 3] 
>>> M = [1, 2, 3]    # M and L reference different objects 
>>> N = L            # N and L reference the same object
 
>>> L == M           # Same value 
True 
>>> L == N           # Same value 
True

在讨论共享引用的时候我们说过,N和L指向的是同一内存地址,因此无论Python中==运算符的语义为何,得到的结果都应该是True,而从比较L和M这两个虽然指向内容一样,但是对象的地址却不同的例子中我们可以得到==运算符的确切语义。那么如果想知道两个变量是否指向同一个对象应该如何编写代码呢?答案是使用is表达式:

>>> L is M           # Different objects! 
False 
>>> L is N           # Same object 
True

 

总结:

本文尝试从C/C++程序员熟悉的指针角度,简略地探讨了Python中动态类型的实现机制,分析了对象的内存布局,变量的共享引用机制。

分享到:
评论

相关推荐

    1. C++程序员python速成.ppt

    作为 C++ 程序员,学习 Python 的基础语法和数据类型是非常必要的。本文将对 Python 的基础语法和数据类型进行详细的介绍。 一、程序结构 Python 的程序结构与 C++ 略有不同。Python 不需要入口函数,而是从上到下...

    C/C++与Python混编的详细文件

    总结,C/C++与Python混编涉及的知识点包括C++的面向对象编程、动态链接库的创建、Python的ctypes库使用、数据类型转换、异常处理、内存管理和性能优化等。通过这种方式,开发者可以充分利用C/C++的高性能特性和...

    python-3.90 文档 手册 中文版.chm

    Python 3.9.0 文档 欢迎!这里是 Python 3.9.0 的中文文档。 按章节浏览文档: Python 3.9 有什么新变化? 或显示自 2.0 以来的全部新变化 ...从这里看起 ...安装和使用 Python ...给 C/C++ 程序员的参考

    python-3.86 文档 手册 中文版.chm

    Python 3.8.6 文档 欢迎!这里是 Python 3.8.6 的中文文档。 按章节浏览文档: Python 3.8 有什么新变化? 或显示自 2.0 以来的全部新变化 ...从这里看起 ...Python安装和使用 ...给 C/C++ 程序员的参考手册

    Python 3.7.3rc1 中文官方文档

    欢迎!这里是 Python 3.7.3rc1 的中文文档。 按章节浏览文档: Python 3.7 有什么新变化?...给 C/C++ 程序员的示例教程 Python/C API 接口 给 C/C++ 程序员的参考手册 常见问题 经常被问到的问题(答案也有!

    zeal离线文档,包含C/C++/Boost/cmake/python

    总的来说,这个压缩包提供了C/C++、Boost、cmake和Python的离线文档,覆盖了从底层系统编程到高级应用开发的广泛领域。无论你是初学者还是资深开发者,这些资源都能为你的工作带来便利,帮助你在编程之路上不断进步...

    Python概述:C++程序员眼中的Python1

    在C++程序员看来,Python是一种截然不同的编程语言,它以其简洁的语法和动态类型特性著称。这篇概述主要关注的是C++程序员如何理解和适应Python的基本概念。 首先,Python脚本的运行方式与C++有所不同。在命令行中...

    大公司是如何做信息安全管理的 |程序员注意事项 |Java/Python/C语言/C++等项目管理

    大公司是如何做信息安全管理的__程序员注意事项__Java_Python_C语言_C++等项目管理

    程序员宝库,开源社区GitHub到底该怎么玩 |如何玩转Github |Java/Python/C语言/C++开源项目聚集地

    程序员宝库,开源社区GitHub到底该怎么玩__如何玩转Github__Java_Python_C语言_C++开源项目聚集地

    Python C++ and SWIG

    这种方法使得 Python 程序员可以在需要的地方调用 C 或 C++ 的库函数,而无需对整个程序架构进行大规模重构。 - **SWIG 的作用**:SWIG 能够自动生成用于连接 C/C++ 库的 Python 接口文件。这些接口文件可以被编译...

    MATLAB C/C++, Fortran, Java, and Python API Reference

    《MATLAB C/C++, Fortran, Java, and Python API 参考手册》是MATLAB公司发布的一份技术文档,旨在为使用C/C++, Fortran, Java和Python编程语言与MATLAB进行接口开发的用户提供详细指南。该参考手册覆盖了如何在这些...

    C/C++/python中文手册

    这些语言各有特点,C语言以其高效、底层和简洁性著称,C++则在C的基础上引入了面向对象编程的概念,而Python则以其易读性强、语法简洁、丰富的库支持和强大的科学计算能力而广受欢迎。以下是对标题和描述中涉及的...

    YouCompleteMe安装教程+配置文件(支持c/c++/python)

    YouCompleteMe(简称YCM)是一款高效、智能的代码补全引擎,尤其在C/C++和Python等语言的开发中,它以其强大的自动完成功能深受程序员喜爱。在Ubuntu操作系统下,YCM的安装过程相对简单,但为了充分发挥其效能,还...

    python3.5.2中文资料.chm

    纯中文帮助文档,chm格式,带搜索功能 Python 3.5.2 文档 欢迎 !这是 Python 3.5.2 的文档,最后更新于 2016 年 8 月 13 日。...给C/C++ 程序员的教程 Python/C API C/C + + 程序员参考手册 常见问题解答

    eclipse for c/c++

    Eclipse for C/C++ 是一个强大的集成开发环境(IDE),专为C和C++程序员设计,提供了丰富的功能和工具,以提升开发效率和代码质量。Eclipse IDE for C/C++ 是 Eclipse 社区的一个核心项目,它基于开放源码的 Eclipse...

    Python 3.10.4 文档(官方中文html版)

    * Python/C API 接口 - 给 C/C++ 程序员的参考手册 * 常见问题 - 经常被问到的问题(答案也有!) * 索引和表格: - 全局模块索引 - 快速查看所有的模块 * 总目录 - 所的函数,类,术语 * 术语对照表 - 解释最重要...

    C/C++手册模板库大全2020最新版

    《C/C++手册模板库大全2020最新版》是一个综合性的开发资源,旨在为C++和C语言开发者提供全面、最新的参考资料。这个CHM(Compiled HTML Help)文件包含了丰富的编程信息,涵盖C++和C语言的基础语法、标准库、模板库...

    python-3.7.4-docs-html.tar.bz2

    给 C/C++ 程序员的示例教程 Python/C API 接口 给 C/C++ 程序员的参考手册 常见问题 经常被问到的问题(答案也有!) 索引和表格: 全局模块索引 快速查看所有的模块 总目录 所的函数,类,术语 术语表 解释最...

    python,c/c++,java,nodejs,php,go 本地代码运行

    标题中的“python,c/c++,java,nodejs,php,go 本地代码运行”表明这是一个支持多种编程语言本地执行的工具或框架。它旨在提供一个统一的平台,使得开发者可以在本地计算机上方便地运行和测试这些语言编写的代码。下面...

    将Python嵌入到C_C++应用程序中的编程方法.zip

    虽然Python的动态性质可能导致性能损失,但通过预编译Python代码(如使用`pyc`文件)和使用`PyCapsule`或`ctypes`库来调用C/C++函数,可以显著提高性能。 九、实例应用 这种技术广泛应用于科学计算、图形用户界面...

Global site tag (gtag.js) - Google Analytics