Python 3.5 学习笔记总结
Python3 基础整理笔记
首先知道几件事:
- YouTube,Quora,知乎,豆瓣都是用Python写的。包括Google、Yahoo等,甚至NASA(美国航空航天局)都大量地使用Python。
- Python拿来做爬虫最好用了(可以抓取接入教务系统信息之类的)。
- Python是著名的“龟叔”Guido van Rossum在1989年圣诞节期间,为了打发无聊的圣诞节而编写的一个编程语言。
- Python是用来编写应用程序的高级编程语言。
- 解释型语言
写操作系统,只能用C语言写;写手机应用,只能用Swift/Objective-C(针对iPhone)和Java(针对Android
),写3D游戏,最好用C或C++。但是Python有自己的特色,
Python适合开发哪些类型的应用呢?
首选是网络应用,包括网站、后台服务等等;其次是许多日常需要的小工具,包括系统管理员需要的脚本任务等等
Python基础知识
Python解释器
整个Python语言从规范到解释器都是开源的,存在多种Python解释器:
- CPython:这个解释器是用C语言开发的,所以叫CPython(使用最广)
- IPython:基于CPython之上的一个交互式解释器,IPython只是在交互方式上有所增强,执行代码功能和CPython完全一样
- PyPy:采用JIT技术,对Python代码进行动态编译(注意不是解释),所以可以显著提高Python代码的执行速度。Python代码在两种解释器下执行可能会有不同的结果。
- Jython:Jython是运行在Java平台上的Python解释器,可以直接把Python代码编译成Java字节码执行。
- ronPython:IronPython和Jython类似,只不过IronPython是运行在微软.Net平台上的Python解释器,可以直接把Python代码编译成.Net的字节码
==△请注意==,如果要和Java或.Net平台交互,最好的办法不是用Jython或IronPython,而是通过网络调用来交互,确保各程序之间的独立性。
第一个Python程序
- 命令行模式下敲命令python3进入Python交互模式
- 在Python交互模式下输入exit()退出
- 命令行模式和Python交互模式
请注意区分命令行模式和Python交互模式。在命令行模式下,可以执行python进入Python交互式环境,也可以执行python hello.py运行一个.py文件。
1 | print('hello, world') |
输入和输出
- 输出print()函数可以接受多个字符串、整数、计算结果:
1 | print('le petit prince', 'j'ai horreur des courants d'air, 'renant') |
- 输入input()函数,input(),可以让用户输入字符串,并存放到一个变量里。这个时候再输出
1
2name = input('please enter your name: ')
jooeys
1 | print('Hi,',name) |
编译器或者解释器就是负责把符合语法的程序代码转换成CPU能够执行的机器码,然后执行。Python也不例外。
Python语法
- 采用缩进方式(Tab设置4个空格或者4个空格)
- 用#注释
- 大小写敏感
1 | # print absolute value of an integer: |
数据类型与变量
- 整数
Python的整数没有大小限制计算机由于使用二进制,所以,有时候用十六进制表示整数比较方便,十六进制用0x前缀和0-9,a-f表示,例如:0xff00,0xa5b4c3d2,等等。1
1,100,-8080,0
- 浮点数
浮点数就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,比如,1.23x109和12.3x108是完全相等的。浮点数可以用数学写法,如但是对于很大或很小的浮点数,就必须用科学计数法表示,把10用e替代,1.23x109就是1.23e9,或者12.3e8,0.000012可以写成1.2e-5,等等。1
1.23,3.14,-9.01,
整数和浮点数在计算机内部存储的方式是不同的,整数运算永远是精确的(除法难道也是精确的?是的!),而浮点数运算则可能会有四舍五入的误差。Python的浮点数也没有大小限制,但是超出一定范围就直接表示为inf(无限大) - 字符串
字符串是以单引号’或双引号”括起来的任意文本
1 | 比如"I'm OK"包含的字符是I,',m,空格,O,K这6个字符。 |
想表示’用转义字符\来标识,\n表示换行,\t表示制表符,字符\本身也要转义,所以\表示的字符就是\。r’’表示’’内部的字符串默认不转义,允许用’’’…’’’的格式表示多行内容,
- 布尔值
True、False表示布尔值(请注意大小写)
布尔值可以用and、or和not运算。1
2
3and运算是与运算,只有所有都为True,and运算结果才是True
or运算是或运算,只要其中有一个为True,or运算结果就是True
not运算是非运算,它是一个单目运算符,把True变成False,False变成True - 空值
None是一个特殊空值,None不能理解为0 - 变量
变量名必须是大小写英文、数字和_的组合,且不能用数字开头,比如:
1 | a =1 |
变量本身类型不固定的语言称之为动态语言,与之对应的是静态语言。
静态语言在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错。例如Java是静态语言,赋值语句如下(// 表示注释):
1 | int a = 123; // a是整数类型变量 |
理解变量在计算机内存中的表示:
1 | a = 'ABC' |
Python解释器干了两件事情:
- 在内存中创建了一个’ABC’的字符串;
- 在内存中创建了一个名为a的变量,并把它指向’ABC’。
常量
常量就是非变量,Python中通常全部大写的变量名表示常量:
1 | PI=3.1415926 |
Python中有两种除法:
1 | >>> 10/3 |
求余
1 | >>>10%3 |
字符编码
计算机只能处理数字,所以文本需要编码。最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最大的整数就是255(二进制11111111=十进制255),如果要表示更大的整数,就必须用更多的字节。比如两个字节可以表示的最大整数是65535,4个字节可以表示的最大整数是4294967295。
美国人发明了计算机所以最早只有127个字符(大小写英文字母、数字和一些符号)被编码到计算机里,这个编码表被称为ASCII编码,比如大写字母A的编码是65,小写字母z的编码是122。
1 | 中国把中文编到GB2312里, |
在多语言混合的文本中,显示出来会有乱码。因此,Unicode应运而生,Unicode把所有语言都统一到一套编码里,最常用的是用两个字节表示一个字符。
主要是理解ASCII、Unicode和UTF-8的关系,其中
- 用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件。
- 浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器。
1 | <meta charset="UTF-8" /> |
Python 3版本中,字符串是以Unicode编码的,也就是说,Python的字符串支持多语言。
1 | >>> print('支持多语言abc') |
对于单个字符的编码,Python提供了ord()函数获取字符的整数表示,chr()函数把编码转换为对应的字符:
1 | >>> ord('A') |
如果知道字符的整数编码,还可以用十六进制这么写str:
1 | >>> '\u4e2d\u6587' |
两种写法完全是等价的
Python对bytes类型的数据(ytes的每个字符都只占用一个字节)用带b前缀的单引号或双引号表示:
1 | x = b'ABC' #占用3个bytes |
以Unicode表示的str通过encode()方法可以编码为指定的bytes,例如:
1 | >>> 'ABC'.encode('ascii') |
纯英文的str可以用ASCII编码为bytes,内容是一样的,含有中文的str可以用UTF-8编码为bytes。含有中文的str无法用ASCII编码,因为中文编码的范围超过了ASCII编码的范围,Python会报错。
在bytes中,无法显示为ASCII字符的字节,用\x##显示。
反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法
1 | >>> b'ABC'.decode('ascii') |
如果bytes中包含无法解码的字节,decode()方法会报错:
1 | >>> b'\xe4\xb8\xad\xff'.decode('utf-8') |
如果bytes中只有一小部分无效的字节,可以传入errors=’ignore’忽略错误的字节:
1 | >>> b'\xe4\xb8\xad\xff'.decode('utf-8', errors='ignore') |
要计算str包含多少个字符,可以用len()函数:
1 | >>> len('ABC') |
len()函数计算的是str的字符数,如果换成bytes,len()函数就计算字节数:
1 | >>> len(b'ABC') |
可见,1个中文字符经过UTF-8编码后通常会占用3个字节,而1个英文字符只占用1个字节。
在操作字符串时,我们经常遇到str和bytes的互相转换。为了避免乱码问题,应当始终坚持使用UTF-8编码对str和bytes进行转换。
由于Python源代码也是一个文本文件,所以,当你的源代码中包含中文的时候,在保存源代码时,就需要务必指定保存为UTF-8编码。当Python解释器读取源代码时,为了让它按UTF-8编码读取,我们通常在文件开头写上这两行:
1 | #!/usr/bin/env python3 |
第一行注释是为了告诉Linux/OS X系统,这是一个Python可执行程序,Windows系统会忽略这个注释;
第二行注释是为了告诉Python解释器,按照UTF-8编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码。
申明了UTF-8编码并不意味着你的.py文件就是UTF-8编码的,必须并且要确保文本编辑器正在使用UTF-8 without BOM编码
输出格式化
在Python中,采用的格式化方式和C语言是一致的,用%实现,举例如下:
1 | >>> 'Hello, %s' % 'world' |
你可能猜到了,%运算符就是用来格式化字符串的。在字符串内部,%s表示用字符串替换,%d表示用整数替换,有几个%?占位符,后面就跟几个变量或者值,顺序要对应好。如果只有一个%?,括号可以省略。
常见的占位符有:
1 | 占位符 替换内容 |
其中,格式化整数和浮点数还可以指定是否补0和整数与小数的位数:
1 | >>> print('%2d-%02d' % (3, 1)) |
%s永远起作用,它会把任何数据类型转换为字符串
1 | >> 'Age: %s. Gender: %s' % (25, True) |
需要转义的话,用%%来表示一个%:
1 | >>> 'growth rate: %d %%' % 7 |
format()
另一种格式化字符串的方法是使用字符串的format()方法,它会用传入的参数依次替换字符串内的占位符{0}、{1}……,不过这种方式写起来比%要麻烦得多:
1 | >>> 'Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125) |
小明的成绩从去年的72分提升到了今年的85分,请计算小明成绩提升的百分点,并用字符串格式化显示出’xx.x%’,只保留小数点后1位:
1 | s1=72 |
小明,今年成绩比去年提升了:18.1 %
当str和bytes互相转换时,需要指定编码。最常用的编码是UTF-8。Python当然也支持其他编码方式,比如把Unicode编码成GB2312:
1 | >>> '中文'.encode('gb2312') |
1 | s = 'Python-中文' |
但这种方式纯属自找麻烦,如果没有特殊业务要求,请牢记仅使用UTF-8编码。
使用list和tuple
- list
Python内置的一种数据类型是列表:list。list是一种有序的集合,可以随时添加和删除其中的元素。
比如,列出班里所有同学的名字,就可以用一个list表示:
1 | >>> classmates = ['Michael', 'Bob', 'Tracy'] |
- 变量classmates就是一个list。用len()函数可以获得list元素的个数:
1 | >>> len(classmates) |
当索引超出了范围时,Python会报一个IndexError错误,所以,要确保索引不要越界,记得最后一个元素的索引是len(classmates) - 1。
如果要取最后一个元素,除了计算索引位置外,还可以用-1做索引,直接获取最后一个元素:
1 | >>> classmates[-1] |
当然,倒数第4个就越界了。
- list是一个可变的有序表,所以,可以往list中追加元素到末尾,用append()方法:
1 | >>> classmates.append('Adam') |
- 要删除list末尾的元素,用pop()方法:
1 | >>> classmates.pop() |
要把某个元素替换成别的元素,可以直接赋值给对应的索引位置:
1 | >>> classmates[1] = 'Sarah' |
要注意s只有4个元素,其中s[2]又是一个list,如果拆开写就更容易理解了:
1 | >>> p = ['asp', 'php'] |
- 要拿到’php’可以写p[1]或者s[2][1],因此s可以看成是一个二维数组,类似的还有三维、四维……数组,不过很少用到。
如果一个list中一个元素也没有,就是一个空的list,它的长度为0:
1 | >>> L = [] |
- 另一种有序列表叫元组:tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改,比如同样是列出同学的名字:
1 | >>> classmates = ('Michael', 'Bob', 'Tracy') |
现在,classmates这个tuple不能变了,它也没有append(),insert()这样的方法。其他获取元素的方法和list是一样的,你可以正常地使用classmates[0],classmates[-1],但不能赋值成另外的元素。
不可变的tuple有什么意义?因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。
tuple的陷阱:当你定义一个tuple时,在定义的时候,tuple的元素就必须被确定下来,比如:
1 | >>> t = (1, 2) |
但是,要定义一个只有1个元素的tuple,如果你这么定义:
1 | >>> t = (1) |
定义的不是tuple,是1这个数!这是因为括号()既可以表示tuple,又可以表示数学公式中的小括号,这就产生了歧义,因此,Python规定,这种情况下,按小括号进行计算,计算结果自然是1。
所以,只有1个元素的tuple定义时必须加一个逗号,,来消除歧义:
1 | >>> t = (1,) |
Python在显示只有1个元素的tuple时,也会加一个逗号,,以免你误解成数学计算意义上的括号。
最后来看一个“可变的”tuple:
1 | >>> t = ('a', 'b', ['A', 'B']) |
这个tuple定义的时候有3个元素,分别是’a’,’b’和一个list。不是说tuple一旦定义后就不可变了吗?怎么后来又变了?
别急,我们先看看定义的时候tuple包含的3个元素:
1 | t = ('a', 'b', ['A', 'B']) |
当我们把list的元素’A’和’B’修改为’X’和’Y’后,tuple
1 | t = ('a', 'b', ['X', 'Y']) |
表面上看,tuple的元素确实变了,但其实变的不是tuple的元素,而是list的元素。tuple一开始指向的list并没有改成别的list,所以,tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。即指向’a’,就不能改成指向’b’,指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!
理解了“指向不变”后,要创建一个内容也不变的tuple怎么做?那就必须保证tuple的每一个元素本身也不能变。
1 | L = [ |
list和tuple是Python内置的有序集合,一个可变,一个不可变。根据需要来选择使用它们。
条件判断
条件判断
计算机之所以能做很多自动化的任务,因为它可以自己做条件判断。
比如,输入用户年龄,根据年龄打印不同的内容,在Python程序中,用if语句实现:
1 | age = 20 |
根据Python的缩进规则,如果if语句判断是True,就把缩进的两行print语句执行了,否则,什么也不做。
也可以给if添加一个else语句,意思是,如果if判断是False,不要执行if的内容,去把else执行了:
1 | age = 3 |
注意不要少写了冒号:。
当然上面的判断是很粗略的,完全可以用elif做更细致的判断:
1 | age = 3 |
elif是else if的缩写,完全可以有多个elif,所以if语句的完整形式就是:
1 | if <条件判断1>: |
if语句执行有个特点,它是从上往下判断,如果在某个判断上是True,把该判断对应的语句执行后,就忽略掉剩下的elif和else,所以,请测试并解释为什么下面的程序打印的是teenager:
1 | age = 20 |
if判断条件还可以简写,比如写:
1 | if x: |
只要x是非零数值、非空字符串、非空list等,就判断为True,否则为False。
再议 input
最后看一个有问题的条件判断。很多同学会用input()读取用户的输入,这样可以自己输入,程序运行得更有意思:
1 | birth = input('birth: ') |
输入1982,结果报错:
1 | Traceback (most recent call last): |
这是因为input()返回的数据类型是str,str不能直接和整数比较,必须先把str转换成整数。Python提供了int()函数来完成这件事情:
1 | s = input('birth: ') |
再次运行,就可以得到正确地结果。但是,如果输入abc呢?又会得到一个错误信息:
1 | Traceback (most recent call last): |
原来int()函数发现一个字符串并不是合法的数字时就会报错,程序就退出了。
如何检查并捕获程序运行期的错误呢?后面的错误和调试会讲到。
练习
小明身高1.75,体重80.5kg。请根据BMI公式(体重除以身高的平方)帮小明计算他的BMI指数,并根据BMI指数:
1 | 低于18.5:过轻 |
用if-elif判断并打印结果:
1 | # -*- coding: utf-8 -*- |
小结
条件判断可以让计算机自己做选择,Python的if…elif…else很灵活。
条件判断从上向下匹配,当满足条件时执行对应的块内语句,后续的elif和else都不再执行。
python-if
循环
循环
要计算1+2+3,我们可以直接写表达式:
1 | >>> 1 + 2 + 3 |
要计算1+2+3+…+10,勉强也能写出来。
但是,要计算1+2+3+…+10000,直接写表达式就不可能了。
为了让计算机能计算成千上万次的重复运算,我们就需要循环语句。
Python的循环有两种,一种是for…in循环,依次把list或tuple中的每个元素迭代出来,看例子:
1 | names = ['Michael', 'Bob', 'Tracy'] |
执行这段代码,会依次打印names的每一个元素:
1 | Michael |
…循环就是把每个元素代入变量x,然后执行缩进块的语句。
再比如我们想计算1-10的整数之和,可以用一个sum变量做累加:
1 | sum = 0 |
如果要计算1-100的整数之和,从1写到100有点困难,幸好Python提供一个range()函数,可以生成一个整数序列,再通过list()函数可以转换为list。比如range(5)生成的序列是从0开始小于5的整数:
1 | >>> list(range(5)) |
range(101)就可以生成0-100的整数序列,计算如下:
1 | sum = 0 |
第二种循环是while循环,只要条件满足,就不断循环,条件不满足时退出循环。比如我们要计算100以内所有奇数之和,可以用while循环实现:
1 | sum = 0 |
在循环内部变量n不断自减,直到变为-1时,不再满足while条件,循环退出。
请利用循环依次对list中的每个名字打印出Hello, xxx!:
1 | L = ['Bart', 'Lisa', 'Adam'] |
- break
在循环中,break语句可以提前退出循环。例如,本来要循环打印1~100的数字:
1 | n = 1 |
上面的代码可以打印出1~100。
如果要提前结束循环,可以用break语句:
1 | n = 1 |
执行上面的代码可以看到,打印出1~10后,紧接着打印END,程序结束。
可见break的作用是提前结束循环。
- continue
在循环过程中,也可以通过continue语句,跳过当前的这次循环,直接开始下一次循环。
1 | n = 0 |
上面的程序可以打印出1~10。但是,如果我们想只打印奇数,可以用continue语句跳过某些循环:
1 | n = 0 |
执行上面的代码可以看到,打印的不再是1~10,而是1,3,5,7,9。
可见continue的作用是提前结束本轮循环,并直接开始下一轮循环。
- 小结
循环是让计算机做重复任务的有效的方法。
break语句可以在循环过程中直接退出循环,而continue语句可以提前结束本轮循环,并直接开始下一轮循环。这两个语句通常都必须配合if语句使用。
要特别注意,不要滥用break和continue语句。break和continue会造成代码执行逻辑分叉过多,容易出错。大多数循环并不需要用到break和continue语句,上面的两个例子,都可以通过改写循环条件或者修改循环逻辑,去掉break和continue语句。
有些时候,如果代码写得有问题,会让程序陷入“死循环”,也就是永远循环下去。这时可以用Ctrl+C退出程序,或者强制结束Python进程。
请试写一个死循环程序。
1 | a = 0 |
使用dict和set
Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。
举个例子,假设要根据同学的名字查找对应的成绩,如果用list实现,需要两个list:
- dic字典
1 | names = ['Michael', 'Bob', 'Tracy'] |
给定一个名字,要查找对应的成绩,就先要在names中找到对应的位置,再从scores取出对应的成绩,list越长,耗时越长。
如果用dict实现,只需要一个“名字”-“成绩”的对照表,直接根据名字查找成绩,无论这个表有多大,查找速度都不会变慢。用Python写一个dict如下:
1 | >>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85} |
dict是key-value存储方式,在放进去的时候,必须根据key算出value的存放位置,这样,取的时候才能根据key直接拿到value。
把数据放入dict的方法,除了初始化时指定外,还可以通过key放入:
1 | >>> d['Adam'] = 67 |
由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会把前面的值冲掉:
1 | >>> d['Jack'] = 90 |
如果key不存在,dict就会报错:
1 | >>> d['Thomas'] |
要避免key不存在的错误,有两种办法,一是通过in判断key是否存在:
1 | >>> 'Thomas' in d |
二是通过dict提供的get()方法,如果key不存在,可以返回None,或者自己指定的value:
1 | >>> d.get('Thomas') |
注意:返回None的时候Python的交互环境不显示结果。
要删除一个key,用pop(key)方法,对应的value也会从dict中删除:
1 | >>> d.pop('Bob') |
请务必注意,dict内部存放的顺序和key放入的顺序是没有关系的。
和list比较,dict有以下几个特点:
- 查找和插入的速度极快,不会随着key的增加而变慢;
- 占用空间小,浪费内存很少。
所以,dict是用空间来换取时间的一种方法。
dict可以用在需要高速查找的很多地方,在Python代码中几乎无处不在,正确使用dict非常重要,需要牢记的第一条就是dict的key必须是不可变对象。
这是因为dict根据key来计算value的存储位置,如果每次计算相同的key得出的结果不同,那dict内部就完全混乱了。这个通过key计算位置的算法称为哈希算法(Hash)。
要保证hash的正确性,作为key的对象就不能变。在Python中,字符串、整数等都是不可变的,因此,可以放心地作为key。而list是可变的,就不能作为key:
1 | >>> key = [1, 2, 3] |
- set
set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。
要创建一个set,需要提供一个list作为输入集合:
1 | >>> s = set([1, 2, 3]) |
注意,传入的参数[1, 2, 3]是一个list,而显示的{1, 2, 3}只是告诉你这个set内部有1,2,3这3个元素,显示的顺序也不表示set是有序的。。
重复元素在set中自动被过滤:
1 | >>> s = set([1, 1, 2, 2, 3, 3]) |
- 通过add(key)方法可以添加元素到set中,可以重复添加,但不会有效果:
1 | >>> s.add(4) |
- 通过remove(key)方法可以删除元素:
1 | >>> s.remove(4) |
set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作:
1 | >>> s1 = set([1, 2, 3]) |
set和dict的唯一区别仅在于没有存储对应的value,但是,set的原理和dict一样,所以,同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”。试试把list放入set,看看是否会报错。
再议不可变对象
上面我们讲了,str是不变对象,而list是可变对象。
对于可变对象,比如list,对list进行操作,list内部的内容是会变化的,比如:
1 | >>> a = ['c', 'b', 'a'] |
而对于不可变对象,比如str,对str进行操作呢:
1 | >>> a = 'abc' |
虽然字符串有个replace()方法,也确实变出了’Abc’,但变量a最后仍是’abc’,应该怎么理解呢?
我们先把代码改成下面这样:
1 | >>> a = 'abc' |
要始终牢记的是,a是变量,而’abc’才是字符串对象!有些时候,我们经常说,对象a的内容是’abc’,但其实是指,a本身是一个变量,它指向的对象的内容才是’abc’:
1 | a————>'abc' |
当我们调用a.replace(‘a’, ‘A’)时,实际上调用方法replace是作用在字符串对象’abc’上的,而这个方法虽然名字叫replace,但却没有改变字符串’abc’的内容。相反,replace方法创建了一个新字符串’Abc’并返回,如果我们用变量b指向该新字符串,就容易理解了,变量a仍指向原有的字符串’abc’,但变量b却指向新字符串’Abc’了:
1 | a————>'abc' |
所以,对于不变对象来说,调用对象自身的任意方法,也不会改变该对象自身的内容。相反,这些方法会创建新的对象并返回,这样,就保证了不可变对象本身永远是不可变的。
小结
使用key-value存储结构的dict在Python中非常有用,选择不可变对象作为key很重要,最常用的key是字符串。
tuple虽然是不变对象,但试试把(1, 2, 3)和(1, [2, 3])放入dict或set中,并解释结果
函数
Python不但能非常灵活地定义函数,而且本身内置了很多有用的函数,可以直接调用。
调用函数
调用函数的时候,如果传入的参数数量不对,会报TypeError的错误,并且Python会明确地告诉你:abs()有且仅有1个参数,但给出了两个:
1 | >>> abs(1, 2) |
如果传入的参数数量是对的,但参数类型不能被函数所接受,也会报TypeError的错误,并且给出错误信息:str是错误的参数类型:
1 | >>> abs('a') |
而max函数max()可以接收任意多个参数,并返回最大的那个:
1 | >>> max(1, 2) |
数据类型转换
Python内置的常用函数还包括数据类型转换函数,比如int()函数可以把其他数据类型转换为整数:
1 | >>> int('123') |
函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”:
1 | >>> a = abs # 变量a指向abs函数 |
练习
请利用Python内置的hex()函数把一个整数转换成十六进制表示的字符串:
1 | n1 = 255 |
定义函数
在Python中,定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。
我们以自定义一个求绝对值的my_abs函数为例:
1 | def my_abs(x): |
请注意,函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。
如果没有return语句,函数执行完毕后也会返回结果,只是结果为None。return None可以简写为return。
空函数
如果想定义一个什么事也不做的空函数,可以用pass语句:
1 | def nop(): |
pass语句什么都不做,那有什么用?实际上pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来。
pass还可以用在其他语句里,比如:
1 | if age >= 18: |
缺少了pass,代码运行就会有语法错误。
参数检查
调用函数时,如果参数个数不对,Python解释器会自动检查出来,并抛出TypeError:
1 | >>> my_abs(1, 2) |
但是如果参数类型不对,Python解释器就无法帮我们检查。试试my_abs和内置函数abs的差别:
1 | >>> my_abs('A') |
当传入了不恰当的参数时,内置函数abs会检查出参数错误,而我们定义的my_abs没有参数检查,会导致if语句出错,出错信息和abs不一样。所以,这个函数定义不够完善。
让我们修改一下my_abs的定义,对参数类型做检查,只允许整数和浮点数类型的参数。数据类型检查可以用内置函数isinstance()实现:
1 | def my_abs(x): |
添加了参数检查后,如果传入错误的参数类型,函数就可以抛出一个错误:
1 | >>> my_abs('A') |
错误和异常处理将在后续讲到。
返回多个值
函数可以返回多个值吗?答案是肯定的。
比如在游戏中经常需要从一个点移动到另一个点,给出坐标、位移和角度,就可以计算出新的新的坐标:
1 | import math |
import math语句表示导入math包,并允许后续代码引用math包里的sin、cos等函数。
然后,我们就可以同时获得返回值:
1 | >>> x, y = move(100, 100, 60, math.pi / 6) |
但其实这只是一种假象,Python函数返回的仍然是单一值:
1 | >>> r = move(100, 100, 60, math.pi / 6) |
原来返回值是一个tuple!但是,在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便。
小结
定义函数时,需要确定函数名和参数个数;
如果有必要,可以先对参数的数据类型做检查;
函数体内部可以用return随时返回函数结果;
函数执行完毕也没有return语句时,自动return None。
函数可以同时返回多个值,但其实就是一个tuple。
练习
请定义一个函数quadratic(a, b, c),接收3个参数,返回一元二次方程:
ax2 + bx + c = 0
的两个解。
提示:计算平方根可以调用math.sqrt()函数:
1 | >>> import math |
1 | print('quadratic(2, 3, 1) =', quadratic(2, 3, 1)) |
函数的参数
高级特性
函数式编程
模块
面向对象编程
面向对象高级编程
错误、调试和测试
IO编程
进程和线程
正则表达式
常用内建模块
常用第三方模块
virtualenv
图形界面GUI
网络编程
电子邮件
访问数据库
Web开发
异步IO
实战
FAQ
期末总结
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 jyzh@yahoo.com
文章标题:Python 3.5 学习笔记总结
文章字数:10.7k
本文作者:Jooeys
发布时间:2018-02-04, 00:44:46
最后更新:2018-02-12, 19:39:59
原始链接:http://jooeys.github.io/2018/02/04/Python%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E6%95%B4%E7%90%86/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。