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...
以下是基于提供的文件内容,对于Python语言学习笔记中涵盖知识点的详细解读: 一、基本语法示例 Python的基本语法类似于英语句子,它使用缩进来定义代码块。例如,使用print()函数打印字符串"helloworld"。另外,...
全国计算机等级考试二级教程——Python语言》(2018年版)学习笔记全国计算机等级考试二级教程——Python语言》(2018年版)学习笔记全国计算机等级考试二级教程——Python语言》(2018年版)学习笔记全国计算机等级...
在Python环境搭建部分,资料详细介绍了Python语言的起源、发展和主要特性,为读者提供了一个全面的背景了解。接着,它指导读者如何安装Python解释器,并创建第一个简单的"Hello, World!"程序,这是每个编程新手的...
全国计算机等级考试二级教程-Python语言的学习笔记涵盖了Python编程的基础知识和应试策略,是为备考计算机二级Python考试的学生量身定制的参考资料。这个学习笔记旨在帮助考生掌握Python语言的关键概念,提高编程...
这份笔记涵盖了Python的基础语法、数据结构、控制流、函数、模块化编程、面向对象编程等多个方面,旨在帮助初学者系统地理解和应用Python语言。 1. **基础语法**:Python以其简洁明了的语法著称,例如缩进替代大...
这个仓库是笔者的一个学习笔记,主要总结一些比较重要的知识点,希望对大家有所帮助。
《全国计算机等级考试二级教程——Python语言》(2018年版)学习笔记.zip 《全国计算机等级考试二级教程——Python语言》(2018年版)学习笔记.zip 《全国计算机等级考试二级教程——Python语言》(2018年版)学习...
Python3.0学习笔记, 安装完Python之后(我本机的版本是2.5.4),打开IDLE(Python GUI) , 该程序是Python语言解释器,你写的语句能够立即运行.我们写下一句著名的程序语句。
本文档是一份详尽的Python基础学习笔记,适用于初学者,涵盖了Python编程语言的方方面面。笔记内容从基础的环境配置到面向对象的高级特性,详尽阐述了Python的核心概念和技术要点。 在Linux基础部分,笔记从终端...
#### 一、Python语言特性 - **解释型语言**: Python是一种解释型语言,这意味着代码可以一行一行地被执行而无需事先进行编译过程。这种特性使得Python非常适合快速开发和测试。 #### 二、Python第三方库安装方法 1....
### Python学习笔记知识点详解 ...通过以上知识点的梳理,我们可以看出,“Python学习笔记.pdf”涵盖了Python语言的基础到高级的多个方面,是一份全面且实用的学习材料,适合初学者到有经验的开发者阅读和参考。
Python是一种广泛使用的高级编程语言,它以其简洁明了的语法和强大的功能而受到众多开发者的喜爱。...这对于进一步深入学习Python语言及其在数据分析、网络编程、机器学习等领域的应用具有重要的指导意义。
"Python学习笔记用案例"这个标题表明这是一份包含了实际应用示例的学习资料,旨在帮助初学者通过实例来理解和掌握Python编程。描述中的“欢迎下载”暗示这份资料是公开共享的,鼓励大家学习和交流。 在Python的学习...
Python基础入门教程,适合Python初学者,文档内容包括, 目录 前言 i 第一章 程序 1 1.1 程序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 什么是调试 . . . . . . . . . . . . . . . ....
首先,在Python语言基础方面,笔记涵盖了虚拟机、类型与对象、名字空间、内存管理、编译和执行等基础知识。虚拟机概念是指Python程序是在虚拟机环境中运行的,这使得Python具备了跨平台的特性。类型与对象部分则解释...
在这份详尽的学习笔记中,作者从基础概念出发,逐步引导读者深入理解Python编程语言的核心要素。 在笔记的开篇,皮大庆首先阐释了什么是程序,以及为何调试对程序开发至关重要。程序作为解决问题的逻辑步骤的集合,...
"Python学习笔记+源码练习"是一个适合初学者的资源包,旨在帮助你从零基础开始掌握Python编程。这份资料包含了理论知识讲解和实际代码实践,使学习过程更为直观和实用。 在学习Python时,笔记是关键,它们可以帮助...