Python语言学习笔记
2010-09-23 星期四 寒流+雨
中秋有三天假,感觉老长似的,专门跑出枫林晚借了本《Learning Python》的书,准备假期看看。厄,现在是假期的中间,书确实是看完了,700页左右的英文书,前后花了3个小时左右,当然只是看,没有编码。
发现自己现在看语言方面的书真是太快了,因为语言的东西确实相差无几。特别是语法方面的细节,在看书的时候我几乎就是一扫而过。比如,如何定义一个类,它的if-else,for循环语法,etc。因为这些只是实现上的差异(语法定义上的差异),跟这个语言的功能与编程范式无关——当然,我承认,语法很影响一个人对一门语言的选择与偏爱,它就像人的相貌一样。
但是,一门的语言最重要的差别不在于语法,而在于其它几个重要的方面。这里直接给出vczh同学的结论,因为我同意他的观点:
计算机语言作为一个计算的定义,在我们开发脚本引擎之前需要先进行了解。对于目前流行的若干种语言,我们可以抽象出一组正交属性来描述他们。
一、命令式与描述式
一门语言是命令式或者描述式取决于这门语言是用来告诉计算机怎样做还是做什么的。举个例子,SQL和Prolog是描述式语言,而C++、C#等则是命令式语言。我们在使用SQL的时候告诉服务器的是我们需要满足什么条件的数据项,而不是告诉服务器我们需要通过什么计算来获得自己所需要的数据项。描述式的语言的优点在于其可读性好。C# 3.0为数据查询加入了LINQ让我们可以在C#中书写类似SQL的代码查询数据。
另一个比较模糊的例子则是Haskell。Haskell很难区分是命令式语言还是描述式语言。因为从形式上来说我们告诉编译器的是我们想做什么而不是我们想怎么做,但是Haskell给我们的工具的粒度太细以至于我们为了告诉编译器做什么的同时仍然需要考虑一个问题是如何被解决的。
二、按值计算与惰性计算
惰性计算的语言很少出现以至于可能很多人都不知道"原来语言可以是这个样子的"。惰性计算的精神是不去执行没用的代码。什么是没用的代码呢?只要是这段代码的值不对外界产生任何影响,譬如没有往屏幕、硬盘或者是其他什么地方写点什么数据,就是没有用的。当然,至于这段代码中间做了些什么事情那是不管的。
举一个比较简单的例子,假设现在有如下代码:
function PrintAndReturn(Message,Result)
{
Print(Message);
return Result;
}
function DoSomething(BoolA,BoolB)
{
If(BoolA || BoolB) Print("!");
}
DoSomething(PrintAndReturn("Hello",true),PrintAndReturn("World",false));
DoSomething函数传入两个参数,都是布尔类型的。如果这两个参数其中有一个是true的话那么就往屏幕上打出一个感叹号。PrintAndReturn函数接受两个参数,往屏幕上打出第一个参数,函数返回第二个参数。
对于一门按值计算的语言,也就是我们平常见到的那种,执行的结果是"HelloWorld!"。因为为了调用DoSomething我们需要首先获得两个布尔值。
对于一门惰性计算的语言,执行的结果是"Hello!"。因为DoSomething在对BoolA || BoolB进行求值的时候计算了BoolA,发现是true,于是BoolB这个参数就没有用了,因此PrintAndReturn("World",false)也就不会执行了,导致"World"不会显示在屏幕上。
当然,对于上面举的这个例子来说,这种语言有着惰性计算的属性并不合理。一门语言为了不具有二义性,在存在惰性计算的同时必须对自己的类型系统进行改造。关于这方面的资料可以查阅Haskell语言中Monad的原理。Haskell作为一门惰性计算的语言,在不关心求值顺序的同时,仍然保证结果的一致性。上面这个例子,如果程序对||的求值是从右操作数开始的话,那么输出的结果就变成"HelloWorld!"了。惰性计算的好处在于可以在逻辑上表达无穷大的对象,而在实际的计算过程中并不需要将这个无穷大的对象一次性计算出来,而是需要哪里算到哪里。举个例子:
function MakeArray(Index)
{
return [Index]++MakeArray(Index+1);
}
function Sum(Array,Count)
{
Result=0;
for i=0 to Count-1
Result+=Array[i];
return Result;
}
Print(Sum(MakeArray(1),10));
在这个例子中,Index代表一个只有一个元素的数组,其内容是Index,而++操作符将两个数组接起来。于是MakeArray(1)就产生了一个无穷长的数组,其内容是1,2,3,4,...。Sum计算数组的前若干个数字的和。对于一门惰性计算的语言,这个例子将输出55,因为我们需要的仅仅是前10个数字,因此MakeArray只需要递归10次就自动挺下来了。而对于一门按值计算的语言来说,将发生死循环而出现不可停机现象。
三、强类型、弱类型与无类型
一门语言是无类型当且仅当一个固定的符号的类型可以在运行时改变。譬如如下代码:
TheVariable=1;
TheVariable="I am a string!";
第一行创建了一个int类型的TheVariable变量,而第二行则将TheVariable修改成了字符串类型。一门无类型语言的对象类型可以是数值、字符串、数组、类、闭包、函数指针等等的东西。
只要不是无类型的,那必然就是强类型或者弱类型的了。强类型与弱类型的分界线比较明显。只要存在隐式类型转换的语言则是弱类型的,譬如C语言能将int隐式转换为double。不存在隐式转换的语言也是存在的,譬如Haskell。在Haskell里面不能创建一个实数类型的名字但是绑定一个整数的值上去。因为整数跟实数的类型是不同的,而且不存在隐式转换。
四、函数与闭包
凡是支持闭包的语言必然是支持函数的,但是并不是所有支持函数的语言都支持闭包,而且也并不是所有的语言都有函数。Windows的批处理文件所能理解的语言就是不支持函数的语言的一个例子。
至于什么是闭包呢?闭包就是可以保持函数执行的上下文的一种强大的函数指针。举个例子:
function Add(a)
{
return function(b)
{
Return a+b;
}
}
Inc=Add(1);
Inc10=Add(10);
Print(Inc(5));
Print(Inc10(5));
这个例子将输出6和15。执行Inc=Add(1);的时候,Add函数返回了一个新的函数,这个函数接受参数b并返回参数a和b相加的结果。返回的这个函数将参数a记了下来。所以Inc和Inc10在执行的时候,虽然执行的是同一个函数,但是这个函数所看到的a确是不同的。a的值的不同代表着Inc和Inc10执行函数的不同。这也就是闭包是可以保持函数执行的上下文的由来了。当然,一门不支持闭包的语言是不能允许上面这种写法的。
这四种属性是区分语言特征的重要属性。至于一门语言是否支持面向对象的写法或者支持元编程或者泛型之类的东西,并不是十分重要的特性,虽然我们使用起来的感觉非常不同。
不过话说回来,虽然说语言的编程范式(如面向对象或者面向过程),跟语言本身不是特别有关系(用面向过程的语言,一样可以编写面向对象的代码),但是这是非常大的语法糖,所以也是一个非常重要的考虑方面。异常处理和泛型编程也是一样的。
另外需要补充几点的是:1. 语言本身的内存管理也是一个非常重要的考虑方面,即是否支持垃圾回收和引用计数。2. 语言的动态程度,这个与vczh的第三点有点重叠,但是支持多大程度的元编程确实是个问题。3. 参数和返回值的传递方式(按值传递还是按引用传递,etc.)。4. 作用域规则
貌似有点扯远了。。回到主题。学习Python,其实最主要是掌握它的对象视图。下面是笔者的总结。
在Python中,所有的变量都是引用(指针,地址,名字,标签),不包含任何类型信息,这就是前面vczh同学说的无类型,指的就是变量(Variable)是无类型的。但是基本上目前任何一门语言都是有类型的(整型,字符型,etc.)。Python也不例外。它的类型信息是跟对象(Object)挂钩的。变量指向创建的对象。在Python中,一切都是对象,包括函数,甚至“类型”本身就是一个对象。它是一门基于对象的语言(all values are objects),同时支持面向对象的编程范式。
Figure 9-3. Python’s major built-in object types, organized by categories. Everything is a type of object in Python, even the type of an object! The type of any object is an object of type “type.”
In fact, even types themselves are an object type in Python: a call to the built-in function type(X) returns the type object of object X. Type objects can be used for manual type comparisons in Python if statements.
One note on type names: as of Python 2.2, each core type has a new built-in name added to support type customization through object-oriented subclassing: dict, list, str, tuple, int, long, float, complex, unicode, type, and file (file is a synonym for open). Calls to these names are really object constructor calls, not simply conversion functions, though you can treat them as simple functions for basic usage.
另外,由于Python中变量是无类型的,对象是有类型的,所以它采用了将“变量赋值”作为“变量声明”的做法。因为赋值操作其实就是创建(可能会复用)一个对象,然后将这个对象的地址信息赋值给这个变量,这样就可以通过该变量引用这个对象了。所以:
>>> a=3
Python编译器将做如下事情:
1. Create an object to represent the value 3.(这里python会推断出3其实是一个整数,所以其类型信息是Int。)
2. Create the variable a, if it does not yet exist.
3. Link the variable a to the new object 3.
Each object also has two standard header fields: a type designator used to mark the type of the object, and a reference counter used to determine when it’s OK to reclaim the object.
根据值来推断变量类型,其实是很有道理的,在静态类型语言中如C,对复制语句做类型是否一致检查,依据的也是这样的。所以是有道理的。只不过将赋值语句作为声明,混淆了赋值语句的含义,所以当你真正需要是修改一个变量值(使其指向另一个对象),而不是重新定义一个新变量时,需要一些特殊的标识来告诉编译器。如:
X = 88 # Global X
def func():
global X # Global X: outside def
X = 99
func()
print X # Prints 99
The scope of a variable (where it can be used) is always determinged by where it is assigned in your source code, and has nothing to do with which functions call which. If a variabl is assigned inside a def, it is local to that function; if assigned outside a def, it is global to the entire file. We call this lexical scoping because variable scopes are determined entired by the locations of the variables in the source code of your program files, not by function calls.
因为对象与类型信息挂钩(包括操作),所以在这些脚本语言中,支持这样的操作:3.times { print "Ruby! " },9.downto(1) {|n| print n } ,etc.
相关推荐
Python 语言学习笔记
计算机二级python题库 全国计算机等级考试二级教程——Python语言 学习笔记
适合了解c或者c++语言的入门python学习,章节层次清晰地全面讲解语法知识,系统性梳理了各种语法和示例,学完基本可以入门
这个仓库是笔者的一个学习笔记,主要总结一些比较重要的知识点,希望对大家有所帮助。
1.2 Python语言的发展历程 1.3 Python语言的主要特点 1.4 Python应用场景 1.5 Python环境搭建 1.6 第一个Python程序 1.7 集成开发工具 2、Python语法基础 2.1 Python中的输入输出函数 2.2 Python中的注释 ...
Python3.0学习笔记, 安装完Python之后(我本机的版本是2.5.4),打开IDLE(Python GUI) , 该程序是Python语言解释器,你写的语句能够立即运行.我们写下一句著名的程序语句。
(完整版)Python基础学习笔记 (完整版)Python基础学习笔记全文共69页,当前为第1页。(完整版)Python基础学习笔记全文共69页,当前为第1页。Python 基础学习笔记 (完整版)Python基础学习笔记全文共69页,当前为第1页。...
Python基础入门教程,适合Python初学者,文档内容包括, 目录 前言 i 第一章 程序 1 1.1 程序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 什么是调试 . . . . . . . . . . . . . . . ....
python 爬虫学习笔记
python学习笔记用案例,欢迎下载..............
python-学习笔记
python学习笔记汇总
《全国计算机等级考试二级教程——Python语言》(2018年版)学习笔记.zip 《全国计算机等级考试二级教程——Python语言》(2018年版)学习笔记.zip 《全国计算机等级考试二级教程——Python语言》(2018年版)学习...
GDAL-Python库学习笔记
Java python 个人学习笔记
包含学习Python前的准备工作,环境搭建,以及详细的语法入门,...配套视频课程是:阿里云培训中心-Python语言基础,感兴趣的小伙伴,可以配合视频服用,效果更佳!因为这里面只是我的学习笔记,并没有视频看的直观。
基于python的学习笔记(附代码),包含python语言,标准库,扩展库和附录四个部分
最流行的编程入门语言python高手学习笔记.docx
Python核心编程(第二版) + Python语言入门 + Python 学习笔记