烧饼的技术乱讲
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 [...]
I'm now a graduate student of Computer Applied Technology in Tongji University. I like Computer Graphics, Web 2.0, Magic, Music and am partially a geek. This blog is about C++, algorithm, cg, comments and other things I may get in touch with in the near future. Hope everyone enjoy this little site. Contact me: 4everlove.xu AT gmail.com