零基础入门学习Python(第2版)
本书配套资源和网站支持
- PPT课件请在清华大学出版社网站本书页面下载。
第1版前言
- Life is short. You need Python。——Bruce Eckel
- 有人说,完成相同的一个任务,使用汇编语言需要1000行代码,使用C语言需要500行,使用Java只需要100行,而使用Python,可能只要20行就可以了。
- Python可以说是一门“万金油”语言,在Web应用开发、系统网络运维、科学与数字计算、3D游戏开发、图形界面开发、网络编程中都有它的身影。
第1章 就这么愉快地开始吧
- 只有勇敢地割掉与时代发展不相符的瑕疵部分,才能缔造出真正的完美体验!
- 安装Python非常容易,可以在它的官网找到最新的版本并下载,地址是http://www.python.org。
1.2 从IDLE启动Python
- IDLE是一个Python shell,shell的意思就是“外壳”,是一个通过输入文本与程序交互的途径。
- >>>提示符的含义是:Python已经准备好了,在等着你输入指令呢!
1.3 失败的尝试
- 井号起到的作用是注释,也就是说,井号后边的内容是给人们看的,并不会被当作代码运行。
1.5 为什么会这样
- print("I love python\n" * 3)
- print("I love python\n" +3):
第2章 用Python设计第一个游戏
- 选择File→New File命令(也可以直接使用Ctrl+N快捷键,在很多地方这个快捷键都是新建一个文件的意思)。
- Tab按键的作用:(1)缩进。(2)IDLE会提供一些建议,例如,输入“pr TAB”会显示所有可能的命令供参考。
- 好多编程语言都用大括号来表示循环、条件等的作用域,而在Python里是没有的。在Python中,只需要用适当的缩进来表示即可。
2.2 缩进
- 缩进取而代之,它是Python的灵魂,缩进的严格要求使得Python的代码显得非常精简并且有层次
- 如果在正确的位置输入冒号(:),IDLE会在下一行自动进行缩进。
2.3 BIF
- BIF就是Built-in Functions,内置函数的意思。
第3章 成为高手前必须知道的一些基础知识
- 当为一个值起名字的时候,它将会存储在内存中,我们把这块内存称为变量(variable)。
- 变量为什么不叫“恒量”而叫“变量”?正是因为它是可变的!
- 变量名可以包括字母、数字、下画线,但变量名不能以数字开头
3.2 字符串
- 字符串也称为文本,文本和数字是截然不同的。
- 要告诉Python你在创建一个字符串,就要在字符两边加上引号,可以是单引号或双引号,
- 转义符号(\)对字符串中的引号进行转义,这样Pytho
3.3 原始字符串
- 原始字符串的使用非常简单,只需要在字符串前边加一个英文字母r即可:
3.4 长字符串
- 只需要使用三重引号字符串("""内容""")
- 切记:编程中我们使用的所有标点符号都应该是英文的!
3.6 条件分支
- 在Python中,用两个连续等号表示等于号,用单独一个等号表示赋值。那不等于呢?嗯,不等于这个有点特殊,用感叹号和一个等号搭配来表示(!=)。
3.7 初识循环
- Python的逻辑操作符可以将任意表达式连接在一起,并得到一个布尔类型的值。布尔类型只有两个值:True和False,就是真与假。
- 使用and逻辑操作符将左右两个条件串起来的时候,只有当两者同时成立,结果才能是True;否则均为False。
3.8 引入外援
- random模块就是与生成随机数相关的模块,这个模块里边有一个函数为randint(),它会返回一个随机的整数
3.9 闲聊数据类型
- Python的变量是没有类型的
- 带了引号的,无论是双引号还是单引号或者是三引号,都是字符串;而不带引号的,就是数字。字符串相加称为拼接;数字相加就会得到两个数字的和:
- 整型说白了就是平时所见的整数
- Python区分整型和浮点型的唯一方式,就是看有没有小数点。
- 布尔类型只有True和False两种情况
- 布尔类型可以当作整数来对待,True相当于整型值1,False相当于整型值0
- 把布尔类型当成1和0来参与运算这种做法是不妥的,容易引起代码的混乱。
- int()的作用是将一个字符串或浮点数转换为一个整数:
- 如果是浮点数转换为整数,Python会采取“截断”处理,就是把小数点后的数据直接砍掉,而不是四舍五入。
- str()的作用是将一个数或任何其他类型转换成一个字符串
- Python其实提供了一个函数,可以明确告诉我们变量的类型,这就是type()函数:
- isinstance()函数有两个参数:第一个是待确定类型的数据;第二个是指定一个数据类型。
3.10 常用操作符
- + - * / % ** //
- 地板除法的概念是:计算结果取比商小的最大整型值(也就是舍弃小数,取整的意思)。
- 使用地板除法,无论是整型还是浮点型,都将舍弃小数部分。
- 百分号(%)表示求余数的意思
- 先乘、除,后加、减,如有括号先运行括号里边的。
- 双星号(**),也称为幂运算操作符
- 幂运算操作符比其左侧的一元操作符优先级高,比其右侧的一元操作符优先级低。
- 比较运算符包括: < <= > >= == !=
- 逻辑操作符包括:and or not
- or操作符只需要左边或者右边任意一边为真,结果都为真;只有当两边同时为假,结果才为假
- not操作符是一个一元操作符,它的作用是得到一个和操作数相反的布尔类型的值:
第4章 了不起的分支和循环
- Python是面向对象的编程
4.2 快速上手
- 分支的含义是“只有符合条件,才会去做某事”;而循环则是“只要符合条件,就持续做某事”。
4.3 避免“悬挂else”问题
- 缩进是Python的灵魂,缩进的严格要求使得Python的代码显得非常精简并且有层次,这种强制的规范使得代码必须被正确地对齐。
4.4 条件表达式(三元操作符)
- 三元操作符语法: a = x if 条件 else y表示当条件为True的时候,a被赋值为x,否则被赋值为y。
4.5 断言
- assert这个关键字翻译过来就是“断言”,当这个关键字后边的条件为假的时候,程序自动崩溃并抛出AssertionError异常。
- 一般来说,可以用它在程序中置入检查点,当需要确保程序中的某个条件一定为真才能让程序正常工作的话,assert关键字就非常有用了。
4.6 while循环语句
- 只要条件为真,while循环会一直重复执行一段代码,这段代码称为循环体。
- 如果上面代码的循环体中缺少i += 1语句,循环将永远也不会退出(除非将程序强制关闭),也称为死循环
4.7 for循环语句
- 所谓可迭代对象,就是指那些元素可以被单独提取出来的对象
- range()是一个BIF函数,它可以为指定的整数生成一个数字序列(可迭代对象)
4.8 break语句
- break语句的作用是终止当前循环,跳出循环体。
4.9 continue语句
- continue语句,它的作用是跳出本轮循环并开始下一轮循环
4.10 else语句
- while和for循环语句的后面也可以加上一个else语句,表示当条件不成立的时候执行的内容
- break语句使得程序跳出循环,但却不会执行else中的内容。
第5章 列表、元组和字符串
- 数组允许把一些相同类型的数据挨个儿摆在一起,然后通过下标进行索引。
- 由于Python的变量没有数据类型,所以Python的“数组”可以同时存放不同类型的变量。
- 创建一个列表非常简单,只需要使用中括号将数据包裹起来(数据之间用逗号分隔)就可以了。
- type()函数用于返回指定参数的类型,list即列表的意思。
- 可以看到这个列表里有整型、字符串、浮点型数据,甚至还可以包含另一个列表。
- 添加元素到列表中,可以使用append()方法:
- 因为append()并不是一个BIF,它是属于列表对象的一个方法。中间这个“.”,
- 如果希望同时添加多个数据,可以使用extend()方法向列表末尾添加多个元素:
- extend()事实上是使用一个列表来扩充另一个列表,所以它的参数是另一个列表。
- insert()方法中代表位置的第一个参数还支持负数,表示与列表末尾的相对距离:
- 通过索引值可以直接获取列表中的某个元素:
- 使用len()函数获取该列表的长度(元素个数),再减1就是这个列表最后一个元素的索引值
- random的choice()方法可以从一个非空的序列(如列表)中随机获取一个元素。
- 从列表中删除元素,可以有三种方法实现:remove()、pop()和del。
- pop()方法是将列表中的指定元素“弹”出来,也就是取出并删除该元素的意思,它的参数是一个索引值:
- del语句在Python中的用法非常丰富,不仅可以用来删除列表中的某个(些)元素,还可以直接删除整个变量:
- 如果省略了开始位置,Python会从0这个位置开始。同样道理,如果要得到从指定索引值到列表末尾的所有元素,把结束位置也省去即可。如果啥都没有,只有一个冒号,Python将返回整个列表的拷贝。
- 列表切片并不会修改列表自身的组成结构和数据,它其实是为列表创建一个新的拷贝(副本)并返回。
- 列表切片操作实际上还可以接受第三个参数,其代表的是步长,默认值为1。
- 将步长设置为-1,相当于将整个列表翻转过来。
- 同样会作用于原始列表的操作还有为切片后的列表赋值:
- 当列表包含多个元素的时候,默认是从第一个元素开始比较,只要有一个PK赢了,就算整个列表赢了。
- 乘号(*)也叫重复操作符
- 成员关系操作符就是in和not in:
- in和not in只能判断一个层次的成员关系
- count()方法的作用是统计某个元素在列表中出现的次数
- “懒”有时候确实是发明创新的原动力。
5.2 元组:戴上了“枷锁”的列表
- 元组和列表的最大区别是:元组只可读,不可写。
- 创建列表用的是中括号,而创建元组大部分时候使用的是小括号:
- tuple即元组的意思。
- 复制一个元组,通常可以使用切片来实现:
- 逗号(,)才是关键,小括号只是起到补充的作用。
- id()函数用于返回指定对象的唯一id值,这个id值可以理解为现实生活中的身份证,在同一生命周期中,Python确保每个对象的id值是唯一的。
- 删除整个元组,只需要使用del语句:
5.3 字符串
- 字符串与元组一样,都是属于“一言既出,驷马难追”的家伙。所以,一旦确定下来就不能再对它进行修改。如果非要这么做,仍然可以利用切片和拼接来实现:
- 这种通过拼接旧字符串的各个部分组合得到新字符串的方式,并不是真正意义上的修改字符串。原来的那个旧的字符串其实还在,只不过我们将变量名指向了拼接后的新字符串。旧的字符串一旦失去了变量的引用,就会被Python的垃圾回收机制释放掉。
- Python字符串的方法及含义
- casefold()方法用于将字符串中所有的英文字母修改为小写:
- 只要涉及字符串修改的方法,并不是修改原字符串,而是返回字符串修改后的一个拷贝。
- find(sub[,start[,end]])或index(sub[,start[,end]])方法用于查找sub参数在字符串中第一次出现的位置,如果找到了,返回位置索引值;如果找不到,find()方法会返回-1,而index()方法会抛出异常(注:异常是可以被捕获并处理的错误)
- split(sep=None, maxsplit=-1)方法用于拆分字符串:
- 格式化字符串,就是按照统一的规格去输出一个字符串。
- 但要注意的是,如果将位置参数和关键字参数综合在一起使用,那么位置参数必须在关键字参数之前,
- Python格式化符号及含义令
- 简单字符串连接时,直接使用加号(+),例如:full_name = prefix + name。 • 复杂的,尤其有格式化需求时,使用格式化操作符(%)进行格式化连接,例如:result = "result is %s:%d" % (name, score)。 • 当有大量字符串拼接,尤其发生在循环体内部时,使用字符串的join()方法无疑是最棒的,例如:result = "".join(iterator)。
- 格式化操作符的辅助命令
5.4 序列
- list()方法用于把一个可迭代对象转换为列表
- 所谓迭代,是重复反馈过程的活动,其目的通常是为了接近并达到所需的目标或结果。每一次对过程的重复被称为一次“迭代”,而每一次迭代得到的结果会被用来作为下一次迭代的初始值
- tuple()方法用于把一个可迭代对象转换为元组
- str()方法用于把obj对象转换为字符串
- len()方法前面已经使用过几次了,该方法用于返回sub参数的长度
- max()方法用于返回序列或者参数集合中的最大值
- 使用max()方法和min()方法都要保证序列或者参数的数据类型统一
- sum()方法用于返回序列iterable的所有元素值的总和
- 列表的内建方法sort()是实现列表原地排序;而sorted()是返回一个排序后的新列表。
- 列表的内建方法是原地翻转,而reversed()是返回一个翻转后的迭代器对象。
- enumerate()方法生成由二元组(二元组就是元素数量为2的元组)构成的一个迭代对象,每个二元组由可迭代参数的索引号及其对应的元素组成
- zip()方法用于返回由各个可迭代参数共同组成的元组
第6章 函数
- 在Python中创建一个函数用def关键字
- 在函数名后面要加上一对小括号。这对小括号是必不可少的
- 调用一个函数也非常简单,直接写出函数名加上小括号即可:
- 括号里放的就是函数的参数
- 参数就是使得函数可以实现个性化:
- 奥卡姆剃刀原理:如无必要,勿增实体
- 只需要在函数中使用关键字return,后面跟着的就是指定要返回的值。
- 如果返回了多个值,Python默认是以元组的形式进行打包。
- 也可以利用列表将多种类型的值打包到一块儿再返回。
6.2 灵活即强大
- 形参指的是函数定义的过程中小括号里的参数,而实参则指的是函数在被调用的过程中传递进来的参数。
- 函数的文档字符串可以通过特殊属性_ _doc_ _获取
- 当想使用一个BIF却又不确定其用法的时候,可以通过help()函数来查看函数的文档:
- 关键字参数其实就是在传入实参时明确指定形参的变量名,其特点就是参数之间不存在先后顺序
- 位置参数必须在关键字参数的前面
- 在定义函数的时候,位置参数必须在默认参数的前面,否则就会出错
- Python就是把标志为收集参数的参数们打包成一个元组。
- 如果在收集参数后面还需要指定其他参数,那么在调用函数的时候就应该使用关键参数来指定,否则Python就都会把实参都纳入到收集参数中。
- 建议大家如果定义的函数中带有收集参数,那么可以将其他参数设置为默认参数
- 星号(*)在形参中的作用是“打包”,而在实参中的作用则相反,起到“解包”的作用。
- 两个星号的收集参数表示为将参数们打包成字典的形式
6.3 我的地盘听我的
- 作用域是程序运行时变量可被访问的范围
- 全局变量拥有更大的作用域,因此在函数中可以访问到它们
- 如果在函数内部试图修改全局变量的值,那么Python会创建一个新的局部变量替代(名字与全局变量相同),但真正的全局变量是“不为所动”的,所以才有了上面的实现结果。
- 仍然觉得有必要在函数内部去修改这个全局变量,那么可以使用global关键字来达到目的。
- 内部函数整个作用域都在外部函数之内
- 在嵌套函数中,内部函数可以引用外部函数的局部变量:
- LEGB含义解释:• L-Local:函数内的名字空间。• E-Enclosing function locals:嵌套函数中外部函数的名字空间。• G-Global:函数定义所在模块的名字空间。• B-Builtin:Python内置模块的名字空间。那么变量的查找顺序依次就是L→E→G→B。
- 简言之:就是在嵌套函数的环境下,内部函数引用了外部函数的局部变量),那么内部函数就被认为是闭包。
- 如果在一个内部函数里(funY()就是这个内部函数)对在外部作用域(但不是在全局作用域)的变量进行引用(x就是被引用的变量,x在外部作用域funX()函数里面,但不在全局作用域里),则这个内部函数就是一个闭包。
- 因为闭包的概念是由内部函数而来,所以不能在外部函数以外的地方对内部函数进行调用
- 如果希望在内部函数里可以修改外部函数里的局部变量的值,可以使用nonlocal关键字告诉Python这不是一个局部变量,使用方式与global一样
- 闭包概念的引入是为了尽可能地避免使用全局变量,闭包允许将函数与其所操作的某些数据(环境)关联起来,这样外部函数就为内部函数构成了一个封闭的环境。
6.4 函数式编程
- 基本语法是使用冒号(:)分隔函数的参数及返回值:冒号的左边放置函数的参数,如果有多个参数,使用逗号(,)分隔即可;冒号右边是函数的返回值。
- filter()这个内置函数有两个参数:第一个参数可以是一个函数也可以是None,如果是一个函数的话,则将第二个可迭代对象里的每一个元素作为函数的参数进行计算,把返回True的值筛选出来;如果第一个参数为None,则直接将第二个参数中为True的值筛选出来。
6.5 递归
- 普通程序员用迭代,天才程序员用递归
- 递归,从原理上来说就是函数调用自身的行为。
- 压栈、弹栈、保存和恢复寄存器的栈操作,所以在这上面是非常消耗时间和空间的。
- 所以在写递归代码的时候,千万要记住口诀:递归递归,归去来兮!
第7章 字典和集合
- 字典是Python中唯一的映射类型
- 映射类型区别于序列类型,序列类型以数组的形式存储,通过索引的方式来获取相应位置的值,一般索引值与对应位置存储的数据是毫无关系的。
- 字典的使用非常简单,它有自己的标志性符号,就是用大括号({})定义。字典由“键”和“值”共同构成,每一对键值组合称为“项”。
- 也可以使用dict()内置函数来创建字典:
- 因为dict()函数的参数可以是一个序列(但不能是多个),所以要打包成一个元组(或列表)序列。
- 这里要注意的是,键的位置不能加上表示字符串的引号,否则会报错:
- 还有一种创建方法是直接给字典的键赋值,如果键已存在,则改写键对应的值;如果键不存在,则创建一个新的键并赋值
- 有别于序列,字典是不支持拼接和重复操作的:
- fromkeys()方法用于创建并返回一个新的字典,它有两个参数;第一个参数是字典的键;第二个参数是可选的,是传入键对应的值,如果不提供,那么默认是None。
- keys()用于返回字典中的键,values()用于返回字典中所有的值,那么,items()当然就是返回字典中所有的键值对(也就是项)。
- get()方法提供了更宽松的方式去访问字典项,当键不存在的时候,get()方法并不会报错,只是默默地返回了一个None,表示啥都没找到:
- 如果希望找不到数据时返回指定的值,那么可以在第二个参数设置对应的默认返回值:
- 如果不知道一个键是否在字典中,那么可以使用成员资格操作符(in或not in)来判断:
- pop()是给定键弹出对应的值,而popitem()是弹出一个项,这两个比较容易理解:
- setdefault()方法和get()方法有点相似,但是,setdefault()在字典中找不到相应的键时会自动添加:
7.2 集合:在我的世界里,你就是唯一
- 在Python 3里,如果用大括号括起一堆数字但没有体现出映射关系,那么Python就会认为这堆数据是一个集合而不是映射。
- 集合是无序的,也就是不能试图去索引集合中的某一个元素
- 创建集合有两种方法:一种是直接把一堆元素用大括号({})括起来;另一种是用set()内置函数。
第8章 永久存储
- close()方法用于关闭文件
- 1个中文字符占用2字节的空间
- readline()方法用于在文件中读取一整行,就是从文件指针的位置向后读取,直到遇到换行符(\n)结束:
- 使用'w'模式写入文件,此前的文件内容会被全部删除
- 如果要在原来的内容上追加,一定要使用'a'模式打开文件。
8.3 pickle:腌制一缸美味的泡菜
- 它几乎可以把所有Python的对象都转化为二进制的形式存放,这个过程称为pickling,那么从二进制形式转换回对象的过程称为unpickling。
- 利用pickle模块,不仅可以保存列表,事实上pickle还可以保存任何你能想象得到的东西。
9.2 try-except语句
- try语句检测范围内一旦出现异常,剩下的语句将不会被执行。
9.3 try-finally语句
- finally语句块中的内容就是确保无论如何都将被执行的内容。
9.5 丰富的else语句
- 只要try语句块里没有出现任何异常,那么就会执行else语句块里的内容。
11.2 对象=属性+方法
- 一个对象的特征称为“属性”,一个对象的行为称为“方法”
- 创建一个对象,也叫类的实例化
11.3 面向对象编程
- Python的self其实就相当于C++的this指针。
- 在Python中定义私有变量只需要在变量名或函数名前加上“_ _”两个下画线,那么这个函数或变量就会成为私有的了:
- 实际上在外部使用“_类名_ _变量名”即可访问两个下画线开头的私有变量了:
11.4 继承
- 被继承的类称为基类、父类或超类;继承者称为子类,一个子类可以继承它的父类的任何属性和方法。
- 如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性:
11.7 类、类对象和实例对象
- 如果属性的名字与方法名相同,属性会覆盖方法
13.4 _ _name_ _='_ _main_ _'
- 上面的代码确保只有单独运行p13_7.py时才会执行test()函数。