📢📢📢📣📣📣
哈喽!大家好,我是「奇点」,江湖人称 singularity。刚工作几年,想和大家一同进步🤝🤝
一位上进心十足的【Java ToB端大厂领域博主】!😜😜😜
喜欢java和python,平时比较懒,能用程序解决的坚决不手动解决😜😜😜✨ 如果有对【java】感兴趣的【小可爱】,欢迎关注我
❤️❤️❤️感谢各位大可爱小可爱!❤️❤️❤️
————————————————如果觉得本文对你有帮助,欢迎点赞,欢迎关注我,如果有补充欢迎评论交流,我将努力创作更多更好的文章。
————————————————
今天继续给大家分享python的学习笔记,之前吧python的基础知识,譬如特点、发展史、基本数据类型,逻辑语句和循环语句和集合等基础知识,有了这些入门知识,我们就能写一下简单的逻辑代码了。今天我们继续深入学习python到基础知识。
对python 0基础的同学可以看一下我的上篇文章,再来学习这篇文章,大佬可以直接跳过。

目录
可更改(mutable)与不可更改(immutable)对象
1.异常类只能来处理指定的异常情况,如果非指定异常则无法处理
Python 程序能用很多方式处理日期和时间,转换日期格式是一个常见的功能。python中内置了很多方法供我们使用。
Python 提供了一个 time 和 calendar 模块可以用于格式化日期和时间。
时间间隔是以秒为单位的浮点小数。
同其他编程语言一样,每个时间戳都以自从1970年1月1日午夜(历元)经过了多长时间来表示。
Python 的 time 模块下有很多函数可以转换常见日期格式,当然python中还有很多时间模块供我们选择,使用datetime模块、pytz模块和dateutil模块。我们今天主要讲的是time模块如函数time.time()用于获取当前时间戳, 如下实例:
- import time # 引入time模块
-
- ticks = time.time()
- print("当前时间戳为:", ticks)
结果如下
当前时间戳为: 1658989655.302531
时间戳单位最适于做日期运算。但是1970年之前的日期就无法以此表示了。太遥远的日期也不行,UNIX和Windows只支持到2038年。
很多Python函数用一个元组装起来的9组数字处理时间:
| 序号 | 字段 | 值 |
|---|---|---|
| 0 | 4位数年 | 2008 |
| 1 | 月 | 1 到 12 |
| 2 | 日 | 1到31 |
| 3 | 小时 | 0到23 |
| 4 | 分钟 | 0到59 |
| 5 | 秒 | 0到61 (60或61 是闰秒) |
| 6 | 一周的第几日 | 0到6 (0是周一) |
| 7 | 一年的第几日 | 1到366 (儒略历) |
| 8 | 夏令时 | -1, 0, 1, -1是决定是否为夏令时的旗帜 |
上述也就是struct_time元组。这种结构具有如下属性
| 序号 | 属性 | 值 |
|---|---|---|
| 0 | tm_year | 2008 |
| 1 | tm_mon | 1 到 12 |
| 2 | tm_mday | 1 到 31 |
| 3 | tm_hour | 0 到 23 |
| 4 | tm_min | 0 到 59 |
| 5 | tm_sec | 0 到 61 (60或61 是闰秒) |
| 6 | tm_wday | 0到6 (0是周一) |
| 7 | tm_yday | 1 到 366(儒略历) |
| 8 | tm_isdst | -1, 0, 1, -1是决定是否为夏令时的旗帜 |
从返回浮点数的时间戳方式向时间元组转换,只要将浮点数传递给如localtime之类的函数。
- localtime = time.localtime(time.time())
- print("本地时间为 :", localtime)
返回的结果如下:
本地时间为 : time.struct_time(tm_year=2022, tm_mon=7, tm_mday=28, tm_hour=15, tm_min=46, tm_sec=4, tm_wday=3, tm_yday=209, tm_isdst=0)
你可以根据需求选取各种格式,但是最简单的获取可读的时间模式的函数是asctime():
- localtime = time.asctime( time.localtime(time.time()) )
- print ("本地时间为 :", localtime)
本地时间为 : Thu Jul 28 17:11:02 2022
我们可以使用 time 模块的 strftime 方法来格式化日期,:
time.strftime(format[, t])
- import time
-
- # 格式化成2016-03-20 11:45:39形式
- print (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
-
- # 格式化成Sat Mar 28 22:24:24 2016形式
- print (time.strftime("%a %b %d %H:%M:%S %Y", time.localtime()))
-
- # 将格式字符串转换为时间戳
- a = "Sat Mar 28 22:24:24 2016"
- print (time.mktime(time.strptime(a,"%a %b %d %H:%M:%S %Y")))
2022-07-28 17:15:42
Thu Jul 28 17:15:42 2022
1459175064.0
python中时间日期格式化符号:
Calendar 模块有很广泛的方法用来处理年历和月历,例如打印某月的月历:
- import calendar
-
- cal = calendar.month(2022, 1)
- print("以下输出2022年1月份的日历:")
- print(cal)
以下输出2022年1月份的日历:
January 2022
Mo Tu We Th Fr Sa Su
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
此模块的函数都是日历相关的,例如打印某月的字符月历。星期一是默认的每周第一天,星期天是默认的最后一天。
更改设置需调用calendar.setfirstweekday()函数。模块包含了以下内置函数:
| 序号 | 函数及描述 |
|---|---|
| 1 | calendar.calendar(year,w=2,l=1,c=6) 返回一个多行字符串格式的 year 年年历,3 个月一行,间隔距离为 c。 每日宽度间隔为w字符。每行长度为 21* W+18+2* C。l 是每星期行数。 |
| 2 | calendar.firstweekday( ) 返回当前每周起始日期的设置。默认情况下,首次载入 calendar 模块时返回 0,即星期一。 |
| 3 | calendar.isleap(year) 是闰年返回 True,否则为 False。 >>> import calendar >>> print(calendar.isleap(2000)) True >>> print(calendar.isleap(1900)) False |
| 4 | calendar.leapdays(y1,y2) 返回在Y1,Y2两年之间的闰年总数。 |
| 5 | calendar.month(year,month,w=2,l=1) 返回一个多行字符串格式的year年month月日历,两行标题,一周一行。每日宽度间隔为w字符。每行的长度为7* w+6。l是每星期的行数。 |
| 6 | calendar.monthcalendar(year,month) 返回一个整数的单层嵌套列表。每个子列表装载代表一个星期的整数。Year年month月外的日期都设为0;范围内的日子都由该月第几日表示,从1开始。 |
| 7 | calendar.monthrange(year,month) 返回两个整数。第一个是该月的星期几,第二个是该月有几天。星期几是从0(星期一)到 6(星期日)。 >>> import calendar >>> calendar.monthrange(2014, 11) (5, 30) (5, 30)解释:5 表示 2014 年 11 月份的第一天是周六,30 表示 2014 年 11 月份总共有 30 天。 |
| 8 | calendar.prcal(year, w=0, l=0, c=6, m=3) 相当于 print (calendar.calendar(year, w=0, l=0, c=6, m=3))。 |
| 9 | calendar.prmonth(theyear, themonth, w=0, l=0) 相当于 print(calendar.month(theyear, themonth, w=0, l=0))。 |
| 10 | calendar.setfirstweekday(weekday) 设置每周的起始日期码。0(星期一)到6(星期日)。 |
| 11 | calendar.timegm(tupletime) 和time.gmtime相反:接受一个时间元组形式,返回该时刻的时间戳(1970纪元后经过的浮点秒数)。 |
| 12 | calendar.weekday(year,month,day) 返回给定日期的日期码。0(星期一)到6(星期日)。月份为 1(一月) 到 12(12月)。 |
和其他语言一样python中的函数也是为了实现某一功能的代码段,用来实现单一功能,能够重复使用。
函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。

Python 定义函数使用 def 关键字,一般格式如下:
- def 函数名(参数列表):
- 函数体
默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的。
例如比较两个数,并返回较大的数:
- def max(a, b):
- if a > b:
- return a
- else:
- return b
-
- a = 4
- b = 5
- print(max(a, b))
定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。
如下实例调用了 printme() 函数:
- # 定义函数
- def printme( str ):
- # 打印任何传入的字符串
- print (str)
- return
-
- # 调用函数
- printme("我要调用用户自定义函数!")
- printme("再次调用同一函数")
在 python 中,类型属于对象,对象有不同类型的区分,变量是没有类型的:
- a=[1,2,3]
-
- a="Runoob"
以上代码中,[1,2,3] 是 List 类型,"Runoob" 是 String 类型,而变量 a 是没有类型,她仅仅是一个对象的引用(一个指针),可以是指向 List 类型对象,也可以是指向 String 类型对象。
在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象。
不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变 a 的值,相当于新生成了 a。
可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。
python 函数的参数传递:
不可变类型:类似 C++ 的值传递,如整数、字符串、元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本身。如果在 fun(a) 内部修改 a 的值,则是新生成一个 a 的对象。
可变类型:类似 C++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后 fun 外部的 la 也会受影响
python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。
通过 id() 函数来查看内存地址变化:
- la = [1, 2, 3]
- print("...")
- print("la的地址" + str(id(la)))
- la[2] = 5
- print('la的地址' + str(id(la)))
-
-
- def change(a):
- print(id(a)) # 4363387120 还是原来的对象,形式参数和实参是一个对象
- a = 10
- print(id(a)) # 4363387408 修改了对象之后,不再是原来的对象,新生成了一个对象
-
-
- a = 1
- print(id(a)) # 4363387120
- change(a)
- print(a) # 1 还是源对象,方法中的是局部变量
- print(id(a)) # 4363387120
la的地址4366217024
la的地址43662170244363387120
4363387120
4363387408
1
4363387120
可以看见在调用函数前后,形参和实参指向的是同一个对象(对象 id 相同),在函数内部修改形参后,形参指向的是不同的 id。
可变对象在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了。例如:
- def changeme(mylist):
- "修改传入的列表"
- mylist.append([1, 2, 3, 4])
- print("函数内取值: ", mylist)
- print("mylist地址2" + str(id(mylist)))
- return
-
-
- # 调用changeme函数
- mylist = [10, 20, 30]
- print("mylist地址1" + str(id(mylist)))
- changeme(mylist)
- print("mylist地址3" + str(id(mylist)))
- print("函数外取值: ", mylist)
mylist地址24366783488
mylist地址34366783488
以下是调用函数时可使用的正式参数类型:
必需参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。
调用 printme() 函数,你必须传入一个参数,不然会出现语法错误:
- #可写函数说明
- def printme( str ):
- "打印任何传入的字符串"
- print (str)
- return
-
- # 调用 printme 函数,不加参数会报错
- printme()
Traceback (most recent call last): File "test.py", line 10, inprintme() TypeError: printme() missing 1 required positional argument: 'str'
关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。
使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。
以下实例在函数 printme() 调用时使用参数名:
- #可写函数说明
- def printme( str ):
- "打印任何传入的字符串"
- print (str)
- return
-
- #调用printme函数
- printme( str = "我是菜鸟一枚")
结果:
我是菜鸟一枚
以下实例中演示了函数参数的使用不需要使用指定顺序:
- #可写函数说明
- def printinfo( name, age ):
- "打印任何传入的字符串"
- print ("名字: ", name)
- print ("年龄: ", age)
- return
-
- #调用printinfo函数
- printinfo( age=50, name="runoob" )
结果:
- 名字: runoob
- 年龄: 50
调用函数时,如果没有传递参数,则会使用默认参数。以下实例中如果没有传入 age 参数,则使用默认值:
- #可写函数说明
- def printinfo( name, age = 35 ):
- "打印任何传入的字符串"
- print ("名字: ", name)
- print ("年龄: ", age)
- return
-
- #调用printinfo函数
- printinfo( age=50, name="runoob" )
- print ("------------------------")
- printinfo( name="runoob" )
结果:
名字: runoob 年龄: 50 ------------------------ 名字: runoob 年龄: 35
你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述 2 种参数不同,声明时不会命名。基本语法如下:
- def functionname([formal_args,] *var_args_tuple ):
- "函数_文档字符串"
- function_suite
- return [expression]
加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。
- # 可写函数说明
- def printinfo( arg1, *vartuple ):
- "打印任何传入的参数"
- print ("输出: ")
- print (arg1)
- print (vartuple)
-
- # 调用printinfo 函数
- printinfo( 70, 60, 50 )
结果
输出: 70 (60, 50)
如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量。如下实例:
- # 可写函数说明
- def printinfo( arg1, *vartuple ):
- "打印任何传入的参数"
- print ("输出: ")
- print (arg1)
- for var in vartuple:
- print (var)
- return
-
- # 调用printinfo 函数
- printinfo( 10 )
- printinfo( 70, 60, 50 )
结果:
- 输出:
- 10
- 输出:
- 70
- 60
- 50
还有一种就是参数带两个星号 **基本语法如下:
- def functionname([formal_args,] **var_args_dict ):
- "函数_文档字符串"
- function_suite
- return [expression]
加了两个星号 ** 的参数会以字典的形式导入。
- # 可写函数说明
- def printinfo( arg1, **vardict ):
- "打印任何传入的参数"
- print ("输出: ")
- print (arg1)
- print (vardict)
-
- # 调用printinfo 函数
- printinfo(1, a=2,b=3)
以上实例输出结果:
输出:
1
{'a': 2, 'b': 3}
声明函数时,参数中星号 * 可以单独出现,例如:
- def f(a,b,*,c):
- return a+b+c
如果单独出现星号 *,则星号 * 后的参数必须用关键字传入:
- >>> def f(a,b,*,c):
- ... return a+b+c
- ...
- >>> f(1,2,3) # 报错
- Traceback (most recent call last):
- File "
" , line 1, in - TypeError: f() takes 2 positional arguments but 3 were given
- >>> f(1,2,c=3) # 正常
- 6
- >>>
Python 使用 lambda 来创建匿名函数。
所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。
lambda 函数的语法只包含一个语句,如下:
lambda [arg1 [,arg2,.....argn]]:expression
设置参数 a 加上 10:
- x = lambda a : a + 10
- print(x(5))
以下实例匿名函数设置两个参数:
- # 可写函数说明
- sum = lambda arg1, arg2: arg1 + arg2
-
- # 调用sum函数
- print ("相加后的值为 : ", sum( 10, 20 ))
- print ("相加后的值为 : ", sum( 20, 20 ))
结果:
相加后的值为 : 30 相加后的值为 : 40
我们可以将匿名函数封装在一个函数内,这样可以使用同样的代码来创建多个匿名函数。
以下实例将匿名函数封装在 myfunc 函数中,通过传入不同的参数来创建不同的匿名函数:
- def myfunc(n):
- return lambda a : a * n
-
- mydoubler = myfunc(2)
- mytripler = myfunc(3)
-
- print(mydoubler(11))
- print(mytripler(11))
结果
22
33
return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。不带参数值的 return 语句返回 None。之前的例子都没有示范如何返回数值,以下实例演示了 return 语句的用法:
- # 可写函数说明
- def sum( arg1, arg2 ):
- # 返回2个参数的和."
- total = arg1 + arg2
- print ("函数内 : ", total)
- return total
-
- # 调用sum函数
- total = sum( 10, 20 )
- print ("函数外 : ", total)
结果:
函数内 : 30 函数外 : 30
Python3.8 新增了一个函数形参语法 / 用来指明函数形参必须使用指定位置参数,不能使用关键字参数的形式。
在以下的例子中,形参 a 和 b 必须使用指定位置参数,c 或 d 可以是位置形参或关键字形参,而 e 和 f 要求为关键字形参:
- def f(a, b, /, c, d, *, e, f):
- print(a, b, c, d, e, f)
以下使用方法是正确的:
f(10, 20, 30, d=40, e=50, f=60)
以下使用方法会发生错误:
f(10, b=20, c=30, d=40, e=50, f=60) # b 不能使用关键字参数的形式 f(10, 20, 30, 40, 50, f=60) # e 必须使用关键字参数的形式
好嘞,学到这里,我们把函数就学习完了,哈哈哈给自己点一个赞吧👍,休息一下马上回来。

Python open() 方法用于打开一个文件,并返回文件对象。
在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出 OSError。
注意:使用 open() 方法一定要保证关闭文件对象,即调用 close() 方法。
open() 函数常用形式是接收两个参数:文件名(file)和模式(mode)。
open(file, mode='r')
完整的语法格式为:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
参数说明:
mode 参数有:
| 模式 | 描述 |
|---|---|
| t | 文本模式 (默认)。 |
| x | 写模式,新建一个文件,如果该文件已存在则会报错。 |
| b | 二进制模式。 |
| + | 打开一个文件进行更新(可读可写)。 |
| U | 通用换行模式(Python 3 不支持)。 |
| r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
| rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。 |
| r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 |
| rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等。 |
| w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
| wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
| w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
| wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
| a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
| ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
| a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
| ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
默认为文本模式,如果要以二进制模式打开,加上 b 。
file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数:
| 序号 | 方法及描述 |
|---|---|
| 1 | 关闭文件。关闭后文件不能再进行读写操作。 |
| 2 | 刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入。 |
| 3 | 返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如os模块的read方法等一些底层操作上。 |
| 4 | 如果文件连接到一个终端设备返回 True,否则返回 False。 |
| 5 | Python 3 中的 File 对象不支持 next() 方法。 返回文件下一行。 |
| 6 | 从文件读取指定的字节数,如果未给定或为负则读取所有。 |
| 7 | 读取整行,包括 "\n" 字符。 |
| 8 | 读取所有行并返回列表,若给定sizeint>0,返回总和大约为sizeint字节的行, 实际读取值可能比 sizeint 较大, 因为需要填充缓冲区。 |
| 9 | 移动文件读取指针到指定位置 |
| 10 | 返回文件当前位置。 |
| 11 | 从文件的首行首字符开始截断,截断文件为 size 个字符,无 size 表示从当前位置截断;截断之后后面的所有字符被删除,其中 windows 系统下的换行代表2个字符大小。 |
| 12 | 将字符串写入文件,返回的是写入的字符长度。 |
| 13 | 向文件写入一个序列字符串列表,如果需要换行则要自己加入每行的换行符。 |
例如下面的例子
当然可以根据自己的需求,在上面的mode参数中根据自己的需求选择不同的模式
- """
- 文件写操作
- """
- try:
- file_path = "abc.txt"
- # file_path = "/Users/ligang/Desktop/abc.txt"
- file = open(file_path, 'a', encoding='utf-8')
- file.write("写文件你好啊")
- finally:
- file.close()
-
- """
- 之前的东西没有了 w-会把文件的指针放到开头
- a-追加
- """
这时由于之前没有这个文件,创建了一个新的文件

- f = open('abc.txt', 'r', encoding='utf-8')
- print(f.read())
- f.close()
这是运行3遍程序之后的abc.txt文件内容

这里说一下read()和readlines()、readline()三者各自的作用:
(1)read() ——不管文件内容的多少一次性全部读出
(2)readlines()——按照行的方式把整个文件中的内容进行一次性的读取,并且返回的是一个列表,其中每一行的数据为一个元素
(3)readline()—— 一次读取一行
- try:
- f = open('abc.txt', 'r', encoding='utf-8')
- # print('read方法' + f.read())
- # list = f.readline()
- # for x in list:
- # print(f.readline())
- # print('readline方法' + str(x))
- list = f.readlines()
- print(list)
- for x in list:
- print('readlines方法' + x)
- finally:
- f.close()
结果

readline方法
- try:
- f = open('abc.txt', 'r', encoding='utf-8')
-
- print(f.readline())
-
- finally:
- f.close()
结果
写文件你好啊1
再加一个readline方法
- try:
- f = open('abc.txt', 'r', encoding='utf-8')
-
- print(f.readline())
- print(f.readline())
-
- finally:
- f.close()
这时的输出就是下面的样子,多读取了一行
写文件你好啊1
写文件你好啊2
当访问模式中有b时,代表以二进制格式处理。
- try:
- f = open('python.png', 'rb')
- print(f.read())
- finally:
- f.close()
结果:

在前面几个章节中,我们其实已经接触了 Python 的输入输出的功能。本章节我们将具体介绍 Python 的输入输出。
Python两种输出值的方式: 表达式语句和 print() 函数。
第三种方式是使用文件对象的 write() 方法,标准输出文件可以用 sys.stdout 引用。
如果你希望输出的形式更加多样,可以使用 str.format() 函数来格式化输出值。
如果你希望将输出的值转成字符串,可以使用 repr() 或 str() 函数来实现。
- >>> str(1/7)
- '0.14285714285714285'
-
- >>> # repr() 的参数可以是 Python 的任何对象
- ... repr((x, y, ('Google', 'Runoob')))
- "(32.5, 40000, ('Google', 'Runoob'))"
这里有两种方式输出一个平方与立方的表:
- >>> for x in range(1, 11):
- ... print(repr(x).rjust(2), repr(x*x).rjust(3), end=' ')
- ... # 注意前一行 'end' 的使用
- ... print(repr(x*x*x).rjust(4))
- ...
- 1 1 1
- 2 4 8
- 3 9 27
- 4 16 64
- 5 25 125
- 6 36 216
- 7 49 343
- 8 64 512
- 9 81 729
- 10 100 1000
-
- >>> for x in range(1, 11):
- ... print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x))
- ...
- 1 1 1
- 2 4 8
- 3 9 27
- 4 16 64
- 5 25 125
- 6 36 216
- 7 49 343
- 8 64 512
- 9 81 729
- 10 100 1000
意:在第一个例子中, 每列间的空格由 print() 添加。
str.format() 的基本使用如下:
print('{}网址: "{}!"'.format('hello', 'www.hello.com'))
hello网址: "www.hello.com!"
括号及其里面的字符 (称作格式化字段) 将会被 format() 中的参数替换。
在括号中的数字用于指向传入对象在 format() 中的位置,如下所示:
print('{0} 和 {1}'.format('Google', 'hello'))
Google 和 hello
print('{1} 和 {0}'.format('Google', 'hello'))
hello 和 Google
如果在 format() 中使用了关键字参数, 那么它们的值会指向使用该名字的参数。
print('{name}网址: {site}'.format(name='hello', site='www.hello.com'))
hello网址: www.hello.com
位置及关键字参数可以任意的结合:
print('站点列表 {0}, {1}, 和 {other}。'.format('Google', 'hello', other='Taobao'))
站点列表 Google, hello, 和 Taobao。
% 操作符也可以实现字符串格式化。 它将左边的参数作为类似 sprintf() 式的格式化字符串, 而将右边的代入, 然后返回格式化后的字符串. 例如:
- >>> import math
- >>> print('常量 PI 的值近似为:%5.3f。' % math.pi)
- 常量 PI 的值近似为:3.142。
因为 str.format() 是比较新的函数, 大多数的 Python 代码仍然使用 % 操作符。但是因为这种旧式的格式化最终会从该语言中移除, 应该更多的使用 str.format().
- str = input("请输入:");
- print ("你输入的内容是: ", str)
这会产生如下的对应着输入的结果:
请输入: hello world 你输入的内容是: hello world
作为 Python 初学者,在刚学习 Python 编程时,经常会看到一些报错信息,在前面我们没有提及,这里我们来学习
Python 有两种错误很容易辨认:语法错误和异常。
Python assert(断言)用于判断一个表达式,在表达式条件为 false 的时候触发异常。
在异常处理方面python的处理方式和java很相似,我们能够通过类比的方式学习python的异常处理机制。

Python 的语法错误或者称之为解析错,是初学者经常碰到的,如下实例
while True print('Hello world')
File "
", line 1, in ?
while True print('Hello world')
^
SyntaxError: invalid syntax
这个例子中,函数 print() 被检查到有错误,是它前面缺少了一个冒号 : 。
语法分析器指出了出错的一行,并且在最先找到的错误的位置标记了一个小小的箭头。
对异常的处理有两种方式,这个也是和java中的处理方法一样,是不是学起来就简单了呢。
常见语法错误
- AttributeError 试图访问一个对象没有的属性,比如foo.x,但是foo没有属性x
-
- IOError 输入/输出异常;基本上是无法打开文件
-
- ImportError 无法引入模块或包;基本上是路径问题或名称错误
-
- IndentationError 语法错误(的子类) ;代码没有正确对齐
-
- IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
-
- KeyError 试图访问字典里不存在的键
-
- KeyboardInterrupt Ctrl+C被按下
-
- NameError 使用一个还未被赋予对象的变量
-
- SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
-
- TypeError 传入对象类型与要求的不符合
-
- UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一
- 个同名的全局变量,导致你以为正在访问它
-
- ValueError 传入一个调用者不期望的值,即使值的类型是正确的
更多错误
- ArithmeticError
- AssertionError
- AttributeError
- BaseException
- BufferError
- BytesWarning
- DeprecationWarning
- EnvironmentError
- EOFError
- Exception
- FloatingPointError
- FutureWarning
- GeneratorExit
- ImportError
- ImportWarning
- IndentationError
- IndexError
- IOError
- KeyboardInterrupt
- KeyError
- LookupError
- MemoryError
- NameError
- NotImplementedError
- OSError
- OverflowError
- PendingDeprecationWarning
- ReferenceError
- RuntimeError
- RuntimeWarning
- StandardError
- StopIteration
- SyntaxError
- SyntaxWarning
- SystemError
- SystemExit
- TabError
- TypeError
- UnboundLocalError
- UnicodeDecodeError
- UnicodeEncodeError
- UnicodeError
- UnicodeTranslateError
- UnicodeWarning
- UserWarning
- ValueError
- Warning
- ZeroDivisionError
即使语句或表达式使用了正确的语法,执行时仍可能触发错误。执行时检测到的错误称为 异常,异常不一定导致严重的后果:很快我们就能学会如何处理 Python 的异常。大多数异常不会被程序处理,而是显示下列错误信息:
- >>> 10 * (1/0)
- Traceback (most recent call last):
- File "
" , line 1, in - ZeroDivisionError: division by zero
-
-
-
- >>> 4 + spam*3
- Traceback (most recent call last):
- File "
" , line 1, in - NameError: name 'spam' is not defined
-
-
-
- >>> '2' + 2
- Traceback (most recent call last):
- File "
" , line 1, in - TypeError: can only concatenate str (not "int") to str
错误信息的最后一行说明程序遇到了什么类型的错误。异常有不同的类型,而类型名称会作为错误信息的一部分中打印出来:上述示例中的异常类型依次是:ZeroDivisionError, NameError 和 TypeError。作为异常类型打印的字符串是发生的内置异常的名称。对于所有内置异常都是如此,但对于用户定义的异常则不一定如此(虽然这种规范很有用)。标准的异常类型是内置的标识符(不是保留关键字)。
此行其余部分根据异常类型,结合出错原因,说明错误细节。
错误信息开头用堆栈回溯形式展示发生异常的语境。一般会列出源代码行的堆栈回溯;但不会显示从标准输入读取的行。
| 异常名称 | 描述 |
|---|---|
| BaseException | 所有异常的基类 |
| SystemExit | 解释器请求退出 |
| KeyboardInterrupt | 用户中断执行(通常是输入^C) |
| Exception | 常规错误的基类 |
| StopIteration | 迭代器没有更多的值 |
| GeneratorExit | 生成器(generator)发生异常来通知退出 |
| SystemExit | Python 解释器请求退出 |
| StandardError | 所有的内建标准异常的基类 |
| ArithmeticError | 所有数值计算错误的基类 |
| FloatingPointError | 浮点计算错误 |
| OverflowError | 数值运算超出最大限制 |
| ZeroDivisionError | 除(或取模)零 (所有数据类型) |
| AssertionError | 断言语句失败 |
| AttributeError | 对象没有这个属性 |
| EOFError | 没有内建输入,到达EOF 标记 |
| EnvironmentError | 操作系统错误的基类 |
| IOError | 输入/输出操作失败 |
| OSError | 操作系统错误 |
| WindowsError | 系统调用失败 |
| ImportError | 导入模块/对象失败 |
| KeyboardInterrupt | 用户中断执行(通常是输入^C) |
| LookupError | 无效数据查询的基类 |
| IndexError | 序列中没有没有此索引(index) |
| KeyError | 映射中没有这个键 |
| MemoryError | 内存溢出错误(对于Python 解释器不是致命的) |
| NameError | 未声明/初始化对象 (没有属性) |
| UnboundLocalError | 访问未初始化的本地变量 |
| ReferenceError | 弱引用(Weak reference)试图访问已经垃圾回收了的对象 |
| RuntimeError | 一般的运行时错误 |
| NotImplementedError | 尚未实现的方法 |
| SyntaxError | Python 语法错误 |
| IndentationError | 缩进错误 |
| TabError | Tab 和空格混用 |
| SystemError | 一般的解释器系统错误 |
| TypeError | 对类型无效的操作 |
| ValueError | 传入无效的参数 |
| UnicodeError | Unicode 相关的错误 |
| UnicodeDecodeError | Unicode 解码时的错误 |
| UnicodeEncodeError | Unicode 编码时错误 |
| UnicodeTranslateError | Unicode 转换时错误 |
| Warning | 警告的基类 |
| DeprecationWarning | 关于被弃用的特征的警告 |
| FutureWarning | 关于构造将来语义会有改变的警告 |
| OverflowWarning | 旧的关于自动提升为长整型(long)的警告 |
| PendingDeprecationWarning | 关于特性将会被废弃的警告 |
| RuntimeWarning | 可疑的运行时行为(runtime behavior)的警告 |
| SyntaxWarning | 可疑的语法的警告 |
| UserWarning | 用户代码生成的警告 |
为了保证程序的健壮性与容错性,即在遇到错误时候程序不会崩溃,我们需要对异常进行处理
我们需要用if进行处理,在错误发生之前进行预防
- AGE=10
- while True:
- age=input('>>: ').strip()
- if age.isdigit(): #只有在age为字符串形式的整数时,下列代码才不会出错,该条件是可预知的
- age=int(age)
- if age == AGE:
- print('you got it')
- break
则需要用到try..except:在错误发生之后进行处理
可以编写程序处理选定的异常。下例会要求用户一直输入内容,直到输入有效的整数,但允许用户中断程序(使用 Control-C 或操作系统支持的其他操作);注意,用户中断程序KeyboardInterrupt异常。
- while True:
- try:
- x = int(input("Please enter a number: "))
- break
- except ValueError:
- print("Oops! That was no valid number. Try again...")
try 语句的工作原理如下:
首先,执行 try 子句 (try 和 except 关键字之间的(多行)语句)。
如果没有触发异常,则跳过 except 子句,try语句执行完毕。
如果在执行try子句时发生了异常,则跳过该子句中剩下的部分。 如果异常的类型与except 关键字后指定的异常相匹配,则会执行 except 子句,然后跳到 try/except 代码块之后继续执行。
如果发生的异常与 except 子句 中指定的异常不匹配,则它会被传递到外部的 try 语句中;如果没有找到处理程序,则它是一个 未处理异常 且执行将终止并输出如上所示的消息。
try 语句可以有多个 except 子句 来为不同的异常指定处理程序。 但最多只有一个处理程序会被执行。 处理程序只处理对应的 try 子句 中发生的异常,而不处理同一 try 语句内其他处理程序中的异常。 except 子句 可以用带圆括号的元组来指定多个异常,例如:
- except (RuntimeError, TypeError, NameError):
- pass
我们把可能发生错误的语句放在try模块里,用except来处理异常。except可以处理一个专门的异常,也可以处理一组圆括号中的异常,如果except后没有指定异常,则默认处理所有的异常。每一个try,都必须至少有一个except
- s1 = 'hello'
- try:
- int(s1)
- except IndexError as e: # 未捕获到异常,程序直接报错
- print e
- s1 = 'hello'
- try:
- int(s1)
- except IndexError as e:
- print(e)
- except KeyError as e:
- print(e)
- except ValueError as e:
- print(e)
- s1 = 'hello'
- try:
- int(s1)
- except Exception as e:
- print(e)
- s1 = 'hello'
- try:
- int(s1)
- except IndexError as e:
- print(e)
- except KeyError as e:
- print(e)
- except ValueError as e:
- print(e)
- except Exception as e:
- print(e)
与java语言类似 finally语句的方法都会执行
- try:
- <语句>
- finally:
- <语句> #退出try时总会执行
- raise
- s1 = 'hello'
- try:
- int(s1)
- except IndexError as e:
- print(e)
- except KeyError as e:
- print(e)
- except ValueError as e:
- print(e)
- #except Exception as e:
- # print(e)
- else:
- print('try内代码块没有异常则执行我')
- finally:
- print('无论异常与否,都会执行该模块,通常是进行清理工作')
我们可以使用raise语句自己触发异常,就像java中的throw一样。raise语法格式如下:
raise [Exception [, args [, traceback]]]
语句中Exception是异常的类型(例如,NameError)参数是一个异常参数值。该参数是可选的,如果不提供,异常的参数是"None"。
最后一个参数是可选的(在实践中很少使用),如果存在,是跟踪异常对象。
示例:
一个异常可以是一个字符串,类或对象。 Python的内核提供的异常,大多数都是实例化的类,这是一个类的实例的参数。
定义一个异常非常简单,如下所示:
- def functionName(level):
- if level < 1:
- raise Exception("Invalid level!", level)
- # 触发异常后,后面的代码就不会再执行
- print("执行后面的代码了")
-
- functionName(1)
- functionName(0)

如果先传递的参数是0后传1后面调用方法传递1的方法就不会执行

- try:
- raise TypeError('类型错误')
- except Exception as e:
- print(e)
结果
类型错误
与java中的throw如出一辙,类比理解能够很容易就接收。
通过创建一个新的异常类,程序可以命名它们自己的异常。异常应该是典型的继承自Exception类,通过直接或间接的方式。
以下为与BaseException相关的实例,实例中创建了一个类,基类为BaseException,用于在异常触发时输出更多的信息。
在try语句块中,用户自定义的异常后执行except块语句,变量 e 是用于创建Networkerror类的实例。
- class Networkerror(BaseException):
- def __init__(self, msg):
- self.msg = msg
-
- def __str__(self):
- return self.msg
-
-
- try:
- raise Networkerror('Networkerror类型错误')
- except Networkerror as e:
- print(e)
结果
Networkerror类型错误
assert 1==1
有的同学会这么想,学完了异常处理后,好强大,我要为我的每一段程序都加上try...except,干毛线去思考它会不会有逻辑错误啊,这样就很好啊,多省脑细胞,这样其实并不好,为什么呢?
首先try...except是你附加给你的程序的一种异常处理的逻辑,与你的主要的工作是没有关系的,这种东西加的多了,会导致你的代码可读性变差
然后异常处理本就不是你的擦屁股纸,只有在错误发生的条件无法预知的情况下,才应该加上try...except
