Python 语法基础知识详解和查询手册
python 很重要, 但不需要这么多知识…… 2024. 11. 22
python 很重要, 但不需要这么多知识…… 2024. 11. 22
数字类型属于内置类型。有三种不同的数字类型:整数,浮点数和复数。
整数通常只有数字,浮点数有小数点,而复数有实部(省略则为 0)和虚部,虚部必须有 J 或 j。
它们的类型分别是 int,float 和 complex。
type(1), type(1.0), type(1j)
(int, float, complex)
它们虽然属于不同的类型,但 Python 完全支持其混合运算。
而且布尔类型属于整数类型的子类型,布尔类型也可参与混合运算。
True/3 + 1.5 - 1J
(1.8333333333333333-1j)
数字之间比较时,比较的是它们的精度决定的精确值:
True == 1 == 1.0
True
对于不同类型的数字,只要精确值相等,哈希值必定相等:
hash(True) == hash(1) == hash(1.0)
True
因此作为集合的元素时,它们是一个元素;作为字典的键时,是同一个键。但这不是明智之举,因为浮点数存在精度问题:
{True, 1, 1.0}
{True}
{True:1, 1:2, 1.0:3}
{True: 3}
1.00000000000000009 == 1
True
整数,浮点数和复数的构造函数分别是:int(),float() 和 complex()。构造细节详见相应内置函数知识点。
int('1'), float('1.0'), complex('1')
(1, 1.0, (1+0j))
关于各数字类型的特性和详细介绍见后面章节。
整数具有无限精度。有四种整数表示法:十六进制整数(0x 或 0X 开头),十进制整数,八进制整数(0o 或 0O 开头)和二进制整数(0b 或 0B 开头)。
# 十六进制
0x10
16
# 十进制
10
10
# 八进制
0O10
8
# 二进制
0b10
2
数字之间或基数说明符(例如 0b)后,可以放一个下划线:
123_456_789
123456789
0b_1010
10
十进制整数不可以 0 开头:
012
File "<ipython-input-44-95f378563ada>", line 1
012
^
SyntaxError: leading zeros in decimal integer literals are not permitted; use an 0o prefix for octal integers
按位运算只对整数有意义。以优先级升序排序的按位运算:
x | y
x 和 y 按位 或 运算x ^ y
x 和 y 按位 异或 运算x & y
x 和 y 按位 与 运算x << n
x 左移 n 位,相当于 x*2**n
x >> n
x 右移 n 位,相当于 x//(2**n)
~x
x 逐位取反下面以八位机为例,x 取 6,y 取 8,n 取 2:
6 和 8 在内存中的储存分别为 00000110,00001000。
按位 或 运算,规则如下:
0|0, 1|0, 1|1
(0, 1, 1)
6|8 逐位运算后结果为 00001110,十进制就是 14:
6|8, 0b00001110
(14, 14)
同理可按下列计算规则,计算出 6^8, 6&8:
0^0, 0^1, 1^1
(0, 1, 0)
0&0, 0&1, 1&1
(0, 0, 1)
6^8, 6&8
(14, 0)
6 左移 2 位结果为 00011000,十进制就是 24,相当于 6*2**2
:
6<<2, 0b00011000, 6*2**2
(24, 24, 24)
同理可计算出 6»2,结果为 1:
6>>2, 6//(2**2)
(1, 1)
6 逐位取反为 11111001,因为我们是以八位机来举例的,八位机中 11111001 表示 -7,这是个天才设计,正负整数计算可以利用一种电路即可完成,有兴趣的可以查资料了解详情。
~6
-7
例如 8 + (-7) 如此计算:
00001000
+ 11111001
=100000001
因为是八位机,结果有 9 位,所以第一个 1 溢出,结果就是 1。
布尔值有 True 和 False,布尔类型是整数类型的子类型,所以整数的运算都适用布尔值运算。
issubclass(bool,int)
True
True + 1
2
~True
-2
任何对象都可以进行布尔值的检测,以便在 if 或 while 中作为条件或是作为下文所述布尔运算的操作数来使用。
一个对象在默认情况下均被视为真值,除非当该对象被调用时其所属类定义了 __bool__()
方法且返回 False 或是定义了 __len__()
方法且返回零。
下面基本完整地列出了会被视为假值的内置对象:
可以使用内置函数 bool() 来查看任意对象的布尔值:
bool(None), bool(int), bool(0)
(False, True, False)
布尔运算按优先级升序排列:
x or y
, if x is false, then y, else xx and y
, if x is false, then x, else ynot x
, if x is false, then True, else False任何值(包括表达式求值结果),除了自身之外,还有相应的逻辑值(布尔值),所以布尔运算符 or,and,not 可对任何值进行运算。
举例如下:
1>2 or 'python'
'python'
1>2 表达式结果为 False,所以布尔运算结果为 ‘python’。
1+1 or 'python'
2
1+1 表达式结果为 2,布尔值为 True,所以布尔运算结果为 2。
1>2 and 'python'
False
1>2 表达式的结果为 False,所以布尔运算结果为 False。
1<2 and 'python'
'python'
1<2 表达式的结果为 True,所以布尔运算结果为 ‘python’。
not 'python'
False
‘python’ 的布尔值为 True,所以布尔运算结果为 False。
not 0
True
0 的布尔值为 False,所以布尔运算结果为 True。
浮点数简单理解就是带小数点的数,通常使用 C 语音中的 double 来实现。有关你的程序运行所在计算机上浮点数的精度和内部表示法可在 sys.float_info 中查看。
import sys
sys.float_info
sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)
浮点数可以省略 .
前后的数;可以使用科学计数法;可以在数字之间插入下划线;可以以 0 开头。
举例如下:
# e 大小写均可 e-2 表示 10 的 -2 次方
0., .5, 0.1e-2, 3_1.1_4, 01.2e02
(0.0, 0.5, 0.001, 31.14, 120.0)
整数除法除一定得到浮点数:
True/3, 3/3
(0.3333333333333333, 1.0)
整数和浮点数可以相互转换,浮点数转为整数,直接去掉小数部分:
int(3.56), float(0)
(3, 0.0)
复数包含实部和虚部(带 j 或 J 的部分),分别以一个浮点数表示。在一个数字后面加上 j 或 J,则得到一个实部为零的复数。
-1j
(-0-1j)
1 + 0j
(1+0j)
看起来实部和虚部并不是以浮点数表示,可以使用 .real 和 .imag,从一个复数中提取这两个部分查看。
(1 + 0j).real, (1 + 0j).imag
(1.0, 0.0)
-1j.real, -1j.imag
(-0.0, -1.0)
实部和虚部都是以浮点数表示,所以复数可以使用浮点数的所有表示法:
0.J, .5J, 0.1e-2J, 3_1.1_4J, 01.2e02J
(0j, 0.5j, 0.001j, 31.14j, 120j)
对复数取绝对值,就是计算它的模——实部和虚部平方的和开根号:
abs(3+4j), (3**2 + 4**2)**0.5
(5.0, 5.0)
所有数字类型都支持下列运算(复数不支持 // 和 %):
x + y
, x 和 y 的和x - y
, x 和 y 的差x * y
, x 和 y 的乘积x / y
, x 和 y 的商x // y
, x 和 y 的商数x % y
, x / y 的余数-x
, x 取反+x
, x 不变x ** y
, x 的 y 次幂Python 完全支持数字的混合运算:当一个二元算术运算符的操作数有不同数值类型时,“较窄” 类型的操作数会拓宽到另一个操作数的类型。其中整数比浮点数窄,浮点数比复数窄。但整数除以整数得到浮点数。
运算示例如下:
True + 1 + 3.14
5.140000000000001
True + 1 + 3.14 + 0j
(5.140000000000001+0j)
3/3, 3/1j
(1.0, -3j)
6//2, 6//2.0
(3, 3.0)
6%4, 6%3.0
(2, 0.0)
3**2, 3**2.0, 3**0j
(9, 9.0, (1+0j))
优先级升序排列如下:
+, -
加和减*, /, //, %
乘,除,整除,取余+x, -x
正,负**
乘方幂运算符 ** 绑定的紧密程度低于在其右侧的算术:
1 + -20 * 4**-1
-4.0
为了易读,应该多使用小括号:
1 + (-20) * 4**(-1)
-4.0
Python 中处理文本数据使用 str 类型对象,也称为字符串。
type('abc')
str
字符串是由 Unicode 码位构成的不可变序列。每个字符的 Unicode 码位可由内建函数 ord() 查看:
ord('a'), ord('b'), ord('c')
(97, 98, 99)
内建函数 str() 可将其他类型对象转换为字符串:
str(3.14)
'3.14'
字符串有多种不同写法:
单引号标示法,如果字符串中有单引号,需要用 \'
表示:
'it\'s a book'
"it's a book"
双引号标示法,如果字符串中有双引号,需要用 \"
表示:
"it's a \"book\""
'it\'s a "book"'
三重引号标示法,可以是三重单引号 '''
,也可以是三重双引号 """
,字符串中的单引号或双引号不受影响,但不能紧挨着:
# 注意最后四个双引号中有一个空格
'''it's a book''', \
"""it's a "book" """
("it's a book", 'it\'s a "book" ')
三重引号标示的字符串可以换行,自动以 \n
表示:
'''
it's a
book
'''
"\nit's a \nbook\n"
若不想引入 \n
,可以使用续航符 \
:
'''\
it's a \
book\
'''
"it's a book"
字符串可带前缀 u(或 U),r(或 R),f(或 F)。
u 表示 Unicode 编码字符串(默认,可省略);r 表示原始字符串,其中的反斜杠会被当作其本身来处理;f 表示格式化字符串字面值。r 和 f 可连用。
'a\nb{1+1}'
'a\nb{1+1}'
r'a\nb{1+1}'
'a\\nb{1+1}'
f'a\nb{1+1}'
'a\nb2'
rf'a\nb{1+1}'
'a\\nb2'
注意带前缀 b(或 B),表示字节串对象:
type(b'abc')
bytes
字符串是不可变序列,下列切片操作得到的是原来的字符串:
a = 'abc'
b = a[:]
a is b
True
相邻的两个字符串,无论中间隔了多少个空格(包括 0 个),都会自动连接到一起:
'Py''thon', 'Py' 'thon'
('Python', 'Python')
甚至可以用 () 包围实现换行拼接,这在字符串(或正则表达式)很长时非常有用:
('Py'
f'thon{3}'
r'\Go')
'Python3\\Go'
+
拼接运算符 +
拼接字符串,和空格类似,但 +
拼接字符串可以是变量的形式:
a = 'Py'
b = 'thon'
'Py' + b, a + b
('Python', 'Python')
运算符 +
还可以和赋值运算符 =
连用,拼接字符串的同时进行赋值:
# 将 a 和 b 拼接,赋值给 a
a += b
print(a)
# 将 b 和 a 拼接,赋值给 b
b += a
b
Python
'thonPython'
转义字符 \
本身不被当作字符,如果要表示一个字符 \
,需要自己将自己转义:
'\\'
'\\'
'\'
File "<ipython-input-2-d44a383620ab>", line 1
'\'
^
SyntaxError: EOL while scanning string literal
上面这一行报错信息是 SyntaxError: EOL while scanning string literal。这是因为 \'
表示的是单引号字符 '
(Literal)—— 是可被输出到屏幕的 '
,而不是用来标示字符串的那个 '
—— 别急,无论哪个初学者第一次读到前面的句子都觉得有点莫名其妙…… —— 于是,Python 编译器扫描这个 “字符串” 的时候,还没找到标示字符串末尾的另外一个 '
的时候就读到了 EOL(End Of Line)。
如果你想输出这么个字符串,He said, it’s fine.,如果用双引号扩起来 "
倒没啥问题,但是如果用单引号扩起来就麻烦了,因为编译器会把 it 后面的那个单引号 '
当作字符串结尾。
'He said, it's fine.'
File "<ipython-input-3-2bcf2ca6dd95>", line 1
'He said, it's fine.'
^
SyntaxError: invalid syntax
于是你就得用转义符 \
:
# 要么你这么写:
print('He said, it\'s fine.')
# 要么你这么写:
print("He said, it's fine.")
# 要么,不管用单引号还是双引号标示字符串,
# 都习惯于用 \' 和 \" 书写属于字符串内部的引号……
"He said, it\'s fine."
He said, it's fine.
He said, it's fine.
"He said, it's fine."
转义字符 \
可与其他字符组合成有特殊含义的字符:
转义字符 | 说明 |
---|---|
\(在行尾时) |
续行符 |
\\ |
反斜杠符号 |
\' |
单引号 |
\" |
双引号 |
\a |
响铃 |
\b |
退格 |
\n |
换行 |
\v |
纵向制表符 |
\t |
横向制表符 |
\r |
回车 |
\f |
换页 |
\yy |
八进制数 yy 码位的字符 |
\xyy |
十六进制数 yy 码位的字符 |
续航符,可以将两行代码(或字符串)连接起来,表示一行:
for i in \
range(3): # 两行相当于 for i in range(10):
print(i)
0
1
2
'hello \
world'
'hello world'
八进制和十六进制字符举例:
# 八进制字符
'\101', '\102'
('A', 'B')
# 十六进制字符
'\x41', '\x42'
('A', 'B')
# 十进制
chr(65),chr(66)
('A', 'B')
在正则表达式中,转义字符 \
的应用更加普遍。详情请看《正则指引》。
字符串方法 str.count(),Python 官方文档描述如下:
help(str.count)
Help on method_descriptor:
count(...)
S.count(sub[, start[, end]]) -> int
Return the number of non-overlapping occurrences of substring sub in
string S[start:end]. Optional arguments start and end are
interpreted as in slice notation.
返回回子字符串 sub 在 [start, end] 范围内非重叠出现的次数。可选参数 start 与 end 会被解读为切片表示法。
只给定 sub 一个参数的话,于是从第一个字符开始搜索到字符串结束;如果,随后给定了一个可选参数的话,那么它是 start,于是从 start 开始,搜索到字符串结束;如果 start 之后还有参数的话,那么它是 end;于是从 start 开始,搜索到 end - 1 结束(即不包含索引值为 end 的那个字符)。
'python'.count('0')
0
'pyyython'.count('yy')
1
'pythonpythonn'.count('n',5)
3
'pythonpythonn'.count('n',5,7)
1
字符串方法 str.replace(),Python 官方文档描述如下:
help(str.replace)
Help on method_descriptor:
replace(self, old, new, count=-1, /)
Return a copy with all occurrences of substring old replaced by new.
count
Maximum number of occurrences to replace.
-1 (the default value) means replace all occurrences.
If the optional argument count is given, only the first count occurrences are
replaced.
返回字符串的副本,其中出现的所有子字符串 old 都将被替换为 new。如果给出了可选参数 count,则只替换前 count 次出现。
'python python'.replace('p','C')
'Cython Cython'
'python python'.replace('py','Cpy',1)
'Cpython python'
如果 old 为空字符串,则在每个字符之间(包括前后)插入 new:
'python python'.replace('','C')
'CpCyCtChCoCnC CpCyCtChCoCnC'
如果 new 为空字符串,则相当于去除了 old:
'python python'.replace('p','')
'ython ython'
字符串方法 str.expandtabs(),Python 官方文档描述如下:
help(str.expandtabs)
Help on method_descriptor:
expandtabs(self, /, tabsize=8)
Return a copy where all tab characters are expanded using spaces.
If tabsize is not given, a tab size of 8 characters is assumed.
返回字符串的副本,其中所有的制表符会由一个或多个空格替换,具体取决于当前列位置和给定的制表符宽度。每 tabsize 个字符设为一个制表位(默认值 8 时设定的制表位在列 0, 8, 16 依次类推)。
要展开字符串,当前列将被设为零并逐一检查字符串中的每个字符。如果字符为制表符 (\t),则会在结果中插入一个或多个空格符,直到当前列等于下一个制表位。(制表符本身不会被复制。)
如果字符为换行符 (\n) 或回车符 (\r),它会被复制并将当前列重设为零。任何其他字符会被不加修改地复制并将当前列加一,不论该字符在被打印时会如何显示。
'01\t012\t0123\t01234'.expandtabs()
'01 012 0123 01234'
'01\t012\t0123\t01234'.expandtabs(4)
'01 012 0123 01234'
'\n\t01\r2\t0123\t01234'.expandtabs(4)
'\n 01\r2 0123 01234'
字符串方法 str.split(),Python 官方文档描述如下:
help(str.split)
Help on method_descriptor:
split(self, /, sep=None, maxsplit=-1)
Return a list of the words in the string, using sep as the delimiter string.
sep
The delimiter according which to split the string.
None (the default value) means split according to any whitespace,
and discard empty strings from the result.
maxsplit
Maximum number of splits to do.
-1 (the default value) means no limit.
返回一个由字符串内单词组成的列表,使用 sep 作为分隔字符串。如果给出了 sep,则连续的分隔符不会被组合在一起而是被视为分隔空字符串;如果给出了 maxsplit,则最多进行 maxsplit 次拆分(因此,列表最多会有 maxsplit+1 个元素)。如果 maxsplit 未指定或为 -1,则不限制拆分次数(进行所有可能的拆分)。
'a.bc'.split('.')
['a', 'bc']
'a.b.c'.split('.',maxsplit=1)
['a', 'b.c']
'a.b..c'.split('.')
['a', 'b', '', 'c']
'a.b..c'.split('..')
['a.b', 'c']
''.split('.')
['']
如果 sep 未指定或为 None,则会应用另一种拆分算法:连续的空格会被视为单个分隔符,如果字符串包含前缀或后缀空格,其结果将不包含开头或末尾的空字符串。因此,使用 None 拆分空字符串或仅包含空格的字符串将返回 []。
'a b c '.split()
['a', 'b', 'c']
' \n '.split()
[]
''.split()
[]
字符串方法 str.rsplit(),Python 官方文档描述如下:
help(str.rsplit)
Help on method_descriptor:
rsplit(self, /, sep=None, maxsplit=-1)
Return a list of the words in the string, using sep as the delimiter string.
sep
The delimiter according which to split the string.
None (the default value) means split according to any whitespace,
and discard empty strings from the result.
maxsplit
Maximum number of splits to do.
-1 (the default value) means no limit.
Splits are done starting at the end of the string and working to the front.
返回一个由字符串内单词组成的列表,使用 sep 作为分隔字符串。如果给出了 maxsplit,则最多进行 maxsplit 次拆分,从 最右边开始。如果 sep 未指定或为 None,任何空白字符串都会被作为分隔符。除了从右边开始拆分,rsplit() 的其他行为都类似于 split()。
'p\nyth on '.rsplit()
['p', 'yth', 'on']
'p\nyth on'.rsplit('y')
['p\n', 'th on']
'p\nyth on'.rsplit(maxsplit=1)
['p\nyth', 'on']
'p\nyth on '.rsplit(maxsplit=2)
['p', 'yth', 'on']
多个分隔符在一起,则会解读为拆分空字符串:
'\n\np\nyth on'.rsplit('\n')
['', '', 'p', 'yth on']
字符串方法 str.partition(),Python 官方文档描述如下:
help(str.partition)
Help on method_descriptor:
partition(self, sep, /)
Partition the string into three parts using the given separator.
This will search for the separator in the string. If the separator is found,
returns a 3-tuple containing the part before the separator, the separator
itself, and the part after it.
If the separator is not found, returns a 3-tuple containing the original string
and two empty strings.
在 sep 首次出现的位置拆分字符串,返回一个 3 元组,其中包含分隔符之前的部分、分隔符本身,以及分隔符之后的部分。如果分隔符未找到,则返回的 3 元组中包含字符本身以及两个空字符串。
'python'.partition('m')
('python', '', '')
'python'.partition('th')
('py', 'th', 'on')
'python'.partition('ht')
('python', '', '')
字符串方法 str.rpartition(),Python 官方文档描述如下:
help(str.rpartition)
Help on method_descriptor:
rpartition(self, sep, /)
Partition the string into three parts using the given separator.
This will search for the separator in the string, starting at the end. If
the separator is found, returns a 3-tuple containing the part before the
separator, the separator itself, and the part after it.
If the separator is not found, returns a 3-tuple containing two empty strings
and the original string.
在 sep 最后一次出现的位置拆分字符串,返回一个 3 元组,其中包含分隔符之前的部分、分隔符本身,以及分隔符之后的部分。如果分隔符未找到,则返回的 3 元组中包含两个空字符串以及字符串本身。
'python'.rpartition('n')
('pytho', 'n', '')
'pythhhon'.rpartition('hh')
('pyth', 'hh', 'on')
分隔符未找到,则返回的 3 元组中 字符串本身 排在最后:
'python'.rpartition('ht')
('', '', 'python')
字符串方法 str.splitlines(),Python 官方文档描述如下:
help(str.splitlines)
Help on method_descriptor:
splitlines(self, /, keepends=False)
Return a list of the lines in the string, breaking at line boundaries.
Line breaks are not included in the resulting list unless keepends is given and
true.
返回由原字符串中各行组成的列表,在行边界的位置拆分。结果列表中不包含行边界,除非给出了 keepends 且为真值。
此方法会以下列行边界进行拆分。特别地,行边界是 universal newlines 的一个超集。
\n
换行\r
回车\r\n
回车 + 换行\v
或 \x0b
行制表符\f
或 \x0c
换表单\x1c
文件分隔符\x1d
组分隔符\x1e
记录分隔符\x85
下一行\u2028
行分隔符\u2029
段分隔符'ab c\n\nde fg\rkl\r\n'.splitlines()
['ab c', '', 'de fg', 'kl']
'ab c\n\nde fg\rkl\r\n'.splitlines(keepends=True)
['ab c\n', '\n', 'de fg\r', 'kl\r\n']
分隔空字符串此方法将返回一个空列表;末尾的换行不会令结果中增加额外的空字符串:
''.splitlines()
[]
"One line\nTwo lines\n".splitlines()
['One line', 'Two lines']
'One line\nTwo lines\n'.split('\n')
['One line', 'Two lines', '']
字符串方法 str.strip(),Python 官方文档描述如下:
help(str.strip)
Help on method_descriptor:
strip(self, chars=None, /)
Return a copy of the string with leading and trailing whitespace remove.
If chars is given and not None, remove characters in chars instead.
返回原字符串的副本,移除其中的前导和末尾字符。chars 参数为指定要移除字符的字符串。如果省略或为 None,则 chars 参数默认移除空格符。实际上 chars 参数并非指定单个前缀或后缀;而是会移除参数值中的所有字符:
' python '.strip()
'python'
' python '.strip('p')
' python '
' python '.strip('p n')
'ytho'
' pythonnnn '.strip('p n')
'ytho'
字符串方法 str.lstrip(),Python 官方文档描述如下:
help(str.lstrip)
Help on method_descriptor:
lstrip(self, chars=None, /)
Return a copy of the string with leading whitespace removed.
If chars is given and not None, remove characters in chars instead.
返回原字符串的副本,移除其中的前导字符。chars 参数为指定要移除字符的字符串。如果省略或为 None,则 chars 参数默认移除空格符。实际上 chars 参数并非指定单个前缀;而是会移除参数值中出现的所有字符:
' python '.lstrip()
'python '
' python '.lstrip('y p')
'thon '
' python '.lstrip('py')
' python '
'ppppython '.lstrip('y p')
'thon '
字符串方法 str.rstrip(),Python 官方文档描述如下:
help(str.rstrip)
Help on method_descriptor:
rstrip(self, chars=None, /)
Return a copy of the string with trailing whitespace removed.
If chars is given and not None, remove characters in chars instead.
返回原字符串的副本,移除其中的末尾字符。chars 参数为指定要移除字符的字符串。如果省略或为 None,则 chars 参数默认移除空格符。实际上 chars 参数并非指定单个后缀;而是会移除参数值中的所有字符串:
' python '.rstrip()
' python'
' python '.rstrip('n o')
' pyth'
' python '.rstrip('n')
' python '
' pythonnnnn'.rstrip('no')
' pyth'
字符串方法 str.find(),Python 官方文档描述如下:
help(str.find)
Help on method_descriptor:
find(...)
S.find(sub[, start[, end]]) -> int
Return the lowest index in S where substring sub is found,
such that sub is contained within S[start:end]. Optional
arguments start and end are interpreted as in slice notation.
Return -1 on failure.
返回子字符串 sub 在 s[start:end] 切片内被找到的最小索引。可选参数 start 与 end 会被解读为切片表示法。如果 sub 未被找到则返回 -1。
只给定 sub 一个参数的话,于是从第一个字符开始搜索到字符串结束;如果,随后给定了一个可选参数的话,那么它是 start,于是从 start 开始,搜索到字符串结束;如果 start 之后还有参数的话,那么它是 end;于是从 start 开始,搜索到 end - 1 结束(即不包含索引值为 end 的那个字符)。
'pythonpython'.find('y')
1
'pythonpython'.find('pt')
-1
'pythonpython'.find('y',5)
7
'pythonpython'.find('y',5,7)
-1
字符串方法 str.rfind(),Python 官方文档描述如下:
help(str.rfind)
Help on method_descriptor:
rfind(...)
S.rfind(sub[, start[, end]]) -> int
Return the highest index in S where substring sub is found,
such that sub is contained within S[start:end]. Optional
arguments start and end are interpreted as in slice notation.
Return -1 on failure.
返回子字符串 sub 在字符串内被找到的最大(最右)索引,这样 sub 将包含在 s[start:end] 当中。可选参数 start 与 end 会被解读为切片表示法。如果未找到则返回 -1。
只给定 sub 一个参数的话,于是从第一个字符开始搜索到字符串结束;如果,随后给定了一个可选参数的话,那么它是 start,于是从 start 开始,搜索到字符串结束;如果 start 之后还有参数的话,那么它是 end;于是从 start 开始,搜索到 end - 1 结束(即不包含索引值为 end 的那个字符)。
'python python'.rfind('on')
11
'python python'.rfind('on',1,7)
4
'python python'.rfind('on',7)
11
'python python'.rfind('no')
-1
字符串方法 str.index(),Python 官方文档描述如下:
help(str.index)
Help on method_descriptor:
index(...)
S.index(sub[, start[, end]]) -> int
Return the lowest index in S where substring sub is found,
such that sub is contained within S[start:end]. Optional
arguments start and end are interpreted as in slice notation.
Raises ValueError when the substring is not found.
返回子字符串 sub 在 s[start:end] 切片内被找到的最小索引。可选参数 start 与 end 会被解读为切片表示法。类似于 find(),但在找不到 sub 时会引发 ValueError。
只给定 sub 一个参数的话,于是从第一个字符开始搜索到字符串结束;如果,随后给定了一个可选参数的话,那么它是 start,于是从 start 开始,搜索到字符串结束;如果 start 之后还有参数的话,那么它是 end;于是从 start 开始,搜索到 end - 1 结束(即不包含索引值为 end 的那个字符)。
'pythonpython'.index('y')
1
'pythonpython'.index('pt')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-3-4252de1acf66> in <module>
----> 1 'pythonpython'.index('pt')
ValueError: substring not found
'pythonpython'.index('y',5)
7
'pythonpython'.index('y',5,7)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-5-35705122f03a> in <module>
----> 1 'pythonpython'.index('y',5,7)
ValueError: substring not found
字符串方法 str.rindex(),Python 官方文档描述如下:
help(str.rindex)
Help on method_descriptor:
rindex(...)
S.rindex(sub[, start[, end]]) -> int
Return the highest index in S where substring sub is found,
such that sub is contained within S[start:end]. Optional
arguments start and end are interpreted as in slice notation.
Raises ValueError when the substring is not found.
返回子字符串 sub 在字符串内被找到的最大(最右)索引,这样 sub 将包含在 s[start:end] 当中。可选参数 start 与 end 会被解读为切片表示法。如果未找到则返回 -1。类似于 rfind(),但在子字符串 sub 未找到时会引发 ValueError。
只给定 sub 一个参数的话,于是从第一个字符开始搜索到字符串结束;如果,随后给定了一个可选参数的话,那么它是 start,于是从 start 开始,搜索到字符串结束;如果 start 之后还有参数的话,那么它是 end;于是从 start 开始,搜索到 end - 1 结束(即不包含索引值为 end 的那个字符)。
'python python'.rindex('on')
11
'python python'.rindex('on',1,7)
4
'python python'.rindex('on',7)
11
'python python'.rindex('no')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-5-92aeb174dba9> in <module>
----> 1 'python python'.rindex('no')
ValueError: substring not found
字符串方法 str.join(),Python 官方文档描述如下:
help(str.join)
Help on method_descriptor:
join(self, iterable, /)
Concatenate any number of strings.
The string whose method is called is inserted in between each given string.
The result is returned as a new string.
Example: '.'.join(['ab', 'pq', 'rs']) -> 'ab.pq.rs'
返回一个由 iterable 中的字符串拼接而成的字符串。如果 iterable 中存在任何非字符串值则会引发 TypeError。调用该方法的字符串将作为元素之间的分隔。
'~'.join('abc')
'a~b~c'
'acb'.join(['1','2'])
'1acb2'
''.join(['1','2'])
'12'
'-'.join({'1':1,'2':2})
'1-2'
'-'.join(['1',2])
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-9-fc346e5ca62e> in <module>
----> 1 '-'.join(['1',2])
TypeError: sequence item 1: expected str instance, int found
'-'.join(b'abc')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-8-9d04d7060926> in <module>
----> 1 '-'.join(b'abc')
TypeError: sequence item 0: expected str instance, int found
字符串方法 str.startswith(),Python 官方文档描述如下:
help(str.startswith)
Help on method_descriptor:
startswith(...)
S.startswith(prefix[, start[, end]]) -> bool
Return True if S starts with the specified prefix, False otherwise.
With optional start, test S beginning at that position.
With optional end, stop comparing S at that position.
prefix can also be a tuple of strings to try.
如果字符串以指定的 prefix 开始则返回 True,否则返回 False。prefix 也可以为由多个供查找的前缀构成的元组。如果有可选项 start,将从所指定位置开始检查。如果有可选项 end,将在所指定位置之前停止比较。
'a.b.a.c'.startswith('ab')
False
'a.b.a.c'.startswith('a.')
True
'a.b.a.c'.startswith('ab',2)
False
'a.b.a.c'.startswith('a.',4)
True
'a.b.a.c'.startswith('a',1,4)
False
字符串方法 str.endswith(),Python 官方文档描述如下:
help(str.endswith)
Help on method_descriptor:
endswith(...)
S.endswith(suffix[, start[, end]]) -> bool
Return True if S ends with the specified suffix, False otherwise.
With optional start, test S beginning at that position.
With optional end, stop comparing S at that position.
suffix can also be a tuple of strings to try.
如果字符串以指定的 suffix 结束返回 True,否则返回 False。suffix 也可以为由多个供查找的后缀构成的元组。如果有可选项 start,将从所指定位置开始检查。如果有可选项 end,将在所指定位置之前停止比较。
'python.exe'.endswith('.exe')
True
'python.exe'.endswith(('.exe','.txt'), 5)
True
'python.exe'.endswith(('.py','.txt'), 5)
False
'python.exe'.endswith(('.exe','.txt'), 5,9)
False
字符串方法 str.ljust(),Python 官方文档描述如下:
help(str.ljust)
Help on method_descriptor:
ljust(self, width, fillchar=' ', /)
Return a left-justified string of length width.
Padding is done using the specified fill character (default is a space).
返回长度为 width 的字符串,原字符串在其中靠左对齐。使用指定的 fillchar 填充空位 (默认使用 ASCII 空格符)。如果 width 小于等于字符串长度 len(str) 则返回原字符串的副本。
'python'.ljust(1)
'python'
'python'.ljust(10,'~')
'python~~~~'
'python'.ljust(10)
'python '
字符串方法 str.center(),Python 官方文档描述如下:
help(str.center)
Help on method_descriptor:
center(self, width, fillchar=' ', /)
Return a centered string of length width.
Padding is done using the specified fill character (default is a space).
返回长度为 width 的字符串,原字符串在其正中。使用指定的 fillchar 填充两边的空位(默认使用ASCII 空格符)。如果 width 小于等于字符串长度,则返回原字符串的副本:
'Python'.center(1)
'Python'
'Python'.center(10)
' Python '
'Python'.center(20,'~')
'~~~~~~~Python~~~~~~~'
字符串方法 str.rjust(),Python 官方文档描述如下:
help(str.rjust)
Help on method_descriptor:
rjust(self, width, fillchar=' ', /)
Return a right-justified string of length width.
Padding is done using the specified fill character (default is a space).
返回长度为 width 的字符串,原字符串在其中靠右对齐。使用指定的 fillchar 填充空位 (默认使用 ASCII 空格符)。如果 width 小于等于字符串长度 len(str) 则返回原字符串的副本。
'python'.rjust(1)
'python'
'python'.rjust(10,'~')
'~~~~python'
'python'.rjust(10)
' python'
字符串方法 str.format(),Python 官方文档描述如下:
help(str.format)
Help on method_descriptor:
format(...)
S.format(*args, **kwargs) -> str
Return a formatted version of S, using substitutions from args and kwargs.
The substitutions are identified by braces ('{' and '}').
执行字符串格式化操作。调用此方法的字符串可以包含字符串字面值或者以花括号 {} 括起来的替换域。每个替换域可以包含一个位置参数的数字索引,或者一个关键字参数的名称。返回的字符串副本中每个替换域都会被替换为对应参数的字符串值。
"The sum of 1 + 2 is {0}".format(1+2)
'The sum of 1 + 2 is 3'
如果你需要在字面文本中包含花括号字符,可以通过重复来转义:
"{{python}}".format()
'{python}'
位置传参和关键字传参方式非常灵活,多个位置索引依次为 0,1,2……,且可以不插入字符串中;关键字传参则需要将关键字插入字符串中:
'{} and {} are both {age} years old.\
'.format('A','B',age=18)
'A and B are both 18 years old.'
'{1} and {0} are both {age} years old.\
'.format('A','B',age=18)
'B and A are both 18 years old.'
'{age} and {} are both {} years old.\
'.format('A','B',age=18)
'18 and A are both B years old.'
'{0} and {0} are both {0} years old.\
'.format('A','B',age=18)
'A and A are both A years old.'
通常,格式化值的工作由值本身的 __format__()
方法来完成。但是,在某些情况下最好强制将类型格式化为一个字符串,覆盖其本身的格式化定义。通过在调用 __format__()
之前将值转换为字符串,可以绕过正常的格式化逻辑。
目前支持的转换旗标有三种: ‘!s’ 会对值调用 str(),’!r’ 调用 repr() 而 ‘!a’ 则调用 ascii()。
'{1!s} and {0!r} are both {age!a} years old.\
'.format('A','B',age=18)
"B and 'A' are both 18 years old."
可以包含值应如何呈现的规格描述,例如字段宽度、对齐、填充、小数精度等细节信息。每种值类型可以定义自己的 “格式化迷你语言” 或解读方式。
# 复数格式化
('The complex number {0} is formed'
' from the real part {0.real} '
'and the imaginary part {0.imag}.').format(3-5j)
'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.'
# 利用索引取出某项格式化,不可切片
'X: {0[0]}; Y: {0[1]}'.format([1,2,3])
'X: 1; Y: 2'
# 切片格式化
a = [1,2,3]
'X: {0}; Y: {1}'.format(a[:2],a[-2:])
'X: [1, 2]; Y: [2, 3]'
# 右对齐
'{:>20}'.format('right aligned')
' right aligned'
# 填充 ~ 居中
'{:~^20}'.format('centered')
'~~~~~~centered~~~~~~'
# 更复杂的排版
for i, w in zip('<^>', ['left', 'center', 'right']):
print('{0:{fill}{align}20}'.format(w, fill=i, align=i))
left<<<<<<<<<<<<<<<<
^^^^^^^center^^^^^^^
>>>>>>>>>>>>>>>right
# 数字前填充 0
'{:05}'.format(12)
'00012'
# 设置保留精度
'{:f}; {:+.1f}'.format(3.14, -3.14)
'3.140000; -3.1'
# 各种进制格式化
"int: {0:d}; hex: {0:x}; oct: {0:o}; \
bin: {0:b}".format(42)
'int: 42; hex: 2a; oct: 52; bin: 101010'
# 保留进制前缀
"int: {0:d}; hex: {0:#x}; oct: {0:#o}; \
bin: {0:#b}".format(42)
'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010'
# 让数字更易读
'{:,}'.format(1234567890)
'1,234,567,890'
# 百分比格式化
'Correct answers: {:.2%}'.format(5/6)
'Correct answers: 83.33%'
# 特定类型的专属格式化
import datetime
d = datetime.datetime(2010, 7, 4, 12, 15, 58)
'{:%Y-%m-%d %H:%M:%S}'.format(d)
'2010-07-04 12:15:58'
# IP地址格式化
octets = [192, 168, 0, 1]
'{:02X}{:02X}{:02X}{:02X}'.format(*octets)
'C0A80001'
各种对齐选项的含义:
仅对数字类型有效选项:
确定了数据应如何呈现:
字符串方法 str.format_map(),Python 官方文档描述如下:
help(str.format_map)
Help on method_descriptor:
format_map(...)
S.format_map(mapping) -> str
Return a formatted version of S, using substitutions from mapping.
The substitutions are identified by braces ('{' and '}').
类似于 str.format(**mapping),不同之处在于 mapping 会被直接使用。适宜使用此方法的一个例子是当 mapping 为 dict 的子类的情况:
# 创建一个字典子类型,当 键值对 不存在时,返回键
class Default(dict):
def __missing__(self, key):
return key
d = Default(a=1)
d['a'], d['b']
(1, 'b')
# country 键值对不存在,所以直接格式化键 ‘country’
'{name} was born in {country}'.format_map(
Default(name='Guido'))
'Guido was born in country'
与 format 格式化对比:
'{a} is {age}'.format_map({'a':'A', 'age':18})
'A is 18'
'{a} is {age}'.format(**{'a':'A', 'age':18})
'A is 18'
f-string 即格式化字符串字面值。字符串以 ‘f’ 或 ‘F’ 为前缀。这种字符串可包含替换字段,即以 {} 标示的表达式。格式化字符串字面值,会在运行时将表达式求值,而其他字符串字面值总是一个常量。
格式化字符串字面值中的表达式会被当作包含在圆括号中的普通 Python 表达式一样处理,但有少数例外。
空表达式不被允许,lambda 和赋值表达式 :=(python 3.8版添加)必须显式地加上圆括号。
f'{(a := 1+1)}' # python 3.8 才能运行
'2'
f'{(lambda x:1)}'
'<function <lambda> at 0x000001D70B06CA60>'
替换表达式可以包含换行(例如在三重引号字符串中),但是不能包含注释。
a = 3; b = 2
f'''3+2\
-5=
{a +
b - 5}'''
'3+2-5=\n0'
每个表达式会在格式化字符串字面值所包含的位置按照从左至右的顺序被求值。
f'{1+2 > 3}'
'False'
可以在表达式后加一个等于号 ‘=’(3.8 新版功能),提供了等于号 ‘=’ 的时候,输出将包含 ‘=’、’=’ 前后的空格以及求值结果。默认情况下,’=’ 会导致表达式的 repr() 被使用,除非专门指定了格式。
foo = "bar"
f"{ foo = }"
" foo = 'bar'"
可以带一个以叹号 ‘!’ 标示的转换字段,转换符 ‘!s’ 即对结果调用 str(),’!r’ 为调用 repr(),而 ‘!a’ 为调用 ascii()。
foo = "bar"
f"{foo = !s}"
'foo = bar'
还可带一个以冒号 ‘:’ 标示的格式说明符,“格式化迷你语言” 与 str.format() 方法所使用的微语言一致,详见 str.format 方法。
foo = 3.14
f"{foo:.4f}"
'3.1400'
f'{123:#o}'
'0o173'
a=5/6
f'{a:.2%}'
'83.33%'
格式表达式中不允许有反斜杠,这会引发错误:
f"newline: {ord('\n')}"
File "<ipython-input-23-30c78f70325d>", line 1
f"newline: {ord('\n')}"
^
SyntaxError: f-string expression part cannot include a backslash
想包含需要用反斜杠转义的值,可以创建一个临时变量:
newline = ord('\n')
f"newline: {newline}"
'newline: 10'
格式化字符串字面值不可用作文档字符串,即便其中没有包含表达式:
def foo():
f"Not a docstring"
print(foo.__doc__)
None
*
操作符 *
可以实现将字符串重复 n(整数)遍相连接:
'Python' * 3
'PythonPythonPython'
n 是小于 1 的整数,则得到空字符串:
'Python' * -1
''
*
操作符可以与 =
连用,重复拼接并赋值:
a = 'py'
a *= 3
a
'pypypy'
由于字符串是可迭代对象,因此可以使用 *
对字符串进行拆包:
(*'Python',)
('P', 'y', 't', 'h', 'o', 'n')
%
字符串使用 %
操作符,官方文档叫 “printf 风格的字符串格式化”。比较早的格式化方法,官方已不推荐使用,了解它能更好地读懂别人的代码。
转换标记符包含两个或更多字符并具有以下组成,且必须遵循如下规定的顺序:
'hi %r' % 'python'
"hi 'python'"
'%s %r' % ('hi','python')
"hi 'python'"
转换旗标为:
标志 | 含义 |
---|---|
‘#’ | 值的转换将使用“替代形式”。 |
‘0’ | 转换将为数字值填充零字符。 |
‘-’ | 转换值将靠左对齐(如果同时给出 ‘0’ 转换,则会覆盖后者)。 |
’ ' | (空格) 符号位转换产生的正数(或空字符串)前将留出一个空格。 |
‘+’ | 符号字符 (’+’ 或 ‘-’) 将显示于转换结果的开头(会覆盖 ”空格” 旗标)。 |
'A is %#x' % 18
'A is 0x12'
'A is % d' % 18
'A is 18'
'A is %05o' % 18
'A is 00022'
转换类型为:
转换符 | 含义 |
---|---|
’d’ | 有符号十进制整数。 |
‘i’ | 有符号十进制整数。 |
‘o’ | 有符号八进制数。 |
‘x’ | 有符号十六进制数(小写)。 |
‘X’ | 有符号十六进制数(大写)。 |
’e’ | 浮点指数格式(小写)。 |
‘E’ | 浮点指数格式(大写)。 |
‘f’ | 浮点十进制格式。 |
‘F’ | 浮点十进制格式。 |
‘g’ | 浮点格式。如果指数小于 -4 或不小于精度则使用小写指数格式,否则使用十进制格式。 |
‘G’ | 浮点格式。如果指数小于 -4 或不小于精度则使用大写指数格式,否则使用十进制格式。 |
‘c’ | 单个字符(接受整数或单个字符的字符串)。 |
‘r’ | 字符串(使用repr() 转换任何 Python 对象)。 |
’s’ | 字符串(使用str() 转换任何 Python 对象)。 |
‘a’ | 字符串(使用ascii() 转换任何 Python 对象)。 |
‘%’ | 不转换参数,在结果中输出一个 ‘%’ 字符。 |
'%f' % 3.14
'3.140000'
'%.3e' % 3.14
'3.140e+00'
'%.1f%%' % (3.14*100)
'314.0%'
当右边的参数为一个字典(或其他映射类型)时,字符串中的格式 必须包含加圆括号的映射键,对应 %
字符之后字典中的每一项。映射键将从映射中选取要格式化的值:
'%(language)s has %(number)03d quote types.' %\
{'language': "Python", "number": 2}
'Python has 002 quote types.'
字符串方法 str.encode(),Python 官方文档描述如下:
help(str.encode)
Help on method_descriptor:
encode(self, /, encoding='utf-8', errors='strict')
Encode the string using the codec registered for encoding.
encoding
The encoding in which to encode the string.
errors
The error handling scheme to use for encoding errors.
The default is 'strict' meaning that encoding errors raise a
UnicodeEncodeError. Other possible values are 'ignore', 'replace' and
'xmlcharrefreplace' as well as any other name registered with
codecs.register_error that can handle UnicodeEncodeErrors.
返回原字符串编码为字节串对象的版本。默认编码为 ‘utf-8’。可以给出 errors 来设置不同的错误处理方案。errors 的默认值为 ‘strict’,表示编码错误会引发 UnicodeError。
下列为 ‘utf-8’ 和 ‘gbk’ 两种编码比较:
'嗨 python'.encode()
b'\xe5\x97\xa8 python'
'嗨 python'.encode('gbk')
b'\xe0\xcb python'
'▲ python'.encode('gbk')
b'\xa1\xf8 python'
'🔺 python'.encode()
b'\xf0\x9f\x94\xba python'
'🔺 python'.encode('gbk') #gbk 不能编码 🔺
---------------------------------------------------------------------------
UnicodeEncodeError Traceback (most recent call last)
<ipython-input-15-60e87a9208be> in <module>
----> 1 '🔺 python'.encode('gbk')
UnicodeEncodeError: 'gbk' codec can't encode character '\U0001f53a' in position 0: illegal multibyte sequence
拓展:
将字节串解码为字符串用 bytes.decode:
help(bytes.decode)
[1;31mSignature:[0m [0mbytes[0m[1;33m.[0m[0mdecode[0m[1;33m([0m[0mself[0m[1;33m,[0m [1;33m/[0m[1;33m,[0m [0mencoding[0m[1;33m=[0m[1;34m'utf-8'[0m[1;33m,[0m [0merrors[0m[1;33m=[0m[1;34m'strict'[0m[1;33m)[0m[1;33m[0m[1;33m[0m[0m
[1;31mDocstring:[0m
Decode the bytes using the codec registered for encoding.
encoding
The encoding with which to decode the bytes.
errors
The error handling scheme to use for the handling of decoding errors.
The default is 'strict' meaning that decoding errors raise a
UnicodeDecodeError. Other possible values are 'ignore' and 'replace'
as well as any other name registered with codecs.register_error that
can handle UnicodeDecodeErrors.
[1;31mType:[0m method_descriptor
b'\xf0\x9f\x94\xba python'.decode()
'🔺 python'
字符串方法 str.capitalize(),Python 官方文档描述如下:
help(str.capitalize)
Help on method_descriptor:
capitalize(self, /)
Return a capitalized version of the string.
More specifically, make the first character have upper case and the rest lower
case.
返回原字符串的副本,其首个字符大写,其余为小写:
'pyTHON'.capitalize()
'Python'
只有首个字符是字母,才会将首个字符大写:
'嗨 pyTHON'.capitalize()
'嗨 python'
字符串方法 str.casefold(),Python 官方文档描述如下:
help(str.casefold)
Help on method_descriptor:
casefold(self, /)
Return a version of the string suitable for caseless comparisons.
返回原字符串消除大小写的副本。消除大小写的字符串可用于忽略大小写的匹配。
消除大小写类似于转为小写,但是更加彻底一些,因为它会移除字符串中的所有大小写变化形式。例如,德语小写字母 ‘ß’ 相当于 “ss”,由于它已经是小写,lower() 不会对 ‘ß’ 做任何改变,而 casefold() 则会将其转换为 “ss”。
'pYthOn'.casefold()
'python'
'ß'.casefold()
'ss'
'ß'.lower()
'ß'
字符串方法 str.lower(),Python 官方文档描述如下:
help(str.lower)
Help on method_descriptor:
lower(self, /)
Return a copy of the string converted to lowercase.
返回原字符串的副本,其所有区分大小写的字符均转换为小写。
'PyThon'.lower()
'python'
'嗨 PyThon'.lower()
'嗨 python'
'PyThon Γ'.lower()
'python γ'
字符串方法 str.title(),Python 官方文档描述如下:
help(str.title)
Help on method_descriptor:
title(self, /)
Return a version of the string where each word is titlecased.
More specifically, words start with uppercased characters and all remaining
cased characters have lower case.
返回原字符串的标题版本,其中每个单词第一个字母为大写,其余字母为小写。
'hi python'.title()
'Hi Python'
'嗨python'.title()
'嗨Python'
该算法使用一种简单的与语言无关的定义,将连续的字母组合视为单词。该定义在多数情况下都很有效,但它也意味着代表缩写形式与所有格的撇号也会成为单词边界,这可能导致不希望的结果:
"they're bill's friends from the UK".title()
"They'Re Bill'S Friends From The Uk"
字符串方法 str.upper(),Python 官方文档描述如下:
help(str.upper)
Help on method_descriptor:
upper(self, /)
Return a copy of the string converted to uppercase.
返回原字符串的副本,其中所有区分大小写的字符均转换为大写。
'嗨python'.upper()
'嗨PYTHON'
'πpython'.upper()
'ΠPYTHON'
字符串方法 str.swapcase(),Python 官方文档描述如下:
help(str.swapcase)
Help on method_descriptor:
swapcase(self, /)
Convert uppercase characters to lowercase and lowercase characters to uppercase.
返回原字符串的副本,其中大写字符转换为小写,反之亦然。请注意 s.swapcase().swapcase() == s 并不一定为真值。
'PythoN'.swapcase()
'pYTHOn'
'pYTHOn'.swapcase()
'PythoN'
'ß'.swapcase() # 德语的小写字母 ß 相当于 ss
'SS'
'SS'.swapcase()
'ss'
'ß'.swapcase().swapcase() == 'ß'
False
字符串方法 str.zfill(),Python 官方文档描述如下:
help(str.zfill)
Help on method_descriptor:
zfill(self, width, /)
Pad a numeric string with zeros on the left, to fill a field of the given width.
The string is never truncated.
返回原字符串的副本,在左边填充 ASCII ‘0’ 数码使其长度变为 width。正负值前缀 (’+’/’-’) 的处理方式是在正负符号 之后填充而非在之前。如果 width 小于等于 len(str) 则返回原字符串的副本。
"42a".zfill(5)
'0042a'
"-42".zfill(5)
'-0042'
"-42".zfill(1)
'-42'
文档描述如下:
help(str.translate)
Help on method_descriptor:
translate(self, table, /)
Replace each character in the string using the given translation table.
table
Translation table, which must be a mapping of Unicode ordinals to
Unicode ordinals, strings, or None.
The table must implement lookup/indexing via __getitem__, for instance a
dictionary or list. If this operation raises LookupError, the character is
left untouched. Characters mapped to None are deleted.
返回原字符串的副本,其中每个字符按给定的转换表进行映射。转换表必须是一个使用 __getitem__()
来实现索引操作的对象,通常为 mapping 或 sequence。当以 Unicode 码位序号(整数)为索引时,转换表对象可以做以下任何一种操作:返回 Unicode 序号或字符串,将字符映射为一个或多个字符;返回 None,将字符从结果字符串中删除;或引发 LookupError 异常,将字符映射为其自身。
ord('p'),ord('C')
(112, 67)
'python'.translate({112:67})
'Cython'
'python'.translate({112:'Cp'})
'Cpython'
'python'.translate({112:None})
'ython'
你可以使用 str.maketrans() 基于不同格式的字符到字符映射来创建一个转换映射表。
table = str.maketrans('pto','123')
'python'.translate(table)
'1y2h3n'
字符串方法 str.maketrans(),该方法是一个静态方法(没有 self),Python 官方文档描述如下:
help(str.maketrans)
Help on built-in function maketrans:
maketrans(x, y=None, z=None, /)
Return a translation table usable for str.translate().
If there is only one argument, it must be a dictionary mapping Unicode
ordinals (integers) or characters to Unicode ordinals, strings or None.
Character keys will be then converted to ordinals.
If there are two arguments, they must be strings of equal length, and
in the resulting dictionary, each character in x will be mapped to the
character at the same position in y. If there is a third argument, it
must be a string, whose characters will be mapped to None in the result.
返回一个可供 str.translate() 使用的转换对照表。
如果只有一个参数,则它必须是一个将 Unicode 码位序号(整数)或字符(长度为 1 的字符串)映射到 Unicode 码位序号、(任意长度的)字符串 或 None 的字典。字符键将会被转换为码位序号。
str.maketrans({97:'123'})
{97: '123'}
str.maketrans({'a':97})
{97: 97}
str.maketrans({'a':None})
{97: None}
如果有两个参数,则它们必须是两个长度相等的字符串,并且在结果字典中,x 中每个字符将被映射到 y 中相同位置的字符。
str.maketrans('abc','123')
{97: 49, 98: 50, 99: 51}
如果有第三个参数,它必须是一个字符串,其中的字符将在结果中被映 射到 None。
str.maketrans('ab','12','xy')
{97: 49, 98: 50, 120: None, 121: None}
字符串方法 str.isalnum(),Python 官方文档描述如下:
help(str.isalnum)
Help on method_descriptor:
isalnum(self, /)
Return True if the string is an alpha-numeric string, False otherwise.
A string is alpha-numeric if all characters in the string are alpha-numeric and
there is at least one character in the string.
如果字符串中的所有字符都是字母或数字且至少有一个字符,则返回 True ,否则返回 False 。
''.isalnum()
False
'python123'.isalnum()
True
'python 123'.isalnum()
False
'γ'.isalnum()
True
字符串方法 str.isalpha(),Python 官方文档描述如下:
help(str.isalpha)
Help on method_descriptor:
isalpha(self, /)
Return True if the string is an alphabetic string, False otherwise.
A string is alphabetic if all characters in the string are alphabetic and there
is at least one character in the string.
如果字符串中的所有字符都是字母,并且至少有一个字符,返回 True ,否则返回 False 。
字母字符是指那些在 Unicode 字符数据库中定义为 ”Letter” 的字符,即那些具有 ”Lm”、”Lt”、”Lu”、”Ll” 或 ”Lo” 之一的通用类别属性的字符。注意,这与 Unicode 标准中定义的 ”字母” 属性不同。
此处的字母包括汉字等。
''.isalpha()
False
'γ'.isalpha()
True
'嗨你好'.isalpha()
True
'嗨!你好'.isalpha()
False
字符串方法 str.isdecimal(),Python 官方文档描述如下:
help(str.isdecimal)
Help on method_descriptor:
isdecimal(self, /)
Return True if the string is a decimal string, False otherwise.
A string is a decimal string if all characters in the string are decimal and
there is at least one character in the string.
如果字符串中的所有字符都是十进制字符且该字符串至少有一个字符,则返回 True,否则返回 False。
十进制字符指那些可以用来组成 10 进制数字的字符。严格地讲,十进制字符是 Unicode 通用类别 ”Nd” 中的一个字符。
''.isdecimal()
False
'3.14'.isdecimal()
False
'0123'.isdecimal()
True
'5²'.isdecimal()
False
'python'.isdecimal()
False
b'100'.isdecimal()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-13-52e1682babfd> in <module>
----> 1 b'100'.isdecimal()
AttributeError: 'bytes' object has no attribute 'isdecimal'
字符串方法 str.isdigit(),Python 官方文档描述如下:
help(str.isdigit)
Help on method_descriptor:
isdigit(self, /)
Return True if the string is a digit string, False otherwise.
A string is a digit string if all characters in the string are digits and there
is at least one character in the string.
如果字符串中的所有字符都是数字,并且至少有一个字符,返回 True ,否则返回 False 。
数字包括十进制字符和需要特殊处理的数字,如兼容性上标数字。这包括了不能用来组成 10 进制数的数字,如 Kharosthi 数。严格地讲,数字是指属性值为 Numeric_Type=Digit 或 Numeric_Type=Decimal 的字符。
'一'.isdigit()
False
'3.14'.isdigit()
False
'123'.isdigit()
True
b'123'.isdigit()
True
'5²'.isdigit()
True
字符串方法 str.isnumeric(),Python 官方文档描述如下:
help(str.isnumeric)
Help on method_descriptor:
isnumeric(self, /)
Return True if the string is a numeric string, False otherwise.
A string is numeric if all characters in the string are numeric and there is at
least one character in the string.
如果字符串中至少有一个字符且所有字符均为数值字符则返回 True,否则返回 False。
数值字符包括数字字符,以及所有在 Unicode 中设置了数值特性属性的字符,例如 U+2155, VUL-GAR FRACTION ONE FIFTH。正式的定义为:数值字符就是具有特征属性值 Numeric_Type=Digit, Numeric_Type=Decimal 或 Numeric_Type=Numeric 的字符。
此处所指数字包括罗马数字,汉字数字等。
'②'.isnumeric()
True
'3.14'.isnumeric()
False
'5²'.isnumeric()
True
'Ⅷ'.isnumeric()
True
'一'.isnumeric()
True
'壹'.isnumeric()
True
字符串方法 str.islower(),Python 官方文档描述如下:
help(str.islower)
Help on method_descriptor:
islower(self, /)
Return True if the string is a lowercase string, False otherwise.
A string is lowercase if all cased characters in the string are lowercase and
there is at least one cased character in the string.
如果字符串中至少有一个区分大小写的字符且此类字符均为小写则返回 True,否则返回 False。
'嗨'.islower()
False
'嗨 Abc'.islower()
False
'嗨 abc'.islower()
True
字符串方法 str.isupper(),Python 官方文档描述如下:
help(str.isupper)
Help on method_descriptor:
isupper(self, /)
Return True if the string is an uppercase string, False otherwise.
A string is uppercase if all cased characters in the string are uppercase and
there is at least one cased character in the string.
如果字符串中至少有一个区分大小写的字符且此类字符均为大写则返回 True,否则返回 False。
'Γ'.isupper()
True
'嗨 AB'.isupper()
True
'嗨 Ab'.isupper()
False
字符串方法 str.istitle(),Python 官方文档描述如下:
help(str.istitle)
Help on method_descriptor:
istitle(self, /)
Return True if the string is a title-cased string, False otherwise.
In a title-cased string, upper- and title-case characters may only
follow uncased characters and lowercase characters only cased ones.
如果字符串中至少有一个字符且为标题字符串则返回 True,例如大写字符之后只能带非大写字符而小写字符必须有大写字符打头。否则返回 False。
'Abc Py'.istitle()
True
'嗨 A11'.istitle()
True
'嗨 Abc'.istitle()
True
'嗨 ABC'.istitle()
False
字符串方法 str.isascii(),Python 官方文档描述如下:
help(str.isascii)
Help on method_descriptor:
isascii(self, /)
Return True if all characters in the string are ASCII, False otherwise.
ASCII characters have code points in the range U+0000-U+007F.
Empty string is ASCII too.
如果字符串为空或字符串中的所有字符都是 ASCII ,返回 True,否则返回 False。ASCII 字符的码点范围是 U+0000-U+007F。
''.isascii()
True
'python'.isascii()
True
'python.3'.isascii()
True
'嗨 python'.isascii()
False
字符串方法 str.isidentifier(),Python 官方文档描述如下:
help(str.isidentifier)
Help on method_descriptor:
isidentifier(self, /)
Return True if the string is a valid Python identifier, False otherwise.
Call keyword.iskeyword(s) to test whether string s is a reserved identifier,
such as "def" or "class".
如果字符串是有效的标识符,返回 True,否则返回 False。
''.isidentifier()
False
'1mycode'.isidentifier()
False
'_mycode'.isidentifier()
True
'123'.isidentifier()
False
'_123'.isidentifier()
True
'变量名'.isidentifier()
True
'for'.isidentifier()
True
字符串方法 str.isprintable(),Python 官方文档描述如下:
help(str.isprintable)
Help on method_descriptor:
isprintable(self, /)
Return True if the string is printable, False otherwise.
A string is printable if all of its characters are considered printable in
repr() or if it is empty.
如果字符串中所有字符均为可打印字符或字符串为空则返回 True,否则返回 False。
不可打印字符是在 Unicode 字符数据库中被定义为 ”Other” 或 ”Separator” 的字符,例外情况是 ASCII 空格字符 (0x20) 被视作可打印字符。
请注意在此语境下可打印字符是指当对一个字符串发起调用 repr() 时不必被转义的字符。它们与字符串写入 sys.stdout 或 sys.stderr 时所需的处理无关。
''.isprintable()
True
' '.isprintable()
True
'\n'.isprintable()
False
'\python'.isprintable()
True
'py\thon'.isprintable()
False
字符串方法 str.isspace(),Python 官方文档描述如下:
help(str.isspace)
Help on method_descriptor:
isspace(self, /)
Return True if the string is a whitespace string, False otherwise.
A string is whitespace if all characters in the string are whitespace and there
is at least one character in the string.
如果字符串中只有空白字符且至少有一个字符则返回 True,否则返回 False。
''.isspace()
False
' '.isspace()
True
'\n\t\r\f'.isspace()
True
' \\'.isspace()
False
字符串方法 str.removeprefix()。
3.9 版本新功能。
str.removeprefix(prefix, /),如果字符串以 前缀字符串 prefix 开头,返回 string[len(prefix):],否则,返回原始字符串的副本。
'TestHook'.removeprefix('Test')
'Hook'
'BaseTestCase'.removeprefix('Test')
'BaseTestCase'
字符串方法 str.removesuffix()。
3.9 版本新功能。
str.removesuffix(suffix, /),如果字符串以 后缀字符串 suffix 结尾,并且后缀非空,返回 string[:-len(suffix)],否则,返回原始字符串的副本。
'MiscTests'.removesuffix('Tests')
'Misc'
'TmpDirMixin'.removesuffix('Tests')
'TmpDirMixin'
列表对象 list 是高级数据结构的一种,通过方括号括起、逗号分隔的一组值得到。类型是 list。
type([1,2,3])
list
列表是可变序列,通常用于存放同类项目的集合。但没做限制,可以存放任意对象。
[1,'a',int]
[1, 'a', int]
列表是可变的,分别创建两个值相同的列表,一定是不同的对象;而同一个列表对象中的元素是可以改变的:
a, b = [1,2], [1,2]
a == b
True
id(a), id(b)
(2004948061384, 2004947934152)
a[0] = 'a'
a, id(a)
(['a', 2], 2004948061384)
列表创建方法有:直接用一对方括号表示;列表推导式;或使用内建函数 list()。
[], [1,2]
([], [1, 2])
[i for i in range(3)]
[0, 1, 2]
list('abc')
['a', 'b', 'c']
列表的所有切片都将得到一个新列表,这意味着以下切片操作会返回列表的一个浅拷贝:
list_1 = [1,2,3]
list_2 = list_1[:]
id(list_1), id(list_2)
(2004947038600, 2004948064968)
然而,列表可以利用切片改变自身的内容,列表仍然是原来的列表:
list_1[:] = 'abc'
list_1, id(list_1)
(['a', 'b', 'c'], 2004947038600)
列表推导式提供了一个更简单的创建列表的方法。常见的用法是把某种操作应用于序列或可迭代对象的每个元素上,然后使用其结果来创建列表,或者通过满足某些特定条件元素来创建子序列。
对比下列两种创建数值平方列表的方式:
squares = []
for x in range(5):
squares.append(x**2)
print(squares)
print(x) # 产生了一个变量 x
[0, 1, 4, 9, 16]
4
squares = [y**2 for y in range(5)]
print(squares)
print(y) # 没有多余变量 y
[0, 1, 4, 9, 16]
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-3-c81791cbad54> in <module>
1 squares = [y**2 for y in range(5)]
2 print(squares)
----> 3 print(y) #
NameError: name 'y' is not defined
我们发现,列表推导式简洁漂亮、易读,不会产生多余的变量而可能带来副作用。
列表推导式示例:
[(x, y) for x in [1,2] for y in [1,3] if x != y]
[(1, 3), (2, 1), (2, 3)]
相当于:
_list = []
for x in [1,2]:
for y in [1,3]:
if x != y:
_list.append((x,y))
_list
[(1, 3), (2, 1), (2, 3)]
列表推导式可以使用复杂的表达式和嵌套函数:
from math import pi
[str(round(pi, i)) for i in range(1, 4)]
['3.1', '3.14', '3.142']
嵌套的列表推导式:
matrix = [[1, 2, 3],
[5, 6, 7]]
[[row[i] for row in matrix] for i in range(3)]
[[1, 5], [2, 6], [3, 7]]
相当于:
matrix = [[1, 2, 3],
[5, 6, 7]]
_list = []
for i in range(3):
lst = []
for row in matrix:
lst.append(row[i])
_list.append(lst)
_list
[[1, 5], [2, 6], [3, 7]]
判断语句在前的列表推导式:
[True if i % 2 == 0 else False for i in [1,4,7,9]]
[False, True, False, False]
相当于:
_list = []
for i in [1,4,7,9]:
if i % 2 == 0:
_list.append(True)
else:
_list.append(False)
_list
[False, True, False, False]
列表是序列类型中的可变类型,它的索引和切片操作,和通用的序列操作比较,有许多不一样的地方,主要体现在利用索引和切片对列表元素进行增、删、改。
索引和切片是序列类型通用操作,详细的规则和用法,见序列索引和切片。
列表可以利用索引替换某一个元素:
_list = [1,2,3]
_list[1] = 0
_list
[1, 0, 3]
利用切片将切片中的元素替换为可迭代对象中的元素:
_list = [1,2,3]
_list[1:3] = '123'
_list
[1, '1', '2', '3']
# 该替换,切片长度和可迭代对象长度必须相等
_list = [1,2,3,4,5]
_list[1:5:2] = '24'
_list
[1, '2', 3, '4', 5]
需要注意,替换并没有改变原来的列表对象:
list_1 = [1,2,3]
print(id(list_1),list_1)
list_1[2] = 0
print(id(list_1),list_1)
list_1[:] = range(5)
print(id(list_1),list_1)
list_1[::2] = ('a','b','c')
print(id(list_1),list_1)
2065281773704 [1, 2, 3]
2065281773704 [1, 2, 0]
2065281773704 [0, 1, 2, 3, 4]
2065281773704 ['a', 1, 'b', 3, 'c']
可以利用切片在列表中任意位置插入数据片段:
_list = [1,2,3]
# 在前面插入两个 0
_list[:0] = (0,0)
print(_list)
# 在索引为 2 的元素前面插入 'a','b'
_list[2:2] = ['a','b']
_list
[0, 0, 1, 2, 3]
[0, 0, 'a', 'b', 1, 2, 3]
列由切片浅拷贝列表,生成新的列表,但列表中有可变对象时,新列表中的可变对象和对应的原来列表中的可变对象是同一个对象的多次引用:
list_1 = [[1,2],3,4]
list_2 = list_1[:]
print('原列表:',id(list_1),'新列表:',id(list_2))
print('原列表中的可变对象:',
id(list_1[0]),
'\n新列表中对应的可变对象:',id(list_2[0]))
原列表: 2065281774536 新列表: 2065281774664
原列表中的可变对象: 2065281383112
新列表中对应的可变对象: 2065281383112
改变其中一个,都会跟着改变。需要注意区分修改列表中元素的元素,和修改列表元素的区别:
list_1[0][0] = 'a'
print(list_1, list_2)
list_1[0] = 'a'
print(list_1, list_2)
[['a', 2], 3, 4] [['a', 2], 3, 4]
['a', 3, 4] [['a', 2], 3, 4]
列表方法 list.clear(),Python 官方文档描述如下:
help(list.clear)
Help on method_descriptor:
clear(self, /)
Remove all items from list.
删除列表中所有的元素。相当于 del a[:](a 是列表)。
_list = [1,2,3]
_list.clear()
_list
[]
del a[:] 是删除列表 a 中的所有元素,和 a 的浅拷贝无关:
a = [1,2,3]
b = a[:]
del a[:]
a, b
([], [1, 2, 3])
该方法是一个过程 (过程就是不返回有意义结果的函数;在 Python 中,过程的返回值为 None), 直接对原列表进行修改:
_list = [1,2,3]
a = _list.clear()
print(a)
None
列表可以使用 比较运算符,但比较运算符对数据通用,单独用一个知识点讲解。该知识点介绍有列表自己特性的操作符 +
和 *
。
操作符 +
,可以让两个列表元素顺序不变地合并到一个新的列表中:
list_1 = [1,2]
list_2 = [3,4]
list_1 + list_2, list_2 + list_1
([1, 2, 3, 4], [3, 4, 1, 2])
操作符 +
还可以与赋值操作符 =
连用,将一个列表中的元素,加到另一个列表中(相当于 list.extend()),而不创建一个新列表:
list_1 = [1,2]
list_2 = [3,4]
print(id(list_1))
list_1 += list_2
id(list_1), list_1
2893532728008
(2893532728008, [1, 2, 3, 4])
操作符 *
,可以将列表中的元素重复 n 次,得到一个新列表:
list_1 = [1,2]
list_2 = list_1*2
print(id(list_1),id(list_2))
list_2
2893532600136 2893532727432
[1, 2, 1, 2]
**注意:**如果列表中有可变对象,重复 n 次后,可变对象是同一个对象的多次引用,改变一个,都会跟着改变。
list_1 = [[0]]
list_2 = list_1*3
print(list_2)
list_1[0][0] = 1
list_2
[[0], [0], [0]]
[[1], [1], [1]]
操作符 *
,还可以与赋值操作符 =
连用,用一个列表的元素重复 n 次来扩充它自身,而不创建新列表:
_list = [1,2]
print(id(_list))
_list *= 2
id(_list), _list
2893532727624
(2893532727624, [1, 2, 1, 2])
当 n 小于 1 时,则得到空列表:
[1,2,3]*0
[]
列表是可迭代对象,*
可以将列表拆包:
print(*[1,2,3])
1 2 3
列表方法 list.append(),Python 官方文档描述如下:
help(list.append)
Help on method_descriptor:
append(self, object, /)
Append object to the end of the list.
在列表的末尾添加一个元素。相当于 a[len(a):] = [x](a 是一个列表)。添加的元素可以是任何对象。
_list = [1,2]
_list.append('abc')
_list.append(list.append)
_list
[1, 2, 'abc', <method 'append' of 'list' objects>]
该方法是一个过程 (过程就是不返回有意义结果的函数;在 Python 中,过程的返回值为 None), 直接对原列表进行修改:
_list = []
a = _list.append('')
print(a)
None
列表方法 list.extend(),Python 官方文档描述如下:
help(list.extend)
Help on method_descriptor:
extend(self, iterable, /)
Extend list by appending elements from the iterable.
使用可迭代对象中的所有元素来扩展列表。相当于 a[len(a):] = iterable(a 是一个列表)。
_list = [1,2]
_list.extend('abc')
_list
[1, 2, 'a', 'b', 'c']
_list.extend(range(2))
_list
[1, 2, 'a', 'b', 'c', 0, 1]
该方法是一个过程 (过程就是不返回有意义结果的函数;在 Python 中,过程的返回值为 None), 直接对原列表进行修改:
_list = [1,2]
a = _list.extend('abc')
print(a)
None
列表方法 list.insert(),Python 官方文档描述如下:
help(list.insert)
Help on method_descriptor:
insert(self, index, object, /)
Insert object before index.
在给定的位置插入一个元素。第一个参数是要插入的元素的索引,所以 a.insert(0, x) 插入列表头部,a.insert(len(a), x) 等同于 a.append(x)(a 是一个列表)。
_list = [1,2,3]
_list.insert(0,0)
_list
[0, 1, 2, 3]
_list.insert(len(_list),[4])
_list
[0, 1, 2, 3, [4]]
该方法是一个过程 (过程就是不返回有意义结果的函数;在 Python 中,过程的返回值为 None), 直接对原列表进行修改:
_list = [1,2,3]
a = _list.insert(0,0)
print(a)
None
列表方法 list.sort(),Python 官方文档描述如下:
help(list.sort)
Help on method_descriptor:
sort(self, /, *, key=None, reverse=False)
Sort the list in ascending order and return None.
The sort is in-place (i.e. the list itself is modified) and stable (i.e. the
order of two equal elements is maintained).
If a key function is given, apply it once to each list item and sort them,
ascending or descending, according to their function values.
The reverse flag can be set to sort in descending order.
此方法会对列表进行原地排序,只使用 <
来进行各项间比较。异常不会被屏蔽——如果有任何比较操作失败,整个排序操作将失败(而列表可能会处于被部分修改的状态)。
_list = [2,3,6,1,'5']
_list.sort()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-2-87abda0b5baf> in <module>
1 _list = [2,3,6,1,'5']
----> 2 _list.sort()
TypeError: '<' not supported between instances of 'str' and 'int'
_list
[1, 2, 3, 6, '5']
sort() 接受两个仅限以关键字形式传入的参数 (仅限关键字参数):
_list = [-3,2,-5,1,4]
_list.sort(key=abs)
_list
[1, 2, -3, 4, -5]
_list.sort()
_list
[-5, -3, 1, 2, 4]
_list = [-3,2,-5,1,4]
_list.sort(reverse=True)
_list
[4, 2, 1, -3, -5]
当对较大的列表排序时,此方法会原地修改该序列以保证空间经济性。因此它并不会返回排序后的序列。
sort() 方法确保是稳定的——如果一个排序确保不会改变比较结果相等的元素的相对顺序就称其为稳定的。
_list = [1,'1.0',2,'1']
_list.sort(key=float)
_list
[1, '1.0', '1', 2]
该方法是一个过程 (过程就是不返回有意义结果的函数;在 Python 中,过程的返回值为 None), 直接对原列表进行修改:
_list = [5,1,4]
a = _list.sort()
print(a)
None
列表方法 list.reverse(),Python 官方文档描述如下:
help(list.reverse)
Help on method_descriptor:
reverse(self, /)
Reverse *IN PLACE*.
反转列表中的元素。
_list = [1,2,3]
_list.reverse()
_list
[3, 2, 1]
该方法是一个过程 (过程就是不返回有意义结果的函数;在 Python 中,过程的返回值为 None), 直接对原列表进行修改:
_list = [1,2,3]
a = _list.reverse()
print(a)
None
列表方法 list.pop(),Python 官方文档描述如下:
help(list.pop)
Help on method_descriptor:
pop(self, index=-1, /)
Remove and return item at index (default last).
Raises IndexError if list is empty or index is out of range.
删除列表中给定位置的元素并返回它。如果没有给定位置,list.pop() 将会删除并返回列表中的最后一个元素。给定位置超出范围,抛出 IndexError 错误。
_list = [1,2,3,4]
_list.pop()
4
_list
[1, 2, 3]
_list.pop(0)
1
_list
[2, 3]
_list.pop(5)
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-4-efa5a84417c8> in <module>
----> 1 _list.pop(5)
IndexError: pop index out of range
列表方法 list.remove(),Python 官方文档描述如下:
help(list.remove)
Help on method_descriptor:
remove(self, value, /)
Remove first occurrence of value.
Raises ValueError if the value is not present.
移除列表中第一个值为 value 的元素。如果没有这样的元素,则抛出 ValueError 异常。
_list = [1,3,2,3]
_list.remove(3)
_list
[1, 2, 3]
_list.remove(4)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-3-5747ddae04fe> in <module>
----> 1 _list.remove(4)
ValueError: list.remove(x): x not in list
该方法是一个过程 (过程就是不返回有意义结果的函数;在 Python 中,过程的返回值为 None), 直接对原列表进行修改:
_list = [1,3,2,3]
a = _list.remove(3)
print(a)
None
列表方法 list.count(),Python 官方文档描述如下:
help(list.count)
Help on method_descriptor:
count(self, value, /)
Return number of occurrences of value.
返回元素 value 在列表中出现的次数,没有出现为 0。
_list = [1,2,3,1]
_list.count(1), _list.count([1])
(2, 0)
列表方法 list.index(),Python 官方文档描述如下:
help(list.index)
Help on method_descriptor:
index(self, value, start=0, stop=9223372036854775807, /)
Return first index of value.
Raises ValueError if the value is not present.
返回列表中第一个值为 value 的元素从零开始的索引。如果没有这样的元素将会抛出 ValueError 异常。
可选参数 start 和 stop 是切片符号,用于将搜索限制为列表的特定子序列。返回的是相对于整个序列开始计算的索引,而不是相对于 start 参数。
_list = [1,2,3,4,3]
_list.index(3)
2
_list.index(3,1,4)
2
_list.index(3,4,10)
4
_list.index(3,5,10)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-6-3e258cbffc85> in <module>
----> 1 _list.index(3,5,10)
ValueError: 3 is not in list
列表方法 list.copy(),Python 官方文档描述如下:
help(list.copy)
Help on method_descriptor:
copy(self, /)
Return a shallow copy of the list.
返回列表的一个浅拷贝。相当于 a[:](a 是一个列表)。浅拷贝得到新的列表,列表中有可变对象时,浅拷贝中的可变对象元素,是原列表中同一个对象的多次引用。
list_1 = [[1],2,3]
list_2 = list_1.copy()
print(list_2)
id(list_1),id(list_2)
[[1], 2, 3]
(2622792783240, 2622792782728)
# 同一个对象
id(list_1[0]), id(list_2[0])
(2622792782792, 2622792782792)
改变其中一个都会跟着改变:
list_1[0][:] = 'abc'
list_1, list_2
([['a', 'b', 'c'], 2, 3], [['a', 'b', 'c'], 2, 3])
元组是不可变序列,通常用一对小括号包围元素,元素之间逗号隔开。元组的元素可以是任何对象。元组类型是 tuple:
type((1,2,['1','2']))
tuple
空元组用一对圆括号表示:
()
()
单元组后面必须有一个逗号:
(1,)
(1,)
除了空元组,括号可以省略,因为决定生成元组的其实是逗号而不是圆括号,圆括号是可选的,但元组是更大的表达式的一部分或会产生语法歧义的情况,括号不能省略:
1,
(1,)
1, 1+1, ('单元组',)
(1, 2, ('单元组',))
内置函数 tuple() 用来构造元组:
tuple(), tuple('123')
((), ('1', '2', '3'))
当元组中包含可变对象(例如列表)时,元组本身不可变(不能增、删、改元组本身的元素),但包含的可变对象仍然具有它的可变性质及其操作,此时的元组不能再作为集合的元素或字典的键:
a = ([1,2],3,3)
print(id(a))
del a[0][:]
id(a), a
2207053762176
(2207053762176, ([], 3, 3))
{a}
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-14-29dfa031a339> in <module>
----> 1 {a}
TypeError: unhashable type: 'list'
元组方法 tuple.count(),Python 官方文档描述如下:
help(tuple.count)
Help on method_descriptor:
count(self, value, /)
Return number of occurrences of value.
返回值为 value 的元素在元组中的出现次数。
(1,2,1,3).count(1)
2
(1,2,1,3).count(4)
0
元组方法 tuple.index(),Python 官方文档描述如下:
help(tuple.index)
Help on method_descriptor:
index(self, value, start=0, stop=9223372036854775807, /)
Return first index of value.
Raises ValueError if the value is not present.
返回列表中第一个值为 value 的元素从零开始的索引。如果没有这样的元素将会抛出 ValueError 异常。
可选参数 start 和 stop 是切片符号,用于将搜索限制为元组的特定子序列。返回的是相对于整个序列开始计算的索引,而不是相对于 start 参数。
(1,2,3,4,1).index(1)
0
(1,2,3,4,1).index(1,1)
4
(1,2,3,4,1).index(1,1,3)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-4-c6a812394eea> in <module>
----> 1 (1,2,3,4,1).index(1,1,3)
ValueError: tuple.index(x): x not in tuple
元组可以使用 +
拼接,拼接后按原来的顺序排列:
(4,5,6) + (1,2,3)
(4, 5, 6, 1, 2, 3)
1,2,3 + 4,5,6
(1, 2, 7, 5, 6)
+
操作符可以与 =
连用,拼接同时赋值,元组是不可变的,该操作是创建了一个新元组:
a = 1,2,3
print(id(a))
a += 4,5,6
id(a), a
2741588191344
(2741587773864, (1, 2, 3, 4, 5, 6))
元组还可使用 *
进行 n 次重复拼接:
(1,)*3
(1, 1, 1)
当 n 小于 1 时,得到空元组:
(1,2,3)*0
()
元组中的元素如果是可变对象,*
重复拼接后,可变对象的性质同 列表操作符 知识点一样,仍然是同一个对象的多次引用:
a = ([],)
b = a*3
# 在元组 a 的第一个元素中加入 1
a[0].append(1)
b
([1], [1], [1])
同列表一样可以用 *=
,重复拼接并赋值:
a = 1,
a *= 3
a
(1, 1, 1)
元组是可迭代对象,所以可以用 *
将元组拆包:
{*(1,1,2,3)}
{1, 2, 3}
序列类型有列表,元组,range,字符串,字节串等。之所以称为序列类型,因为它们中的元素是按顺序排列的,可以使用下标索引或切片取值。
a = [1,2,3]
b = 1,2,3
c = range(1,4)
d = '123'
e = b'123'
a[0],b[0],c[0],d[0],e[0]
(1, 1, 1, '1', 49)
chr(49) # 字节串索引取到的是 Unicode 码位值
'1'
序列类型又分为可变和不可变两种,列表是可变序列类型,元组,range,字符串,字节串是不可变序列类型。不可变序列类型普遍实现而可变序列类型未实现的唯一操作就是对 hash() 内置函数的支持。
这种支持允许不可变类型,例如元组被用作字典的键,以及存储在集合中。
尝试对包含有不可哈希值的不可变序列进行哈希运算将会导致 TypeError。
hash((1,2)), hash('12')
(-3550055125485641917, -480100434937186025)
{(1,2), '12'}
{(1, 2), '12'}
{([1,2],3),4}
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-10-b847264454c5> in <module>
----> 1 {([1,2],3),4}
TypeError: unhashable type: 'list'
可变序列类型,可以就地进行元素的增、删、改,而不可变序列类型不可以,有时看起来像,但其实是创建了新对象:
a, b = [1,2], (1,2)
print(id(a),id(b))
a += [3] # 将元素 3 加入列表中,相当于 a.extend([3])
b += (3,) # 将元组 b 与元组 (3,) 拼接赋值给 b
print(a,b)
print(id(a), id(b))
2058115879744 2058115232576
[1, 2, 3] (1, 2, 3)
2058115879744 2058115884416
range 对象是一个整数等差数列,用内置函数 range() 构造得到,类型是 range:
type(range(3))
range
range(-1,5,2)
range(-1, 5, 2)
range 通常用于在 for 循环中循环指定的次数:
for i in range(3):
print('重要的事情说三遍')
重要的事情说三遍
重要的事情说三遍
重要的事情说三遍
range 对象可以指定起始值(默认 0),结束值(不包含),和等差数列的公差(默认 1)。
指定一个大于 0 的值则默认从 0 开始,公差为 1,到指定值之前一个整数结束:
list(range(5))
[0, 1, 2, 3, 4]
因为公差默认为 1,指定一个小于等于 0 的值则得到空 range:
list(range(-5))
[]
起始值,结束值,公差都指定,则得到相应等差数列:
list(range(1,5))
[1, 2, 3, 4]
list(range(1,-5,-1))
[1, 0, -1, -2, -3, -4]
range 类型相比常规 list 或 tuple,优势在于一个 range 对象总是占用固定的(较小)内存,不论其所表示的范围有多大。因为 range 类型只保存了 start, stop 和 step 值,并会根据需要计算具体单项或子范围的值。
除了拆包可以使用操作符*
,range 对象不可以像列表,元组等一样,使用 +
,*
,+=
,*=
进行拼接或重复:
(*range(3),)
(0, 1, 2)
序列类型都可以使用下标进行索引或切片取值,这是序列类型通用操作。可变序列类型比较特殊,例如列表,可以利用索引或切片进行元素增、删、改,详见 列表的索引和切片。
下标从前往后,则以 0 开始,从后往前,则从 -1 开始,双向索引:
('a', 'b', 'c', 'd')
0 1 2 3
-4 -3 -2 -1
下标索引,直接取出对应索引下的值,超出范围则报错:
a = [1,2,3,4]
a[10]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-18-5680bb375980> in <module>
1 a = [1,2,3,4]
----> 2 a[10]
IndexError: list index out of range
a = [1,2,3,4]
a[0], a[-2]
(1, 3)
下标切片取值规则:[起始:结束:步长],不包含结束。
a = [1,2,3,4,5,6,7]
a[:3]
[1, 2, 3]
a = [1,2,3,4,5,6,7]
a[3:]
[4, 5, 6, 7]
a = [1,2,3,4,5,6,7]
a[1:-3], a[-6:4]
([2, 3, 4], [2, 3, 4])
a = [1,2,3,4,5,6,7]
a[::2]
[1, 3, 5, 7]
a = [1,2,3,4,5,6,7]
a[::-2] # 默认 -1 开始取
[7, 5, 3, 1]
a = [1,2,3,4,5,6,7]
a[0:7:-2]
[]
a = [1,2,3,4,5,6,7]
a[-1:0:-2]
[7, 5, 3]
切片范围可以无限大,范围内没有元素,则得到空的容器:
a = [1,2,3,4,5,6,7]
a[5:100], a[1:1], a[5:-10]
([6, 7], [], [])
序列类型有许多通用的操作,在各个知识点都有详细的介绍,下面将他们综合起来比较。
序列类型都可以使用操作符 +
进行拼接,使用 +=
拼接并赋值(range 除外),但对于可变序列类型,使用 +=
是原地修改:
a = [1,2]
print(id(a))
a += [3,4]
id(a), a
2612604344328
(2612604344328, [1, 2, 3, 4])
'12'+'34', [1,2]+[3,4], (1,2)+(3,4)
('1234', [1, 2, 3, 4], (1, 2, 3, 4))
序列类型都可以使用操作符 *
进行重复并拼接,使用 *=
拼接并赋值(range 除外),但对于可变序列类型,使用 *=
是原地修改:
'1'*2, 2*[1], (1,)*2
('11', [1, 1], (1, 1))
a = [1]
print(id(a))
a *= 2
id(a), a
2612603190024
(2612603190024, [1, 1])
序列类型都可以使用 *
进行拆包,拆包之后需要包含在列表,元组,集合中,或用于函数传参:
[*(1,2)], (*[1,2],), {*range(1,3)}
([1, 2], (1, 2), {1, 2})
print(*'123')
1 2 3
序列类型都可以使用索引或切片操作取值,但对于可变序列类型,还可以使用索引或切片操作进行内容的增、删、改:
a = '1234'
b = [1,2,3,4]
c = (1,2,3,4)
d = range(1,5)
a[0], b[0], c[0], d[0]
('1', 1, 1, 1)
a[1:3], b[1:3], c[1:3], d[1:3]
('23', [2, 3], (2, 3), range(2, 4))
b[1:3] = 'abc'
b
[1, 'a', 'b', 'c', 4]
序列类型都有方法 index 和 count,但字符串和字节串的 count 方法可以指定范围(具体详见各知识点的方法):
'1234'.index('23'),\
[1,2,3,4].index(2),\
range(1,4).index(2)
(1, 1, 1)
'1231'.count('1',1,3),\
(1,2,3,1).count(1)
(0, 2)
集合是由具有唯一性的可哈希对象(一个对象的哈希值如果在其生命周期内绝不改变)组成的无序多项集。
目前有两种内置集合类型,set 和 frozenset,前者是可变类型,后者是不可变类型。
type({1}), type(frozenset())
(set, frozenset)
因为一对花括号表示字典而非集合,所以创建空集合必须使用构造函数 set() 和 frozenset() 来表示。两个内置函数还可将可迭代对象转换为集合:
type({}), set(), frozenset()
(dict, set(), frozenset())
set('121'), frozenset('112')
({'1', '2'}, frozenset({'1', '2'}))
构造 set 集合还可以直接使用一对花括号包含元素,元素之间用逗号隔开:
{1,2,1}
{1, 2}
集合的元素必须是可哈希的,例如字符串,元组(不能包含不可哈希对象,例如元组里有列表);也是唯一的,同时存在多个哈希值相等的元素,只保留一个。
print(hash(False),hash(0))
0 0
{'12', (1,2), False, 0}
{(1, 2), '12', False}
set 类型集合是可变类型,没有哈希值,不可作为集合的元素或字典的键,而 frozenset 类型的集合可以:
{frozenset([1,2])}
{frozenset({1, 2})}
两种类型集合可进行比较,并集,交集,差集,对称差集操作:
{1,2} == frozenset({1,2})
True
{1,2} | frozenset({1,2,3})
{1, 2, 3}
frozenset({1,2,3}) ^ {1,2}
frozenset({3})
set 类型是可变的,还可进行元素增、删、改,等操作,而 frozenset 类型不可以:
a = set()
print(id(a))
# a 增加元素 1
a.add(1)
print(id(a),a)
# 将一个集合并入 a
a |= frozenset({1,2,3})
print(id(a),a)
# 清空集合 a
a.clear()
print(id(a),a)
2029775797832
2029775797832 {1}
2029775797832 {1, 2, 3}
2029775797832 set()
集合是按哈希值对元素进行储存,而不是按顺序,因此集合没有索引和切片操作。搜索元素时,由于是通过哈希值匹配,集合比序列类型效率高。
由于集合仅定义了部分排序(子集关系),比较大小的排序并无定义。
{2,1,5} > {2,5}
True
a = [{2,1,5},{9},{6},{2,5}]
a.sort()
a
[{1, 2, 5}, {9}, {6}, {2, 5}]
集合方法 set.isdisjoint(),Python 官方文档描述如下:
help(set.isdisjoint)
Help on method_descriptor:
isdisjoint(...)
Return True if two sets have a null intersection.
两个集合的交集为空,则返回 True。方法中的参数可以是可迭代对象。
{1,2}.isdisjoint([1,2])
False
{1,2}.isdisjoint([3,4])
True
{1,2}.isdisjoint('12') # 参数是字符串而非数字
True
集合方法 set.issubset(),Python 官方文档描述如下:
help(set.issubset)
Help on method_descriptor:
issubset(...)
Report whether another set contains this set.
检查一个集合中的元素,是否都在另一个集合中。相当于 a <= b(a,b 是两个集合),但方法中的参数可以是可迭代对象。
{1,2}.issubset([1,2,3])
True
{1,2} <= {1,2,3}
True
{1,2}.issubset((1,1,2))
True
该方法检查是否是子集,而对于真子集,可以使用 <
进行检查:
{1,2} < {1,1,2}
False
{1,2} < {1,2,3}
True
集合方法 set.issuperset(),Python 官方文档描述如下:
help(set.issuperset)
Help on method_descriptor:
issuperset(...)
Report whether this set contains another set.
检查一个集合是否是另一个集合的超集。相当于 a >= b(a,b 是两个集合),但方法中的参数可以是可迭代对象。
{1,2}.issuperset({True:'1',2:'2'})
True
{1,2,3} >= {True,2}
True
对于真超集,使用 >
进行检查:
{1,2,3} > {True,2}
True
{1,2} > {True,2}
False
集合方法 set.union(),Python 官方文档描述如下:
help(set.union)
Help on method_descriptor:
union(...)
Return the union of sets as a new set.
(i.e. all elements that are in either set.)
该方法接收任意的位置参数,返回一个所有集合的元素组成的新集合。相当于 a | b | … (a,b 是集合),但方法中的参数可以是可迭代对象。
{1}.union([2],(3,4))
{1, 2, 3, 4}
{1} | {2} | {3,4}
{1, 2, 3, 4}
集合方法 set.intersection(),Python 官方文档描述如下:
help(set.intersection)
Help on method_descriptor:
intersection(...)
Return the intersection of two sets as a new set.
(i.e. all elements that are in both sets.)
该方法接收任意的位置参数,返回一个所有集合中共有的元素组成的新集合。相当于 a & b & … (a,b 是集合),但方法中的参数可以是可迭代对象。
{1,2,3}.intersection({3,4},[1,5,3])
{3}
{1,2,3} & {3,4} & {1,5,3}
{3}
集合方法 set.difference(),Python 官方文档描述如下:
help(set.difference)
Help on method_descriptor:
difference(...)
Return the difference of two or more sets as a new set.
(i.e. all elements that are in this set but not the others.)
该方法接收任意的位置参数,返回一个集合在其他所有集合中都不存在的元素组成的新集合。相当于 a - b - … (a,b 是集合),但方法的参数可以是可迭代对象。
{1,2,3,4}.difference((2,1,5),{6,2,4})
{3}
{1,2,3,4} - {2,1,5} - {6,2,4}
{3}
集合方法 set.symmetric_difference(),Python 官方文档描述如下:
help(set.symmetric_difference)
Help on method_descriptor:
symmetric_difference(...)
Return the symmetric difference of two sets as a new set.
(i.e. all elements that are in exactly one of the sets.)
返回两个集合中非共同元素组成的新集合。相当于 a ^ b(a,b 是集合),但方法的参数可以是可迭代对象。
{1,2,3}.symmetric_difference([2,3,4])
{1, 4}
{1,2,3} ^ {2,3,4}
{1, 4}
集合方法 set.copy(),Python 官方文档描述如下:
help(set.copy)
Help on method_descriptor:
copy(...)
Return a shallow copy of a set.
返回集合的一个浅拷贝。
a = {1,2}
print(id(a),a)
b = a.copy()
id(b),b
2091426558696 {1, 2}
(2091426559368, {1, 2})
集合方法 set.update(),Python 官方文档描述如下:
help(set.update)
Help on method_descriptor:
update(...)
Update a set with the union of itself and others.
该方法接收任意的位置参数,将其他集合的元素合并到一个集合中。相当于 a |= b | … (a,b 是集合),但方法的参数可以是可迭代对象。
a = {1,2}
a.update([3],(4,5))
a
{1, 2, 3, 4, 5}
a = {1,2}
a |= {3} | {4,5}
a
{1, 2, 3, 4, 5}
该方法是一个过程,就地修改集合,返回值为 None。
a = {1,2}
b = a.update([3],(4,5))
print(b)
None
集合方法 set.intersection_update(),Python 官方文档描述如下:
help(set.intersection_update)
Help on method_descriptor:
intersection_update(...)
Update a set with the intersection of itself and another.
该方法接收任意的位置参数,更新集合,只保留在其他所有集合中都存在的元素。相当于 a &= b & …(a,b 是集合),但方法的参数可以是可迭代对象。
a = {1,2,3,4}
a.intersection_update((1,2,5),{1,3,5})
a
{1}
a = {1,2,3,4}
a &= {1,2,5} & {1,3,5}
a
{1}
该方法是一个过程,就地修改集合,返回值为 None。
a = {1,2,3,4}
b = a.intersection_update()
print(b)
None
集合方法 set.difference_update(),Python 官方文档描述如下:
help(set.difference_update)
Help on method_descriptor:
difference_update(...)
Remove all elements of another set from this set.
该方法接收任意的位置参数,更新集合,移除在其他集合中也存在的元素。相当于 a -= b | …(a,b 是集合),但方法的参数可以是可迭代对象。
a = {1,2,3,4}
a.difference_update((1,3,5),[4,5])
a
{2}
a = {1,2,3,4}
a -= {1,3,5} | {4,5}
a
{2}
该方法是一个过程,就地修改集合,返回值为 None。
a = {1,2,3,4}
b = a.difference_update([4,5])
print(b)
None
集合的对称差集更新操作,相当于集合方法 set.symmetric_difference_update,其文档描述如下:
help(set.symmetric_difference_update)
Help on method_descriptor:
symmetric_difference_update(...)
Update a set with the symmetric difference of itself and another.
更新集合,只保留两个集合中非共同部分。
a = {1,2,3}
a.symmetric_difference_update([2,3,4])
a
{1, 4}
a = {1,2,3}
a ^= {2,3,4}
a
{1, 4}
该方法是一个过程,就地修改集合,返回值为 None。
a = {1,2,3}
b = a.symmetric_difference_update([2,3,4])
print(b)
None
集合方法 set.add(),Python 官方文档描述如下:
help(set.add)
Help on method_descriptor:
add(...)
Add an element to a set.
This has no effect if the element is already present.
集合中增加一个元素,如果元素已经存在,没有任何影响。
a = {1,2}
a.add(3)
a
{1, 2, 3}
a = {1,2}
a.add(1)
a
{1, 2}
该方法是一个过程,就地修改集合,返回值为 None。
a = {1,2}
b = a.add(3)
print(b)
None
集合方法 set.remove(),Python 官方文档描述如下:
help(set.remove)
Help on method_descriptor:
remove(...)
Remove an element from a set; it must be a member.
If the element is not a member, raise a KeyError.
删除一个指定元素,删除元素不存在则引发 KeyError。
a = {1,2}
a.remove(1)
a
{2}
a = {1,2}
a.remove(3)
a
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-3-d0f57d460301> in <module>
1 a = {1,2}
----> 2 a.remove(3)
3 a
KeyError: 3
该方法是一个过程,就地修改集合,返回值为 None。
a = {1,2}
b = a.remove(1)
print(b)
None
集合方法 set.discard(),Python 官方文档描述如下:
help(set.discard)
Help on method_descriptor:
discard(...)
Remove an element from a set if it is a member.
If the element is not a member, do nothing.
从集合中删除一个指定元素,元素不存在没有任何影响。
a = {1,2}
a.discard(1)
a
{2}
a = {1,2}
a.discard(3)
a
{1, 2}
该方法是一个过程,就地修改集合,返回值为 None。
a = {1,2}
b = a.discard(1)
print(b)
None
集合方法 set.pop(),Python 官方文档描述如下:
help(set.pop)
Help on method_descriptor:
pop(...)
Remove and return an arbitrary set element.
Raises KeyError if the set is empty.
集合中删除任意一个元素,并返回它。如果集合为空,引发 KeyError。
a = {1,2}
a.pop()
1
a
{2}
set().pop()
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-6-db3bab0ab3b8> in <module>
----> 1 set().pop()
KeyError: 'pop from an empty set'
集合方法 set.clear(),Python 官方文档描述如下:
help(set.clear)
Help on method_descriptor:
clear(...)
Remove all elements from this set.
清空集合所有元素。
a = {1,2}
a.clear()
a
set()
该方法是一个过程,就地修改集合,返回值为 None。
a = {1,2}
b = a.clear()
print(b)
None
字典属于映射类型,将可哈希对象映射到任意对象,可哈希对象为字典的键,映射的对象为键对应的条目(值)。因此:
所以字典的键必须是可哈希对象,例如字符串,元组(不能包含不可哈希对象);哈希值相等的对象作为字典的键会被当作一个键。
{'1':1, (1,2):2, 1:3, True:4}
{'1': 1, (1, 2): 2, 1: 4}
字典是目前唯一的标准映射类型。其类型为 dict。空字典用一对花括号表示。
type({})
dict
字典可以通过花括号包含逗号分隔的 键值对 来创建,也可以用内置函数 dict() 来创建。
{'a':1, 'b':2}
{'a': 1, 'b': 2}
dict(a=1,b=2)
{'a': 1, 'b': 2}
dict(zip(['a','b'],(1,2)))
{'a': 1, 'b': 2}
字典是可变对象,可以通过键,来获取对应的项,或更新、添加项。获取项时,键不存在则引发 KeyError。
# 获取
d = {'a':1}
d['a']
1
# 更新
d['a'] = [1,2]
d
{'a': [1, 2]}
# 键不存在则添加项
d['b'] = {1,2}
d
{'a': [1, 2], 'b': {1, 2}}
d['c']
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-9-05ba6e0488c7> in <module>
----> 1 d['c']
KeyError: 'c'
字典的元素(键值对)是按哈希值来存储的,没有序列类型的双向索引操作,但字典会保留元素插入时的顺序,更新不会改变插入顺序。而且使用 popitem 方法删除元素是按后进先出原则删除。
d = {}
d[3] = 3
d[1] = 1
d[2] = 2
d
{3: 3, 1: 1, 2: 2}
d[1] = 10
d
{3: 3, 1: 10, 2: 2}
d.popitem(),d.popitem(),d.popitem()
((2, 2), (1, 10), (3, 3))
字典方法 dict.keys(),Python 官方文档描述如下:
help(dict.keys)
Help on method_descriptor:
keys(...)
D.keys() -> a set-like object providing a view on D's keys
返回一个由字典的键组成的动态视图。字典的视图支持成员检测,可以被迭代。
d = {'a':1, 'b':2}
d.keys()
dict_keys(['a', 'b'])
'a' in d.keys()
True
list(d.keys())
['a', 'b']
d = {'a':1, 'b':2}
d_view = d.keys()
print(d_view)
d['c'] = 3 # 添加元素,视图也动态变化
print(d_view)
dict_keys(['a', 'b'])
dict_keys(['a', 'b', 'c'])
字典方法 dict.values(),Python 官方文档描述如下:
help(dict.values)
Help on method_descriptor:
values(...)
D.values() -> an object providing a view on D's values
返回由字典的值组成的动态视图。字典的视图支持成员检测,可以被迭代。
d = {'a':1, 'b':2}
d_view = d.values()
print(d_view)
d['c'] = 3 # 添加元素,视图也动态变化
print(d_view)
dict_values([1, 2])
dict_values([1, 2, 3])
1 in d_view
True
[i for i in d_view]
[1, 2, 3]
字典方法 dict.items(),Python 官方文档描述如下:
help(dict.items)
Help on method_descriptor:
items(...)
D.items() -> a set-like object providing a view on D's items
返回字典的 (键,值) 元组组成的动态视图。字典的视图支持成员检测,可以被迭代。
d = {'a':1, 'b':2}
d_view = d.items()
print(d_view)
d['c'] = 3 # 添加元素,视图也动态变化
print(d_view)
dict_items([('a', 1), ('b', 2)])
dict_items([('a', 1), ('b', 2), ('c', 3)])
('a', 1) in d_view
True
[k*j for k, j in d_view]
['a', 'bb', 'ccc']
字典方法 dict.get(),Python 官方文档描述如下:
help(dict.get)
Help on method_descriptor:
get(self, key, default=None, /)
Return the value for key if key is in the dictionary, else default.
获取字典的项目,如果 key 存在于字典中则返回 key 的值,否则返回 default 指定的值,默认为 None。
d = {'a':1, 'b':2}
d.get('a')
1
print(d.get('c'))
None
d.get('c', 3)
3
字典方法 dict.copy(),Python 官方文档描述如下:
help(dict.copy)
Help on method_descriptor:
copy(...)
D.copy() -> a shallow copy of D
返回字典的一个浅拷贝。字典是可变对象,浅拷贝将创建一个新字典,但如果字典中某个 键值对 的值是可变对象,则是同一个对象的多次引用。
d = {'a':[1,2], 'b':3}
print(id(d), d)
d1 = d.copy()
print(id(d1), d1)
2276967660712 {'a': [1, 2], 'b': 3}
2276967660784 {'a': [1, 2], 'b': 3}
# 同一个对象的多次引用
id(d['a']), id(d1['a'])
(2276966678024, 2276966678024)
# 改变一个都会改变
d['a'].extend('34')
print(d)
print(d1)
{'a': [1, 2, '3', '4'], 'b': 3}
{'a': [1, 2, '3', '4'], 'b': 3}
字典方法 dict.pop(),Python 官方文档描述如下:
help(dict.pop)
Help on method_descriptor:
pop(...)
D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
If key is not found, d is returned if given, otherwise KeyError is raised
如果字典的键 k 存在,则移除 k 对应的 键值对,并返回 值;
如果 k 不存在,但指定了可选参数 d,则返回 d;
如果 k 不存在且未指定 d,则引发 KeyError。
d = {'a':1, 'b':2}
d.pop('a')
1
d = {'a':1, 'b':2}
d.pop('c', 3)
3
d = {'a':1, 'b':2}
d.pop('c')
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-4-1e5ab2c0b86c> in <module>
1 d = {'a':1, 'b':2}
----> 2 d.pop('c')
KeyError: 'c'
字典方法 dict.popitem(),Python 官方文档描述如下:
help(dict.popitem)
Help on method_descriptor:
popitem(self, /)
Remove and return a (key, value) pair as a 2-tuple.
Pairs are returned in LIFO (last-in, first-out) order.
Raises KeyError if the dict is empty.
按 后进先出 的原则,删除字典的元素,并以 (key, value) 元组返回。如果字典为空,则引发 KeyError。
d = {2:2,1:1}
d.popitem()
(1, 1)
d = {}
d[1] = 1
d[3] = 3
d[2] = 2
d[3] = 30 # 更新并不改变元素插入顺序
d.popitem(),d.popitem(),d.popitem()
((2, 2), (3, 30), (1, 1))
d = {}
d.popitem()
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-13-3d5a99fd0340> in <module>
1 d = {}
----> 2 d.popitem()
KeyError: 'popitem(): dictionary is empty'
字典的方法 fromkeys,Python 官方文档描述如下:
help(dict.fromkeys)
Help on built-in function fromkeys:
fromkeys(iterable, value=None, /) method of builtins.type instance
Create a new dictionary with keys from iterable and values set to value.
使用可迭代对象 iterable 中的元素作为字典的键,value 为值(默认是 None)创建字典。
dict.fromkeys('123')
{'1': None, '2': None, '3': None}
dict.fromkeys([1,2,3], 0)
{1: 0, 2: 0, 3: 0}
可迭代对象中不能包含不可哈希对象:
dict.fromkeys([[1],2,3], 0)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-6-470a0d0c77b4> in <module>
----> 1 dict.fromkeys([[1],2,3], 0)
TypeError: unhashable type: 'list'
字典方法 dict.clear(),Python 官方文档描述如下:
help(dict.clear)
Help on method_descriptor:
clear(...)
D.clear() -> None. Remove all items from D.
清空字典元素。
d = {'a':1, 'b':2}
d.clear()
d
{}
该方法是一个过程,返回值为 None。
d = {'a':1, 'b':2}
print(d.clear())
None
字典方法 dict.setdefault(),Python 官方文档描述如下:
help(dict.setdefault)
Help on method_descriptor:
setdefault(self, key, default=None, /)
Insert key with a value of default if key is not in the dictionary.
Return the value for key if key is in the dictionary, else default.
如果字典存在键 key,则返回它的值;如果 key 不存在,则插入 key,以 default(默认 None)作为它的值,并返回。
d = {'a':1, 'b':2}
d.setdefault('a')
1
d.setdefault('c', 3)
3
d
{'a': 1, 'b': 2, 'c': 3}
d.setdefault('c', 4) # 如果存在,并不会再次设置
3
d
{'a': 1, 'b': 2, 'c': 3}
字典方法 dict.update(),Python 官方文档描述如下:
help(dict.update)
Help on method_descriptor:
update(...)
D.update([E, ]**F) -> None. Update D from dict/iterable E and F.
If E is present and has a .keys() method, then does: for k in E: D[k] = E[k]
If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v
In either case, this is followed by: for k in F: D[k] = F[k]
更新字典,键相同,则覆盖原有的值,不同,则增加 键值对 元素。有下列几种情况:
d = {'a':1, 'b':2}
d.update({'a':10, 'c':3})
d
{'a': 10, 'b': 2, 'c': 3}
d = {'a':1, 'b':2}
d.update([('a',10),['c',3]])
d
{'a': 10, 'b': 2, 'c': 3}
d = {'a':1, 'b':2}
d.update(a=10, c=3)
d
{'a': 10, 'b': 2, 'c': 3}
字典是可迭代对象,可以遍历字典的元素。由于字典元素是 键值对,遍历比较特殊。
如果未指定遍历对象,默认遍历字典的键。很多函数将字典作为可迭代对象处理时,也是如此。
d = {'a':1, 'c':3, 'b':2}
for k in d:
print(k)
a
c
b
list(d)
['a', 'c', 'b']
sorted(d)
['a', 'b', 'c']
max(d)
'c'
可以利用字典的视图指定遍历字典的键(默认就是遍历键,可以省略),值 或是 键值对。
d = {'a':1, 'c':3, 'b':2}
for k in d.keys(): # 可以不用视图
print(k)
a
c
b
d = {'a':1, 'c':3, 'b':2}
for k in d.values():
print(k)
1
3
2
d = {'a':1, 'c':3, 'b':2}
for k,v in d.items():
print(k,v)
a 1
c 3
b 2
# 按值排序后再遍历
d = {'a':1, 'c':3, 'b':2}
for k,v in sorted(d.items(),key=lambda x:x[1]):
print(k,v)
a 1
b 2
c 3
字典不可以使用比较大小的操作符 <
, <=
, >=
和 >
,会引发 TypeError。
{1:1} < {2:2}
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-1-8ea82599b938> in <module>
----> 1 {1:1} < {2:2}
TypeError: '<' not supported between instances of 'dict' and 'dict'
字典比较相等时,当且仅当 键值对 都相等时才相等。
{1:1.0, 2:2} == {2:2, True:1}
True
{1:'1', 2:2} == {2:2, 1:1}
False
字典可以使用 **
操作符进行拆包,拆包后置于新字典中,可以用来更新字典;或拆包后作为关键字参数传递给函数。
{'a':1, 'b':2, **{'a':10}}
{'a': 10, 'b': 2}
d = {'a':1, 'b':2}
'a={a},b={b}'.format(**d)
'a=1,b=2'
Python 3.9 新版,实现了两个操作符 |
和 |=
:
{'a':1} | {'b':2}
{'a': 1, 'b': 2}
合并 d 和 other 中的键和值来创建一个新的字典,两者必须都是字典。当 d 和 other 有相同键时,other 的值优先。
{'a':1} | {'a':5, 'b':2}
{'a': 5, 'b': 2}
用 other 的键和值更新字典 d ,other 可以是映射(mapping)或可迭代对象(iterable)的键值对。当 d 和 other 有相同键时,other 的值优先。
生成器表达式和列表推导式非常相似,区别就是将方括号换成了小括号。
生成器表达式返回的是一个生成器迭代器 generator。表达式会产生一系列值,可使用内置函数 next() 逐一获取,或使用 for 循环遍历。
生成器迭代器中的元素,仅供一次性使用,而且可以要多少取多少,它会记住你取了多少,取到了哪里。
(i*i for i in range(3))
<generator object <genexpr> at 0x00000271080FBC00>
g = (i*i for i in range(5))
type(g)
generator
next(g), next(g)
(0, 1)
for i in g:
print(i)
4
9
16
这种表达式被设计用于生成器将立即被外层函数所使用的情况。生成器表达式相比完整的生成器更紧凑但较不灵活,相比等效的列表推导式则更为节省内存。
sum(i*i for i in range(5))
30
list(i*i for i in range(5))
[0, 1, 4, 9, 16]
除了列表推导式和生成器表达式,集合和字典也可使用类似的推导式。
{i*2 for i in 'abac'}
{'aa', 'bb', 'cc'}
{i:j for i,j in zip('abc',(1,2,3))}
{'a': 1, 'b': 2, 'c': 3}
空值 None,此对象会由没有显式地设置返回值的函数返回。None 是个内置名称,空对象求值,什么也不会发生。
None
help(None)
Help on NoneType object:
class NoneType(object)
| Methods defined here:
|
| __bool__(self, /)
| self != 0
|
| __repr__(self, /)
| Return repr(self).
|
| ----------------------------------------------------------------------
| Static methods defined here:
|
| __new__(*args, **kwargs) from builtins.type
| Create and return a new object. See help(type) for accurate signature.
# 没有返回值的列表方法
a = [].append(1)
a
# 将 a 打印出来,将打印内置名称 None
print(a)
None
内置类型除了数字类型,布尔类型,序列类型,集合类型,映射类型,迭代器类型,解释器支持的还有一些其他种类的对象。这些对象大都仅支持一两种操作。
模块唯一的特殊操作是属性访问: m.name
,这里 m 为一个模块而 name 为定义在 m 的符号表中的一个属性的名称。模块属性可以被赋值。import 语句严格来说也是对模块对象的一种操作。关于模块有详细的知识点介绍。
type(math)
module
import math
math.pi
3.141592653589793
函数对象是通过函数定义创建的。对函数对象的唯一操作是调用它: func(argument-list)。
实际上存在两种不同的函数对象:内置函数和用户自定义函数。两者支持同样的操作(调用函数),但实现方式不同,因此对象类型也不同。关于函数有详细的知识点介绍。
print('abc') # 调用函数
abc
type(print)
builtin_function_or_method
def f():pass # 自定义函数
type(f)
function
方法是在类中定义,使用属性表示法来调用的函数。关于方法有详细的知识点介绍。
type(list.append)
method_descriptor
type([].append)
builtin_function_or_method
代码对象可由内置的 compile() 函数返回,也可通过从函数对象的 __code__
属性从中提取。
可将代码对象(而非源码字符串)传给 exec() 或 eval() 内置函数来执行或求值。
def f():
print('代码对象')
code = f.__code__
type(code)
code
exec(code)
代码对象
类型对象表示各种对象类型。对象的类型可通过内置函数 type() 来获取。类型没有特殊的操作。标准库模块 types 定义了所有标准内置类型的名称。
type(int), type(list)
(type, type)
type(1), type([])
(int, list)
操作符可分为运算符(operators)和分隔符(delimiters)。
运算符有:
+
,-
,*
,**
,/
,//
,%
,详细用法见 数字运算。
<<
,>>
,&
,|
,^
,~
,详细用法见 整数及其位运算。
<
,>
,<=
,>=
,==
,!=
,in
,not in
,is
,is not
,详细用法见 比较运算符。
and
,or
,not
,详细用法见 布尔值及布尔运算。
:=
Python 3.8 新增,将右边的表达式赋值给左边的变量, 同时返回表达式的值。
(a := 1+1)
2
运算符还分为一元运算符和二元运算符,一元运算符运算一个对象(操作数),二元运算符运算两个。一元运算符有 +
(正数),-
(负数),~
(整数按位取反)和 not
(布尔运算 非)。if ... else ...
有时称作三元运算符。
-1, +2, ~3, not 4
(-1, 2, -4, False)
1 + 2 - 3 * 4 # 二元运算符加、减和乘
-9
True if 2 > 3 else False
False
分隔符有:
(
,)
,[
,]
,{
,}
,,
,:
,.
,;
,=
,+=
,-=
,*=
,/=
,//=
,%=
,&=
,|=
,^=
,>>=
,<<=
,**=
部分分隔符用法举例:
圆括号绑定表达式,或元组显示,方括号用来对序列进行索引、切片取值或列表显示,花括号字典显示或集合显示
3 * (1 + 2) * (1,)
(1, 1, 1, 1, 1, 1, 1, 1, 1)
[1,2,3,4][1:3]
[2, 3]
{'列表':[], '集合':{1,2,3}}
{'列表': [], '集合': {1, 2, 3}}
上述分隔符 =
为赋值操作符,之后的操作符为增强赋值操作符,将名称绑定(或重新绑定)到特定值,以及修改属性或可变对象的成员项。 详见 赋值语句。
假设将值 value1 绑定到名称 name,name = value1
,则 name += value2
的结果相当于 name = name + value2
,其他操作符类似。
举例如下:
a = 1
a += 1
a
2
b = 17
b |= 5
b
21
除了运算符和分隔符,还有 '
,"
,\
,#
字符,作为其他字符的组成部分时具有特殊含义,或是对词法分析器有重要意义。
#
通常用来注释代码,但不能包含在字符串中,注释在语法分析中会被忽略:
# 这是注释
'''
# hello world
# hello python
'''
'\n# hello world\n# hello python\n'
操作符除了常规的用法,操作不同的数据类型,相应的数据类型可能定义了特定的操作规则;在特定的应用场景,也有着特殊的用法。详见 操作符特殊用法
比较运算符有 <
,>
,<=
,>=
,==
,!=
,in
,not in
,is
,is not
。
运算符 <
,>
,>=
,<=
,==
和 !=
比较两个对象的值,<
,>
,>=
和 <=
称为次序比较;==
和 !=
称为一致性比较。
由于所有类型都是 object 的(直接或间接)子类型,它们都从 object 继承了默认的比较行为,一致性比较是默认的比较行为,因此可在任何对象之间进行。
False == 0 != 'a' != int != {}
True
对象的值在 Python 中是一个相当抽象的概念:
主要内置类型的比较行为:
1,数字类型内部可跨类型比较,按数学(算法)规则正确进行比较且不会有精度损失。但复数不支持次序比较。
True == 1 == 1.0
True
3.14 < 3
False
0 >= 0j
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-6-df80cad0b1a4> in <module>
----> 1 0 >= 0j
TypeError: '>=' not supported between instances of 'int' and 'complex'
2,字符串使用其字符的 Unicode 码位数字值依次进行比较,某个字符比较出大小即停止。如果一个字符串包含另一个,较短的排前面。
ord('a'), ord('b'), ord('c')
(97, 98, 99)
'a' == 'a', 'a' == 'c'
(True, False)
'ab' < 'ac'
True
'abc' > 'ab'
True
3,序列(列表,元组,range 实例)只能进行类型内部比较。跨类型一致性比较结果将是不相等,跨类型次序比较将引发 TypeError。range 不支持次序比较。
比较时按顺序对相应元素进行逐个比较,某个元素比较出大小即停止。如果一个序列元素包含另一个,较短的排前面。
(1,2) == [1,2]
False
[1,2] == [1,2]
True
[1,4] > [1,3,7]
True
[1,4] < [1,4,7]
True
(1,2) >= [1,2]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-22-cb12354bca8e> in <module>
----> 1 (1,2) >= [1,2]
TypeError: '>=' not supported between instances of 'tuple' and 'list'
4, 两个字典若要相等,必须当且仅当它们具有相同的 键值对。次序比较将引发 TypeError。
{1:1} == {True:1.0}
True
{1:1} <= {True:1.0}
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-24-a13e7674e543> in <module>
----> 1 {1:1} <= {True:1.0}
TypeError: '<=' not supported between instances of 'dict' and 'dict'
5,集合 (set 或 frozenset 的实例) 可进行类型内部和跨类型的比较。
它们将比较运算符定义为子集和超集检测,具体详见集合知识点。这类关系没有定义完全排序。相应地,集合不适宜作为依赖于完全排序的函数的参数。
{1,2} == frozenset([1,2,1])
True
{3,1} > {1,2}
False
sorted([{3},{1},{2}])
[{3}, {1}, {2}]
运算符 in
和 not in
用于成员检测。如果 x 是 s 的成员则 x in s
求值为 True,否则为 False。x not in s
返回 x in s
取反后的值。
所有内置序列和集合类型以及字典都支持此运算,对于字典来说 in 检测其是否有给定的键。
'a' in 'abc'
True
'abc' in 'abbc'
False
1 in [1,2]
True
[1] in [1,2]
False
'a' in {'a':1}
True
运算符 is
和 is not
用于检测对象的标识号:当且仅当 x 和 y 是同一对象时 x is y
为真。一个对象的标识号可使用 id() 函数来确定。x is not y
会产生相反的逻辑值。
默认的一致性比较是基于对象的标识号。x is y
就意味着 x == y
。
a = 1
b = 1
a is b, a == b
(True, True)
a = (1,3)
b = (1,3)
a is b, a == b
(False, True)
Python 表达式语句中操作符的优先顺序从最低优先级(最后绑定)到最高优先级(最先绑定)如下:
:=
赋值表达式lambda
lambda 表达式if -- else
条件表达式or
布尔逻辑或 ORand
布尔逻辑与 ANDnot x
布尔逻辑非 NOTin
, not in
, is
, is not
, <
, <=
, >
, >=
, !=
, ==
比较运算|
按位或 OR^
按位异或 XOR&
按位与 AND<<
, >>
移位+
, -
加和减*
, /
, //
, %
乘,矩阵乘,除,整除,取余+x
, -x
, ~x
正,负,按位非 NOT**
乘方(右边的先绑定)await x
await 表达式x[index]
, x[index:index]
, x(arguments...)
, x.attribute
抽取,切片,调用,属性引用(expressions...)
, [expressions...]
, {key: value...}
, {expressions...}
绑定或加圆括号的表达式,列表显示,字典显示,集合显示一个表达式语句中可以有多个上述操作符,最终返回一个值(包括返回值为 None 的函数调用)。
而赋值语句中的赋值操作符 =
,+=
,-=
,*=
,/=
,//=
,%=
,&=
,|=
,^=
,>>=
,<<=
,**=
,在操作符中优先级最低,它右边表达式的值计算完之后,才最后绑定到左边的名称。
举例如下:
value = int('2')**(-1) == 2/(3+1)
value
True
int('2')**(-1) == 2/(3+1)
True
[].append(1) is None and not 1 - 1
True
value = 1 if 'a' in 'a b c'.split()[1:3] else 2
value
2
value **= 3 + 2 * 1
value
32
操作符 =
可以用来连续赋值:
a = b = c = 1
a,b,c
(1, 1, 1)
容器类的内置类型,通常对操作符定义了自己特有的的操作行为。
*
操作符,除了数字运算的 乘,还可以用来将可迭代对象拆包。拆包之后置于元组,列表,集合中,或作为参数传递给函数:{*{'a':1, 'b':2}}
{'a', 'b'}
print(*'abc', sep='-')
a-b-c
+
,+=
,*
,*=
可用来对序列类型进行拼接,重复拼接或拼接并赋值(range 类型除外)。由于列表是可变对象,+=
和 *=
在操作列表时,是用来更新列表。具体详见 列表操作符。'd-' + 'abc'*2
'd-abcabc'
a = [1]*2
a += [2]
a
[1, 1, 2]
语句分为简单语句和复合语句,简单语句由一个单独的逻辑行构成。多条简单语句可以存在于同一行内并以分号分隔。表达式语句属于简单语句。
表达式语句用于计算和写入值(大多是在交互模式下),或者调用一个过程 (过程就是不返回有意义结果的函数。在 Python 中,过程的返回值为 None)。
表达式语句会对指定的表达式进行求值。
在交互模式下,它会通过内置的 repr() 函数转换为一个字符串,该结果字符串将以单独一行的形式写入标准输出(例外情况是如果结果为 None,则该过程调用不产生任何输出)。
以下均是一个表达式语句(可包含多个表达式):
'python'
'python'
1
1
(a := 1) # 3.8 新功能,赋值表达式
1
a
1
'a\n',f'b{1}' # 两个表达式
('a\n', 'b1')
1 + 2 * 3 / 5, True and False # 两个表达式
(2.2, False)
lambda x: x**2
<function __main__.<lambda>(x)>
0 if 2>3 else (1 if 5<6 else 2)
1
[1,2,3] + [4]
[1, 2, 3, 4]
[].append(1) # 返回 None
[].append(1) is None
True
# 返回值为 None,输出并不是表达式的值
print('非表达式的值') is None
非表达式的值
True
sum(i for i in [3,2,5])
10
list(zip('abc',[1,2,3]))[1:]
[('b', 2), ('c', 3)]
用分号分隔多个表达式语句,输出最后一个的值。
1; print('非表达式的值'); 1 + 2 * 3 / 5, True and False
非表达式的值
(2.2, False)
赋值语句用于将名称绑定或重新绑定到特定值,以及修改属性或可变对象的成员项。
赋值语句使用赋值操作符和增强赋值操作符。详见 操作符概述。
# 将值 1 绑定到变量 a
a = 1
print('a =', a)
# 变量 a 重新绑定值 'a'
a = 'a'
print('a =', a)
a = 1
a = a
同时进行多个值多个名称绑定,值和名称数量要相等:
# 一个名称时,右边为元组
a = 1,2,3,4
a
(1, 2, 3, 4)
# 多个名称
a,b,c,d = 1,[2,3],4,5
f'a={a},b={b},c={c},d={d}'
'a=1,b=[2, 3],c=4,d=5'
# 可迭代对象拆包,则需要更多名称
a,b,c,d,e = 1,*[2,3],4,5
f'a={a},b={b},c={c},d={d},e={e}'
'a=1,b=2,c=3,d=4,e=5'
赋值一般左右两边一一对应 “同时” 赋值,但赋值给变量的多项集时可能不一样(例如列表的某一项):
x = [0,1]
i = 0
i, x[i] = 1, 2
f'x={x},i={i}'
'x=[0, 2],i=1'
修改属性或可变对象的成员项:
# 新增属性
class A:
x = 1
a = A()
# 右边的 a.x 是访问类属性
# 左边的 a.x 是新增实例属性, 值为类属性值 + 1
a.x = a.x + 1
a.x, A.x
(2, 1)
# 修改列表项
a = [1,2,3]
a[0] = [0,1]
a
[[0, 1], 2, 3]
# 修改或新增字典项
d = {'a':1}
d['a'] = 10
d['b'] = 2
d
{'a': 10, 'b': 2}
赋值操作符 =
,可以进行连续赋值,绑定多个名称,但赋值语句非表达式语句,不能被求值,因此不能被括号包围或分隔:
a = b = c = 1
a,b,c
(1, 1, 1)
a = (b = c = 1)
File "<ipython-input-40-5dae496e91ce>", line 1
a = (b = c = 1)
^
SyntaxError: invalid syntax
不可变容器的增强赋值操作,是重新绑定对象;可变容器的增强赋值操作是增、删、改成员项:
s = '123'
print(id(s),s)
# 因为不可变,相当于新建了一个字符串 '1234' 重新绑定 s
s += '4'
print(id(s),s)
2371959191728 123
2371959179632 1234
l = [1,2,3]
print(id(l),l)
# 可变,相当于在原列表 l 中增加元素 4
l += [4]
print(id(l),l)
2371958877312 [1, 2, 3]
2371958877312 [1, 2, 3, 4]
l = [1,2,3]
print(id(l),l)
l *= 0 # 清空列表
print(id(l),l)
2371958290048 [1, 2, 3]
2371958290048 []
s = {1,2,3}
print(id(s),s)
s |= {0}
print(id(s),s)
2371958464800 {1, 2, 3}
2371958464800 {0, 1, 2, 3}
带标注的赋值语句。单个语句中将变量或属性标注和可选的赋值语句合为一体。标注对提高代码的可读性非常有用,看标注而不需要看代码上下文就大概知道代码的使用。
# 标注函数参数的类型及默认值
def f(n:int=1):
print('Hi'*n)
f(2)
HiHi
name: str = '小张'
name
'小张'
if 语句用于有条件的执行。语法如下:
if assignment_expression:
suite
elif assignment_expression: # 可选子句
suite
... # 可以多个 elif
else: #可选子句
suite
对于简单语句,可以写为一行,但不推荐。
它通过对表达式逐个求值直至找到一个真值。然后执行该 if 语句或子句体下的代码,从而 if 语句的其他部分不会被执行或求值。
如果所有表达式均为假值,else 子句体如果存在就会被执行。
for i in range(5):
if i % 2 == 0:print(i)
0
2
4
for i in range(5):
if i % 2 == 0:
print(i)
0
2
4
i,j = 0,1
if i < 0:
print(i) # 不执行
elif i == 0:
print(i) # 执行,下面的则不再执行
elif j == 1:
print(j)
else:
print(i,j)
0
i,j = 0,1
if i < 0:
print(i) # 不执行
elif i == 1:
print(i) # 不执行
elif j == 0:
print(j) # 不执行
else:
print(i,j) # 执行
0 1
多个 if 语句连用,则分别判断,互不影响:
i,j = 0,1
if i < 0:
print(i) # 不执行
else:
print(i,j) # 执行
if i == 0:
print(i) # 执行
if j == 1:
print(j) # 执行
else:
print(i,j) # 不执行
0 1
0
1
for 语句用于对可迭代对象中的元素进行迭代。语法如下:
for target_list in expression_list:
suite
else: # 可选子句
suite
对于简单语句可以写为一行,但不推荐。
表达式 expression_list 被求值一次,它应该产生一个可迭代对象。系统将为 expression_list 的结果创建一个迭代器,然后每一项会按标准赋值规则(详见见 赋值语句)被依次赋值给 target_list,每赋值一次执行一次语句下的代码。
当所有项被耗尽时,else 子句如果存在将会被执行,并终止循环。
for i in range(3):print(i)
0
1
2
for i in zip('123','abc'):
print(i)
('1', 'a')
('2', 'b')
('3', 'c')
for i,j in zip('123','abc'):
print(f'{i}->{j}')
else:
print('end')
1->a
2->b
3->c
end
for 循环会对 target_list 中的变量进行赋值。这将覆盖之前对这些变量的所有赋值,包括在 for 循环体中的赋值。
变量在循环结束时不会被删除,但如果序列为空,则它们根本不会被循环所赋值。
i = 'a'
for i in range(3):
print(i)
print(i)
0
1
2
2
for i in range(0):
print(i)
print(i)
2
while 语句用于在表达式保持为真的情况下重复地执行。语法如下:
while assignment_expression:
suite
else: # 可选子句
suite
对于简单语句可以写为一行,但不推荐。
这将重复地检验表达式,如果其值为真就执行其下的代码;表达式值为假则如果 else 子句存在就会被执行并终止循环。
i = 0
while i < 3: print(i); i += 1
0
1
2
i = 0
while i < 3:
print(i)
i += 1
else: # i 为 3 时执行
print(f'i={i}')
print('end')
0
1
2
i=3
end
break 在语法上只会出现于 for 或 while 循环所嵌套的代码。
它会终结最近的外层循环,如果循环有可选的 else 子句,也会跳过该子句。
如果一个 for 循环被 break 所终结,该循环的控制变量会保持其当前值。
当 break 将控制流传出一个带有 finally 子句的 try 语句时,该 finally 子句会先被执行然后再真正离开该循环。
for i in range(6):
for j in range(6):
if i**2 == j:
print(f'i={i},j={j}')
print(f'i={i},j={j}')
i=0,j=0
i=1,j=1
i=2,j=4
i=5,j=5
for i in range(6):
for j in range(6):
if i**2 == j:
print(f'i={i},j={j}')
break
print(f'i={i},j={j}')
i=0,j=0
i=5,j=0
for i in range(6):
for j in range(6):
if i**2 == j:
print(f'i={i},j={j}')
break # 控制内层循环
else: # 不会执行
print(f'i={i},j={j}')
i=0,j=0
for i in range(6):
for j in range(6):
if i**2 == j:
print(f'i={i},j={j}')
break
else: # 属于外层循环,会执行
print(f'i={i},j={j}')
i=0,j=0
i=5,j=0
for i in range(5):
try:
print(f'3/i={3/i}')
except ZeroDivisionError as e:
print(e)
finally:
print(f'i={i}')
division by zero
i=0
3/i=3.0
i=1
3/i=1.5
i=2
3/i=1.0
i=3
3/i=0.75
i=4
# 引发异常直接跳过 break
# 无异常则继续执行完 finally 才终止循环
for i in range(5):
try:
print(f'3/i={3/i}')
break
except ZeroDivisionError as e:
print(e)
finally:
print(f'i={i}')
division by zero
i=0
3/i=3.0
i=1
continue 在语法上只会出现于 for 或 while 循环所嵌套的代码中。
它会继续执行最近的外层循环的下一个轮次,或者在没有下一轮次时转往 else 子句执行。
当 continue 将控制流传出一个带有 finally 子句的 try 语句时,该 finally 子句会先被执行然后再真正开始循环的下一个轮次。
for i in range(3):
for j in range(3):
if j == 1:
print(f'i={i},j={j}')
continue
i=0,j=1
i=1,j=1
i=2,j=1
for i in range(3):
for j in range(3):
if j == 2:
print(f'i={i},j={j}')
continue
else: # 属于内层循环,每次内层循环结束都执行
print('end')
i=0,j=2
end
i=1,j=2
end
i=2,j=2
end
for i in range(3):
for j in range(3):
if j == 2:
print(f'i={i},j={j}')
continue
else: # 属于外层循环,外层循环结束才执行
print('end')
i=0,j=2
i=1,j=2
i=2,j=2
end
# 引发异常直接跳过 continue
# 无异常则继续执行完 finally 才继续下一次循环
for i in range(3):
try:
print(f'3/i={3/i}')
continue
except ZeroDivisionError as e:
print(e)
finally:
print(f'i={i}')
print(i) # 无异常时被跳过
else:
print('end')
division by zero
i=0
0
3/i=3.0
i=1
3/i=1.5
i=2
end
del 语句用来删除名称的绑定,删除对象的属性引用 或 删除可抽取、切片的可变容器的元素。
删除名称绑定:
# 将值 (1,2) 绑定到名称 a, b, c
a = b = c = (1,2)
# 删除名称 b, c
del b,c
a
(1, 2)
b # 名称 b 已被删除
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-27-9185c0ba25e7> in <module>
----> 1 b # 名称 b 已被删除
NameError: name 'b' is not defined
class A:
x = y = 1
A.x, A.y
(1, 1)
del A.y
print(A.x)
A.y # 属性名称 y 已被删除,不可引用值 1
1
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-29-8ed1b3e470b1> in <module>
1 del A.y
2 print(A.x)
----> 3 A.y # 属性名称 y 已被删除,不可引用值 1
AttributeError: type object 'A' has no attribute 'y'
# 删除字典元素
d = {'a':1,'b':2}
del d['a'] # 删除键为 'a' 的元素
print(d)
d['a']
{'b': 2}
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-30-5d91a843f82e> in <module>
3 del d['a'] # 删除键为 'a' 的元素
4 print(d)
----> 5 d['a']
KeyError: 'a'
# 删除列表切片
_list = [1,2,3,4]
del _list[::2]
_list
[2, 4]
# 删除列表切片
_list = [1,2,3,4]
del _list[:] # 相当于 _list[:] = []
_list
[]
pass 是一个空操作 —— 当它被执行时,什么都不发生。
它适合当语法上需要一条语句但并不需要执行任何代码时用来临时占位,例如:
pass
# 什么也不做的函数
def f():pass
# 没有任何自定义属性的类
class A:pass
def 语句是定义函数的语句。语法如下:
@assignment_expression
def funcname(parameter_list) -> expression:
suite
其中的装饰器 @assignment_expression
,形参 parameter_list
和标注 -> expression
是可选项。
函数定义是一条可执行语句。它执行时会将函数名称 funcname
绑定到一个函数对象(函数可执行代码的包装器)。
例如,用必选项定义一个什么也不做的函数如下:
def f():
pass
f
<function __main__.f()>
一个函数定义可以被一个或多个装饰器表达式所包装。
装饰器必须是可调用对象,它会以该函数对象作为唯一参数被发起调用。
其返回值将被绑定到函数名称。多个装饰器会以嵌套方式被应用。
@str
@type
def f():pass
f
"<class 'function'>"
大致相当于:
def f():pass
f = str(type(f))
f
"<class 'function'>"
函数形参 parameter_list
详见 函数形参。
函数标注 -> expression
可以是任何表达式,标注对提高代码的可读性非常有用,看标注而不需要看代码上下文就大概知道代码的使用。例如:
# 标注函数的参数和返回值类型
def f(arg:int) -> list:
return list(str(arg))
f(123)
['1', '2', '3']
return 在语法上只会出现于函数定义所嵌套的代码,不会出现于类定义所嵌套的代码。
如果提供了表达式,它将被求值,否则以 None 替代(类似省略 return 语句结果)。
return 会离开当前函数调用,并以表达式的值 (或 None) 作为返回值。
当 return 将控制流传出一个带有 finally 子句的 try 语句时,该 finally 子句会先被执行然后再真正离开该函数。
def f2():
x =1
print(f2())
None
def f1():
x = 1
return
print(f1())
None
# return 结束函数调用
def f(x):
return x**2
print('end') # retrun 结束函数调用,不会被执行
f(2)
4
# finally 总是被执行再结束函数调用
def f(x):
try:
return 3/x
except ZeroDivisionError as e:
print(e)
finally:
return x, x**2
f(0),f(2)
division by zero
((0, 0), (2, 4))
yield 语句,仅在定义 生成器函数 时使用,并且仅被用于生成器函数的函数体内部。语法如下:
yield from expression
from
和表达式 expression
是可选的,没有表达式默认是 None。
yield 语句整体也是一个可被求值的表达式语句,初始值也是默认 None,可通过 send 方法设置 yield 表达式的值。
在函数定义中使用 yield 使得该定义创建的是生成器函数而非普通函数。当一个生成器函数被调用的时候,它返回一个生成器迭代器。
yield from 相当于将一个可迭代对象 “拆包”,然后逐项被生成器迭代时使用。
# 创建一个简单的生成器函数
def f():
yield
print(f)
# 调用它获得一个生成器
print(f())
# next() 函数迭代生成器获取表达式的值
print(next(f()))
<function f at 0x00000157028A9598>
<generator object f at 0x000001570286CB88>
None
# 获取并设置 yield 语句的值
def f(n):
x = yield n
print(x)
g = f(1)
print(next(g))
# 迭代结束,打印出 yield 语句 x 的初始值为 None
print(next(g,'end'))
1
None
end
# 可通过 send 方法设置当前 yield 表达式的值
# 并返回生成器产生的下一个值
def f(n):
x = yield n
print(f'yield 表达式的值为:{x}')
n += 1
yield n
g = f(0)
next(g), g.send(10)
yield 表达式的值为:10
(0, 1)
def f(*args):
yield from args
g = f(1,2,3)
next(g),next(g),next(g),next(g,'end')
(1, 2, 3, 'end')
def f(arg):
yield from arg
g = f('123')
next(g),next(g),next(g),next(g,'end')
('1', '2', '3', 'end')
class 语句用来定义类,语法如下:
@assignment_expression
class classname(argument_list):
suite
其中的装饰器 @assignment_expression
,基类参数及圆括号 (argument_list)
是可选项。
类定义是一条可执行语句。它执行时会将类名称 classname 绑定到一个新建的类对象。
没有继承基类参数 argument_list 的类默认继承自基类 object。下列是一个必选参数定义的类,默认继承自 object:
# 创建一个类名为 A 的类
class A: pass
A.__bases__ # 查看基类
(object,)
# 创建一个类 B 继承自 int 和 A
class B(int, A):
pass
B.__bases__
(int, __main__.A)
类也可以被装饰,就像装饰函数一样,装饰器表达式的求值规则与函数装饰器相同(详见 def 定义函数)。结果随后会被绑定到类名称。
@str
@type
class C: pass
C
"<class 'type'>"
大致相当于:
class C: pass
C = str(type(C))
C
"<class 'type'>"
try 语句可为一组语句指定异常处理器和/或清理代码。语法结构有两种如下。
try:
suite
except expression as identifier:
suite
else: # 可选
suite
finally: # 可选
suite
try:
suite
finally:
suite
except 子句之后的表达式(通常为异常)expression
,关键字 as
以及指定的别名 identifier
都是可选的。
当 try 子句中没有发生异常时,没有异常处理器会被执行。当 try 子句中发生异常时,将启动对异常处理器的搜索。此搜索会依次检查 except 子句,直至找到与该异常相匹配的子句。
except 子句可指定一个或多个异常,如果与发生的异常 “兼容” 则该子句将匹配该异常。
当一个异常完全未被处理时,解释器会终止程序的执行。
for i in range(3):
try:
print(3/i)
except (ZeroDivisionError, AssertionError) as e:
print(e)
division by zero
3.0
1.5
for i in range(3):
try:
print(3/i)
except ZeroDivisionError:
print(f'i={i}引发异常')
i=0引发异常
3.0
1.5
for i in range(3):
print(3/i)
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-5-ddbcfc1a1b1b> in <module>
1 for i in range(3):
----> 2 print(3/i)
ZeroDivisionError: division by zero
如果存在无表达式的 except 子句,它必须是最后一个,它将匹配任何异常:
try:
3/0
except NameError as n:
print(n)
except:
pass
如果没有 except 子句与异常相匹配,则会在周边代码和发起调用栈上继续搜索异常处理器,除非存在一个finally 子句正好引发了另一个异常。新引发的异常将导致旧异常的丢失:
def f():
try:
return 3/0
except NameError as n:
print(n)
try:
f()
except ZeroDivisionError as z:
print(z)
division by zero
def f():
try:
return 3/0
except NameError as n:
print(n)
finally:
name1
try:
f()
except ZeroDivisionError as z: # 该异常已丢失
print(z)
except NameError as n:
print(n)
name 'name1' is not defined
使用 as 将匹配的异常赋值给一个别名,才能在 except 子句之后引用它,并且它将在 except 子句结束时被清除:
for i in range(3):
try:
print(3/i)
except (ZeroDivisionError, AssertionError) as e:
print(e)
print(e)
division by zero
3.0
1.5
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-16-a87e190baccb> in <module>
4 except (ZeroDivisionError, AssertionError) as e:
5 print(e)
----> 6 print(e)
NameError: name 'e' is not defined
如果控制流离开 try 子句体时没有引发异常,并且没有执行 return, continue 或 break 语句,可选的 else 子句将被执行:
try:
print('开始')
except:
print('捕获')
else:
print('结束')
开始
结束
while True:
try:
print('开始')
break
except:
print('捕获')
else:
print('结束')
开始
如果存在 finally,它用来指定一个 “清理” 处理程序。try,except 或 else 子句中发生任何未处理的异常,会被临时保存。finally 始终被执行,被保存的异常,它会在 finally 子句执行后被重新引发:
try:
print(3/0)
except:
name2
else: # 未被执行
range(3)[5]
finally:
print('end')
end
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-24-7d6fe0d94043> in <module>
1 try:
----> 2 print(3/0)
3 except:
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
NameError Traceback (most recent call last)
<ipython-input-24-7d6fe0d94043> in <module>
2 print(3/0)
3 except:
----> 4 name2
5 else: # 未被执行
6 range(3)[5]
NameError: name 'name2' is not defined
如果 finally 子句引发了另一个异常,被保存的异常会被设为新异常的上下文。如果 finally 子句执行了 return, break 或 continue 语句,则被保存的异常会被丢弃:
while True:
try:
print('开始')
except:
print('捕获')
else:
range(3)[5]
finally:
print(3/0)
开始
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-25-1f272bfbd667> in <module>
6 else:
----> 7 range(3)[5]
8 finally:
IndexError: range object index out of range
During handling of the above exception, another exception occurred:
ZeroDivisionError Traceback (most recent call last)
<ipython-input-25-1f272bfbd667> in <module>
7 range(3)[5]
8 finally:
----> 9 print(3/0)
ZeroDivisionError: division by zero
while True:
try:
print('开始')
except:
print('捕获')
else:
range(3)[5]
finally:
break
开始
当 return, break 或 continue 语句在 finally 语句之前被执行时,finally 子语句也会 ‘在离开时’ 被执行:
while True:
try:
print('开始')
except:
print('捕获')
else:
break
finally:
print('结束')
开始
结束
def f():
try:
return '开始'
finally:
print('结束')
f() # 先执行 finally 再离开函数调用
结束
'开始'
raise 语句用来引发异常。语法如下:
raise expression from expression
如果不带表达式,raise 会重新引发当前作用域内最后一个激活的异常。如果当前作用域内没有激活的异常,将会引发 RuntimeError 来提示错误。
raise
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-1-9c9a2cba73bf> in <module>
----> 1 raise
RuntimeError: No active exception to reraise
raise 会将第一个表达式求值为异常对象。它必须为 BaseException 的子类或实例。如果它是一个类,当需要时会通过不带参数地实例化该类来获得异常的实例。
type(ZeroDivisionError)
type
raise ZeroDivisionError # 无提示信息
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-2-798b08d1683c> in <module>
----> 1 raise ZeroDivisionError # 无提示信息
ZeroDivisionError:
raise ZeroDivisionError('分母不能为 0') # 自定义提示信息
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-17-950b4accf1f2> in <module>
----> 1 raise ZeroDivisionError('分母不能为 0') # 自定义提示信息
ZeroDivisionError: 分母不能为 0
from 子句用于异常串连:如果有该子句,则第二个表达式必须为另一个异常类或实例,它将被关联到所引发的异常:
raise IndexError("索引错误") from NameError('名称错误')
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
NameError: 名称错误
The above exception was the direct cause of the following exception:
IndexError Traceback (most recent call last)
<ipython-input-18-124f83b49e6f> in <module>
----> 1 raise IndexError("索引错误") from NameError('名称错误')
IndexError: 索引错误
try:
print(1 / 0)
except Exception as e:
raise RuntimeError("Something bad happened") from e
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-13-83aaca0b7e7f> in <module>
1 try:
----> 2 print(1 / 0)
3 except Exception as e:
ZeroDivisionError: division by zero
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
<ipython-input-13-83aaca0b7e7f> in <module>
2 print(1 / 0)
3 except Exception as e:
----> 4 raise RuntimeError("Something bad happened") from e
RuntimeError: Something bad happened
如果一个异常在异常处理器或 finally 中被引发,类似的机制会隐式地发挥作用:
try:
print(1 / 0)
except:
raise RuntimeError("Something bad happened")
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-16-5576c5c08e42> in <module>
1 try:
----> 2 print(1 / 0)
3 except:
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
RuntimeError Traceback (most recent call last)
<ipython-input-16-5576c5c08e42> in <module>
2 print(1 / 0)
3 except:
----> 4 raise RuntimeError("Something bad happened")
RuntimeError: Something bad happened
try:
print(1 / 0)
finally:
raise RuntimeError("Something bad happened")
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-15-8b172672db5a> in <module>
1 try:
----> 2 print(1 / 0)
3 finally:
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
RuntimeError Traceback (most recent call last)
<ipython-input-15-8b172672db5a> in <module>
2 print(1 / 0)
3 finally:
----> 4 raise RuntimeError("Something bad happened")
RuntimeError: Something bad happened
with 语句用于包装代码块的执行,代码块带有使用上下文管理器定义的函数或方法。语法如下:
with expression as target, expression as target, ...:
suite
带有一个表达式 expression 的 with 语句的执行过程如下:
__enter__()
以便后续使用。__exit__()
以便后续使用。__enter__()
方法。__enter__()
的返回值将被赋值给它。__exit__()
方法。with 语句会保证如果 __enter__()
方法返回时未发生错误,则 __exit__()
将总是被调用。因此,如果在对目标赋值期间发生错误,则会将其视为在语句体内部发生的错误。
如果语句体的退出是由异常导致的,则其类型、值和回溯信息将被作为参数传递给 __exit__()
。否则的话,将提供三个 None 参数(相当于无异常地退出)。
如果语句体的退出是由异常导致的,并且来自 __exit__()
方法的返回值为真,则该异常会被抑制,并会继续执行 with 语句之后的语句。如果返回值为假,则该异常会被重新引发(__exit__()
方法不应该重新引发被传入的异常,这是调用者的责任)。
如果语句体由于异常以外的任何原因退出,则来自 __exit__()
的返回值会被忽略,并会在该类退出正常的发生位置继续执行。
以下代码:
with EXPRESSION as TARGET:
SUITE
在语义上等价于:
manager = (EXPRESSION)
enter = type(manager).__enter__
exit = type(manager).__exit__
value = enter(manager)
hit_except = False # False 表示正常执行
try:
TARGET = value
SUITE
except:
hit_except = True # 发生了异常
# 忽略或抑制异常,继续退出;或退出并引发异常
if not exit(manager, *sys.exc_info()):
raise
finally:
if not hit_except: # 正常执行
# 正常退出
exit(manager, None, None, None)
可见使用 with 语句,无论有没有发生异常,都会 “清理” 程序(保存和恢复各种全局状态,锁定和解锁资源,关闭打开的文件等等)。
有多个表达式,则会视作存在多个 with 语句嵌套来处理多个上下文管理器:
with A() as a, B() as b:
SUITE
# 在语义上等价于:
with A() as a:
with B() as b:
SUITE
with 语句常用来打开文件而不需要显式地关闭文件:
with open('../11_built-in_function/test.txt',
'r', encoding='utf-8') as f:
print(f.read())
xue.cn
自学是门手艺
# 相当于
f = open('../11_built-in_function/test.txt',
'r', encoding='utf-8')
print(f.read())
f.close()
xue.cn
自学是门手艺
assert 语句是在程序中插入调试性断言的简便方式。在表达式条件为 False 的时候触发异常。
简单形式为:assert expression
。
assert 1 + 1 == 2
assert 1 + 1 != 2
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-2-5cd89e6dd50b> in <module>
----> 1 assert 1 + 1 != 2
AssertionError:
扩展形式为:assert expression1, expression2
。expression2 通常是提示信息。
assert 1 + 1 != 2, '计算错误'
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-7-3b85a53ff241> in <module>
----> 1 assert 1 + 1 != 2, '计算错误'
AssertionError: 计算错误
for i in range(5):
try:
assert i % 2 == 0, f'{i}是奇数'
print(i)
except AssertionError as a:
print(a)
0
1是奇数
2
3是奇数
4
import 语句用于从模块中导入子模块,类,函数等。语法大致有三种:
# 第一种
import module as name, module as name, ...
# 第二种
# import 之后可以置于一个元组
from module import identifier as name, identifier as name, ...
# 第三种
from module import *
模块 module
可以是高层级到低层级用属性表示法引用的模块,例如 pandas.core.series
。
as
及其后的别名 name
是可选的。
语句可以导入单个或多个对象,用逗号分隔实际是多个子句。
第一种导入方法,如果成功获取到模块,则可以通过以下方式之一在 import 语句所在命名空间中使用它:
如果没有指定模块,引发 ModuleNotFoundError。
import pandas
pandas
<module 'pandas' from 'F:\\anaconda\\lib\\site-packages\\pandas\\__init__.py'>
del pandas
import pandas.core.series
pandas, pandas.core, pandas.core.series
(<module 'pandas' from 'F:\\anaconda\\lib\\site-packages\\pandas\\__init__.py'>,
<module 'pandas.core' from 'F:\\anaconda\\lib\\site-packages\\pandas\\core\\__init__.py'>,
<module 'pandas.core.series' from 'F:\\anaconda\\lib\\site-packages\\pandas\\core\\series.py'>)
series # 必须完成限定名访问
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-6-2859777d6f2b> in <module>
----> 1 series
NameError: name 'series' is not defined
del pandas
import pandas.core.series as pds
pds
<module 'pandas.core.series' from 'F:\\anaconda\\lib\\site-packages\\pandas\\core\\series.py'>
pandas # 只能使用别名访问
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-8-609b6d5922fb> in <module>
----> 1 pandas
NameError: name 'pandas' is not defined
def f():
import pandas # 局部命名空间导入
pandas # 全局命名空间不能访问
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-10-0b76d1984901> in <module>
1 def f():
2 import pandas # 局部命名空间导入
----> 3 pandas
NameError: name 'pandas' is not defined
第二种导入方法,如果成功获取到模块,from 之后的模块名不会被绑定,对于 import 子句导入的属性或子模块,如果有 as 子句,则只能使用其指定的别名使用它,否则使用该属性或子模块的名称 identifier 使用它。
如果属性或子模块不存在,或不能导入,引发 ImportError。
from pandas.core import base
base
<module 'pandas.core.base' from 'F:\\anaconda\\lib\\site-packages\\pandas\\core\\base.py'>
pandas.core # 只导入了该模块下的子模块 base
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-2-37462de79a89> in <module>
----> 1 pandas.core
NameError: name 'pandas' is not defined
# 导入多个可置于元组中
from random import (random as r1,
randint as r2,)
r1, r2
(<function Random.random()>,
<bound method Random.randint of <random.Random object at 0x000001E531A14580>>)
# pandas 下没有 base,导入错误
from pandas import base
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
<ipython-input-7-7903c4949085> in <module>
----> 1 from pandas import base
ImportError: cannot import name 'base' from 'pandas' (F:\anaconda\lib\site-packages\pandas\__init__.py)
第三种导入方法,则在模块中定义的全部公有名称都将绑定到 import 语句所在的命名空间。
公有名称是由在模块的命名空间中检测一个名为 __all__
的变量来确定的;如果 __all__
没有被定义,则公有名称的集合将包含模块的命名空间中找到的所有不以下划线字符 _
打头的名称。
from random import *
randint
<bound method Random.randint of <random.Random object at 0x0000025E1DCC8180>>
当指定要导入哪个模块时,你不必指定模块的绝对名称。当一个模块或包被包含在另一个包之中时,可以在同一个最高层级包中进行相对导入,而不必提及包名称。
通过在 from 之后指定的模块或包中使用前缀点号,你可以在不指定确切名称的情况下指明在当前包层级结构中要上溯多少级。一个前缀点号表示是执行导入的模块所在的当前包,两个点号表示上溯一个包层级。三个点号表示上溯两级,依此类推。例如:
package/
__init__.py
subpackage1/
__init__.py
moduleX.py
moduleY.py
subpackage2/
__init__.py
moduleZ.py
moduleA.py
假设当前位置是 subpackage1/moduleX.py
,则:
from .moduleY import spam
from . import moduleY
from ..subpackage1 import moduleY
from ..subpackage2.moduleZ import eggs
from ..moduleA import foo
都是有效的。
global 语句作用于整个当前代码块,它后面所列出的标识符将被解读为全局变量。
在 global 语句中列出的名称不得在同一代码块内该 global 语句之前的位置中使用。
当前的实现虽然并未强制要求,但在 global 语句中列出的名称不得被定义为正式形参,不也得出现于 for 循环的控制目标、class 定义、函数定义、import 语句 或 变量标注之中。
举例如下:
def f():
a = 0
f() # 调用函数,对 a 赋值
a # a 是局部变量,不可访问
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-5-251a24e05273> in <module>
3
4 f() # 调用函数,对 a 赋值
----> 5 a # a 是局部变量,不可访问
NameError: name 'a' is not defined
def f():
global a # 将 a 声明为全局变量
a = 0
f() # 调用函数,对 a 赋值
print(a) # a 已经是全局变量
del a
0
def f():
a = 1 # 同一代码块中,不可在 global 前使用
global a # 将 a 声明为全局变量
a = 0
File "<ipython-input-9-51bc7826eb42>", line 3
global a # 将 a 声明为全局变量
^
SyntaxError: name 'a' is assigned to before global declaration
a = 1 # 与 global 不在一个代码块
def f():
global a, b # 将 a, b 声明为全局变量
a = 0 # a 被重新赋值
b = 1
f() # 调用函数,对 b 赋值,对 a 重新赋值
print(a,b)
del a,b
0 1
nonlocal 语句会使得所列出的名称指向在它之前已经存在的,和它最近并且在包含它的作用域中绑定,除全局变量以外的变量。
这种功能很重要,因为绑定的默认行为是先搜索局部命名空间。这个语句允许被封装的代码重新绑定局部作用域以外且非全局(模块)作用域当中的变量。
举例如下:
a = '全局'
def f():
a = 'f' # f 中已经存在的 a, 包含 f2
def f1():
a = 'f1' # f1 中的局部变量
def f2():
nonlocal a # 和他最近且包含的是 'f'
a = 'f2'
def f3():
global a
a = 'f3'
# 调用 f1 不改变 a = 'f'
f1()
print(a)
# 调用 f2, nonlocal 将 a = 'f' 重新绑定为 a = 'f2'
f2()
print(a)
# 调用 f3, global 将 a 声明为全局变量,
# 并将 a = '全局' 重新绑定为 a = 'f3'
# 但在 f 这个局部中,a 仍然是 'f2'
f3()
print(a)
f() # 调用 f 使绑定都生效
print(a)
f
f2
f2
f3
# 不存在不可以绑定
def f():
nonlocal a
a = 1
f()
File "<ipython-input-3-3706e217f701>", line 2
nonlocal a
^
SyntaxError: no binding for nonlocal 'a' found
# 不是包含它的作用域,不可以绑定
def f():
def f1():
a = 0
f1()
nonlocal a
a = 1
f()
File "<ipython-input-4-a036260d029b>", line 5
nonlocal a
^
SyntaxError: no binding for nonlocal 'a' found
# 全局变量,不可以绑定
a = 0
def f():
nonlocal a
a = 1
f()
File "<ipython-input-5-87297c0b0eeb>", line 4
nonlocal a
^
SyntaxError: no binding for nonlocal 'a' found
内置函数 abs(),Python 官方文档描述如下:
help(abs)
Help on built-in function abs in module builtins:
abs(x, /)
Return the absolute value of the argument.
返回一个数的绝对值,参数可以是整数、浮点数或任何实现了 __abs__()
的对象。如果参数是一
个复数,则返回它的模。
abs(-1)
1
abs(-3.14)
3.14
abs(3+4j)
5.0
内置函数 all(),Python 官方文档描述如下:
help(all)
Help on built-in function all in module builtins:
all(iterable, /)
Return True if bool(x) is True for all values x in the iterable.
If the iterable is empty, return True.
如果可迭代对象(iterable)的所有元素均为真值(或可迭代对象为空)则返回 True 。
all('0123') # 字符串 '0' 是真值
True
all([0,1,2,3])
False
all({})
True
all({1:[], 2:0 })
True
内置函数 any(),Python 官方文档描述如下:
help(any)
Help on built-in function any in module builtins:
any(iterable, /)
Return True if bool(x) is True for any x in the iterable.
If the iterable is empty, return False.
如果可迭代对象(iterable)的任一元素为真值则返回 True。如果可迭代对象为空,返回 False。
any([0,1])
True
any((None, [], range(1,1)))
False
内置函数 ascii(),Python 官方文档描述如下:
help(ascii)
Help on built-in function ascii in module builtins:
ascii(obj, /)
Return an ASCII-only representation of an object.
As repr(), return a string containing a printable representation of an
object, but escape the non-ASCII characters in the string returned by
repr() using \\x, \\u or \\U escapes. This generates a string similar
to that returned by repr() in Python 2.
就像函数 repr(),返回一个对象可打印的字符串,但是非 ASCII 编码的字符,会使用 \x、\u 和 \U 来转义。
ascii(123)
'123'
ascii(None)
'None'
ascii('python')
"'python'"
ascii('嗨')
"'\\u55e8'"
repr('嗨')
"'嗨'"
'\u55e8' # 16 位十六进制数 55e8 码位的字符
'嗨'
内置函数 bin(),Python 官方文档描述如下:
help(bin)
Help on built-in function bin in module builtins:
bin(number, /)
Return the binary representation of an integer.
>>> bin(2796202)
'0b1010101010101010101010'
返回给定整数的二进制表示形式的字符串。
bin(123)
'0b1111011'
0b1111011
123
内置函数(类) bool,Python 官方文档描述如下:
help(bool)
Help on class bool in module builtins:
class bool(int)
| bool(x) -> bool
|
| Returns True when the argument x is true, False otherwise.
| The builtins True and False are the only two instances of the class bool.
| The class bool is a subclass of the class int, and cannot be subclassed.
|
| Method resolution order:
| bool
| int
| object
|
返回对象 x 的布尔值。省略 x 则返回 False。对象的真值、假值规则如下:
一个对象在默认情况下均被视为真值,除非当该对象被调用时其所属类定义了 __bool__()
方法且返回 False 或是定义了 __len__()
方法且返回零。
下面基本完整地列出了会被视为假值的内置对象:
type(bool)
type
bool()
False
bool(None)
False
bool('0')
True
bool(' ')
True
内置函数(类)bytes,Python 官方文档描述如下:
help(bytes)
Help on class bytes in module builtins:
class bytes(object)
| bytes(iterable_of_ints) -> bytes
| bytes(string, encoding[, errors]) -> bytes
| bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer
| bytes(int) -> bytes object of size given by the parameter initialized with null bytes
| bytes() -> empty bytes object
|
| Construct an immutable array of bytes from:
| - an iterable yielding integers in range(256)
| - a text string encoded using the specified encoding
| - any object implementing the buffer API.
| - an integer
|
| Methods defined here:
|
返回一个新的二进制序列 bytes 对象。参数可以是:
type(bytes)
type
bytes([1,2,3])
b'\x01\x02\x03'
bytes('嗨', 'utf-8')
b'\xe5\x97\xa8'
bytes(3)
b'\x00\x00\x00'
bytes()
b''
内置函数 callable(),Python 官方文档描述如下:
help(callable)
Help on built-in function callable in module builtins:
callable(obj, /)
Return whether the object is callable (i.e., some kind of function).
Note that classes are callable, as are instances of classes with a
__call__() method.
如果 obj 是可调用对象就返回 True,否则返回 False。如果返回 True,调用仍可能失败,但如果返回 False,则调用将肯定不会成功。
函数、方法、类以及实现了 __call__()
方法的类的实例是可调用的。
callable(1)
False
callable(int)
True
class Myint(int):
def __call__(self):
pass
num = Myint(1)
num
1
callable(num)
True
callable(lambda: 1)
True
内置函数 chr(),Python 官方文档描述如下:
help(chr)
Help on built-in function chr in module builtins:
chr(i, /)
Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff.
返回 Unicode 码位对应的字符的字符串格式。码位范围是 0~1114111(16 进制表示是 0x10FFFF),超过这个范围,会触发 ValueError 异常。该函数是 ord() 的逆函数。
chr(97)
'a'
ord('a')
97
chr(1114111)
'\U0010ffff'
chr(1114112)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-5-4857faf08086> in <module>
----> 1 chr(1114112)
ValueError: chr() arg not in range(0x110000)
内置函数(类)classmethod,Python 官方文档描述如下:
help(classmethod)
Help on class classmethod in module builtins:
class classmethod(object)
| classmethod(function) -> method
|
| Convert a function to be a class method.
|
| A class method receives the class as implicit first argument,
| just like an instance method receives the instance.
| To declare a class method, use this idiom:
|
| class C:
| @classmethod
| def f(cls, arg1, arg2, ...):
| ...
|
把一个函数封装成类方法。一个类方法把类自己作为第一个实参,就像一个实例方法把实例自己作为第一个实参。
可将函数作为参数来声明类方法,但请用习惯的装饰器形式(@classmethod)来声明类方法。
type(classmethod)
type
class A:
print_itself = classmethod(print)
A.print_itself()
<class '__main__.A'>
class A:
@classmethod
def print_itself(cls):
print(cls)
A.print_itself()
<class '__main__.A'>
内置函数 compile(),Python 官方文档描述如下:
help(compile)
Help on built-in function compile in module builtins:
compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
Compile source into a code object that can be executed by exec() or eval().
The source code may represent a Python module, statement or expression.
The filename will be used for run-time error messages.
The mode must be 'exec' to compile a module, 'single' to compile a
single (interactive) statement, or 'eval' to compile an expression.
The flags argument, if present, controls which future statements influence
the compilation of the code.
The dont_inherit argument, if true, stops the compilation inheriting
the effects of any future statements in effect in the code calling
compile; if absent or false these statements do influence the compilation,
in addition to any features explicitly specified.
将 source 编译成代码或 AST 对象。代码对象可以被 exec() 或 eval() 执行。
参数说明:
source = 'for i in range(3):print(i)'
code = compile(source,'null','exec')
code
<code object <module> at 0x000001E999B07780, file "null", line 1>
exec(code)
0
1
2
eval(code)
0
1
2
内置函数(类)complex,Python 官方文档描述如下:
help(complex)
Help on class complex in module builtins:
class complex(object)
| complex(real=0, imag=0)
|
| Create a complex number from a real part and an optional imaginary part.
|
| This is equivalent to (real + imag*1j) where imag defaults to 0.
|
| Methods defined here:
|
| __abs__(self, /)
| abs(self)
|
| __add__(self, value, /)
| Return self+value.
|
| __bool__(self, /)
| self != 0
|
| __divmod__(self, value, /)
| Return divmod(self, value).
|
| __eq__(self, value, /)
| Return self==value.
|
| __float__(self, /)
| float(self)
|
| __floordiv__(self, value, /)
| Return self//value.
|
| __format__(...)
| complex.__format__() -> str
|
| Convert to a string according to format_spec.
|
| __ge__(self, value, /)
| Return self>=value.
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __getnewargs__(...)
|
| __gt__(self, value, /)
| Return self>value.
|
| __hash__(self, /)
| Return hash(self).
|
| __int__(self, /)
| int(self)
|
| __le__(self, value, /)
| Return self<=value.
|
| __lt__(self, value, /)
| Return self<value.
|
| __mod__(self, value, /)
| Return self%value.
|
| __mul__(self, value, /)
| Return self*value.
|
| __ne__(self, value, /)
| Return self!=value.
|
| __neg__(self, /)
| -self
|
| __pos__(self, /)
| +self
|
| __pow__(self, value, mod=None, /)
| Return pow(self, value, mod).
|
| __radd__(self, value, /)
| Return value+self.
|
| __rdivmod__(self, value, /)
| Return divmod(value, self).
|
| __repr__(self, /)
| Return repr(self).
|
| __rfloordiv__(self, value, /)
| Return value//self.
|
| __rmod__(self, value, /)
| Return value%self.
|
| __rmul__(self, value, /)
| Return value*self.
|
| __rpow__(self, value, mod=None, /)
| Return pow(value, self, mod).
|
| __rsub__(self, value, /)
| Return value-self.
|
| __rtruediv__(self, value, /)
| Return value/self.
|
| __sub__(self, value, /)
| Return self-value.
|
| __truediv__(self, value, /)
| Return self/value.
|
| conjugate(...)
| complex.conjugate() -> complex
|
| Return the complex conjugate of its argument. (3-4j).conjugate() == 3+4j.
|
| ----------------------------------------------------------------------
| Static methods defined here:
|
| __new__(*args, **kwargs) from builtins.type
| Create and return a new object. See help(type) for accurate signature.
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| imag
| the imaginary part of a complex number
|
| real
| the real part of a complex number
返回值为 real + imag*1j 的复数,或将字符串或数字转换为复数。
type(complex)
type
complex('1')
(1+0j)
complex('1+2j')
(1+2j)
complex(1j, 2j)
(-2+1j)
complex(1j)
1j
complex()
0j
complex('1 + 2j')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-7-fd0fa4b53d7c> in <module>
----> 1 complex('1 + 2j')
ValueError: complex() arg is a malformed string
内置函数 delattr(),Python 官方文档描述如下:
help(delattr)
Help on built-in function delattr in module builtins:
delattr(obj, name, /)
Deletes the named attribute from the given object.
delattr(x, 'y') is equivalent to ``del x.y''
实参是一个对象和一个字符串。该字符串必须是对象的某个属性。如果对象允许,该函数将删除指定的属性。delattr(x, 'y')
等价于 del x.y
。
class A:
y = 0
x = A
x.y
0
delattr(x,'y')
x.y
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-12-3552434a3e61> in <module>
----> 1 x.y
AttributeError: type object 'A' has no attribute 'y'
内置函数(类)dict,Python 官方文档描述如下:
help(dict)
Help on class dict in module builtins:
class dict(object)
| dict() -> new empty dictionary
| dict(mapping) -> new dictionary initialized from a mapping object's
| (key, value) pairs
| dict(iterable) -> new dictionary initialized as if via:
| d = {}
| for k, v in iterable:
| d[k] = v
| dict(**kwargs) -> new dictionary initialized with the name=value pairs
| in the keyword argument list. For example: dict(one=1, two=2)
|
创建一个新字典。参数说明:
type(dict)
type
dict()
{}
dict({'a':1})
{'a': 1}
d = zip('abc',[1,2,3])
dict(d)
{'a': 1, 'b': 2, 'c': 3}
dict([('a', 1), ('b', 2)])
{'a': 1, 'b': 2}
dict(a=1,b=2)
{'a': 1, 'b': 2}
内置函数 dir(),Python 官方文档描述如下:
help(dir)
Help on built-in function dir in module builtins:
dir(...)
dir([object]) -> list of strings
If called without an argument, return the names in the current scope.
Else, return an alphabetized list of names comprising (some of) the attributes
of the given object, and of attributes reachable from it.
If the object supplies a method named __dir__, it will be used; otherwise
the default dir() logic is used and returns:
for a module object: the module's attributes.
for a class object: its attributes, and recursively the attributes
of its bases.
for any other object: its attributes, its class's attributes, and
recursively the attributes of its class's base classes.
如果没有实参,则返回当前作用域中的名称列表。如果有实参,它会尝试返回该对象的有效属性列表。
dir()
['In',
'Out',
'_',
'__',
'___',
'__builtin__',
'__builtins__',
'__doc__',
'__loader__',
'__name__',
'__package__',
'__spec__',
'_dh',
'_i',
'_i1',
'_i2',
'_ih',
'_ii',
'_iii',
'_oh',
'exit',
'get_ipython',
'quit']
如果对象有一个名为 __dir__()
的方法,那么该方法将被调用,并且必须返回一个属性列表。这允许实现自定义 dir() 来报告它的属性。
class A:
def __dir__(self):
return ['area', 'perimeter', 'location']
a = A()
dir(a)
['area', 'location', 'perimeter']
如果对象不提供 __dir__()
,默认的 dir() 机制对不同类型的对象行为不同,它会试图返回最相关而不是最全的信息:
import string
dir(string)
['Formatter',
'Template',
'_ChainMap',
'_TemplateMetaclass',
'__all__',
'__builtins__',
'__cached__',
'__doc__',
'__file__',
'__loader__',
'__name__',
'__package__',
'__spec__',
'_re',
'_string',
'ascii_letters',
'ascii_lowercase',
'ascii_uppercase',
'capwords',
'digits',
'hexdigits',
'octdigits',
'printable',
'punctuation',
'whitespace']
dir(int)
['__abs__',
'__add__',
'__and__',
'__bool__',
'__ceil__',
'__class__',
'__delattr__',
'__dir__',
'__divmod__',
'__doc__',
'__eq__',
'__float__',
'__floor__',
'__floordiv__',
'__format__',
'__ge__',
'__getattribute__',
'__getnewargs__',
'__gt__',
'__hash__',
'__index__',
'__init__',
'__init_subclass__',
'__int__',
'__invert__',
'__le__',
'__lshift__',
'__lt__',
'__mod__',
'__mul__',
'__ne__',
'__neg__',
'__new__',
'__or__',
'__pos__',
'__pow__',
'__radd__',
'__rand__',
'__rdivmod__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__rfloordiv__',
'__rlshift__',
'__rmod__',
'__rmul__',
'__ror__',
'__round__',
'__rpow__',
'__rrshift__',
'__rshift__',
'__rsub__',
'__rtruediv__',
'__rxor__',
'__setattr__',
'__sizeof__',
'__str__',
'__sub__',
'__subclasshook__',
'__truediv__',
'__trunc__',
'__xor__',
'bit_length',
'conjugate',
'denominator',
'from_bytes',
'imag',
'numerator',
'real',
'to_bytes']
dir(1)
['__abs__',
'__add__',
'__and__',
'__bool__',
'__ceil__',
'__class__',
'__delattr__',
'__dir__',
'__divmod__',
'__doc__',
'__eq__',
'__float__',
'__floor__',
'__floordiv__',
'__format__',
'__ge__',
'__getattribute__',
'__getnewargs__',
'__gt__',
'__hash__',
'__index__',
'__init__',
'__init_subclass__',
'__int__',
'__invert__',
'__le__',
'__lshift__',
'__lt__',
'__mod__',
'__mul__',
'__ne__',
'__neg__',
'__new__',
'__or__',
'__pos__',
'__pow__',
'__radd__',
'__rand__',
'__rdivmod__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__rfloordiv__',
'__rlshift__',
'__rmod__',
'__rmul__',
'__ror__',
'__round__',
'__rpow__',
'__rrshift__',
'__rshift__',
'__rsub__',
'__rtruediv__',
'__rxor__',
'__setattr__',
'__sizeof__',
'__str__',
'__sub__',
'__subclasshook__',
'__truediv__',
'__trunc__',
'__xor__',
'bit_length',
'conjugate',
'denominator',
'from_bytes',
'imag',
'numerator',
'real',
'to_bytes']
内置函数 divmod(),Python 官方文档描述如下:
help(divmod)
Help on built-in function divmod in module builtins:
divmod(x, y, /)
Return the tuple (x//y, x%y). Invariant: div*y + mod == x.
它将两个(非复数)数字作为实参,返回两个数字的(商,余数)元组。对于混合操作数类型,适用二元算术运算符的规则。
divmod(1,2)
(0, 1)
divmod(3.14, 2)
(1.0, 1.1400000000000001)
内置函数(类)enumerate,Python 官方文档描述如下:
help(enumerate)
Help on class enumerate in module builtins:
class enumerate(object)
| enumerate(iterable, start=0)
|
| Return an enumerate object.
|
| iterable
| an object supporting iteration
|
| The enumerate object yields pairs containing a count (from start, which
| defaults to zero) and a value yielded by the iterable argument.
|
| enumerate is useful for obtaining an indexed list:
| (0, seq[0]), (1, seq[1]), (2, seq[2]), ...
|
返回一个可迭代对象(iterable)的枚举对象。枚举对象是一个迭代器,迭代出来是一个个元组,里面包含一个计数值(从 start 开始,默认为 0)和通过迭代 iterable 获得的值。
type(enumerate)
type
e = enumerate({'a':1,'b':2,'c':3})
e
<enumerate at 0x200ccb71240>
next(e)
(0, 'a')
for i in e:
print(i)
(1, 'b')
(2, 'c')
e = enumerate('abc', 1)
list(e)
[(1, 'a'), (2, 'b'), (3, 'c')]
内置函数 eval(),Python 官方文档描述如下:
help(eval)
Help on built-in function eval in module builtins:
eval(source, globals=None, locals=None, /)
Evaluate the given source in the context of globals and locals.
The source may be a string representing a Python expression
or a code object as returned by compile().
The globals must be a dictionary and locals can be any mapping,
defaulting to the current globals and locals.
If only globals is given, locals defaults to it.
source 参数接受字符串(会作为一个 Python 表达式)或代码对象(可通过 compile() 创建),然后解析并求值,返回求值结果。
eval('{1 + 1}')
{2}
s = 'for i in range(3):print(i)'
code = compile(s,'','exec')
eval(code)
0
1
2
eval("__import__('math').sqrt(3**2+4**2)")
5.0
参数 globals 和 locals 作为 source 的全局和局部命名空间。如果省略 locals 字典则其默认值为 globals 字典。如果两个字典同时省略,则表达式执行时会使用 eval() 被调用的环境中的全局和局部名称。
如果 globals 字典存在且不包含以 __builtins__
为键的值,则会在解析 source 之前插入以此为键的对内置模块 builtins 的引用。这意味着 source 通常具有对标准 builtins 模块的完全访问权限且受限的环境会被传播。
globals 实参必须是一个字典。locals 可以是任何映射对象。
x = 3
def f():
y = 4
code = "__import__('math').sqrt(x**2+y**2)"
z = eval(code,{'x':5},{'y':12})
print(f'x={x}, y={y}, z={z}')
f()
x=3, y=4, z=13.0
x = 3
def f():
y = 4
code = "__import__('math').sqrt(x**2+y**2)"
z = eval(code,{'x':5,'y':12})
print(f'x={x}, y={y}, z={z}')
f()
x=3, y=4, z=13.0
x = 3
def f():
y = 4
code = "__import__('math').sqrt(x**2+y**2)"
z = eval(code)
print(f'x={x}, y={y}, z={z}')
f()
x=3, y=4, z=5.0
内置函数 exec(),Python 官方文档描述如下:
help(exec)
Help on built-in function exec in module builtins:
exec(source, globals=None, locals=None, /)
Execute the given source in the context of globals and locals.
The source may be a string representing one or more Python statements
or a code object as returned by compile().
The globals must be a dictionary and locals can be any mapping,
defaulting to the current globals and locals.
If only globals is given, locals defaults to it.
这个函数支持动态执行 Python 代码。source 必须是字符串或者代码对象。
如果是字符串,那么该字符串将被解析为一系列 Python 语句并执行(除非发生语法错误)。
如果是代码对象,它将被直接执行。
该函数返回值为 None。
print(exec('{1 + 1}'))
None
s = 'for i in range(3):print(i)'
code = compile(s,'','exec')
exec(code)
0
1
2
参数 globals 和 locals 作为 source 的全局和局部命名空间。如果省略 locals 字典则其默认值为 globals 字典。如果两个字典同时省略,则表达式执行时会使用 eval() 被调用的环境中的全局和局部名称。
如果 globals 字典存在且不包含以 __builtins__
为键的值,则将为该键插入对内建 builtins 模块字典的引用。因此,在将执行的代码传递给 exec() 之前,可以通过将自己的 __builtins__
字典插入到 globals 中来控制可以使用哪些内置代码。
globals 实参必须是一个字典。locals 可以是任何映射对象。
x = 1
def f():
x = 2
code = "for i in range(x):print(i)"
exec(code,{'x':3},{'x':4})
f()
0
1
2
3
x = 1
def f():
x = 2
code = "for i in range(x):print(i)"
exec(code,{'x':3})
f()
0
1
2
x = 1
def f():
x = 2
code = "for i in range(x):print(i)"
exec(code)
f()
0
1
内置函数(类)filter,Python 官方文档描述如下:
help(filter)
Help on class filter in module builtins:
class filter(object)
| filter(function or None, iterable) --> filter object
|
| Return an iterator yielding those items of iterable for which function(item)
| is true. If function is None, return the items that are true.
|
返回可迭代对象(iterable)中那些传递给函数 function 计算之后,布尔值仍然为真的元素组成的迭代器。
如果 function 是 None,则会假设它是一个身份函数,即 iterable 中所有布尔值为假的元素会被移除。
type(filter)
type
f = filter(None,[0,1,2,1])
list(f)
[1, 2, 1]
f = filter(lambda x: x-1, [0,1,2,1])
list(f)
[0, 2]
list(filter(None,'0120'))
['0', '1', '2', '0']
list(filter(int,'0120'))
['1', '2']
内置函数(类)float,Python 官方文档描述如下:
help(float)
Help on class float in module builtins:
class float(object)
| float(x=0, /)
|
| Convert a string or number to a floating point number, if possible.
|
返回从数字或字符串 x 生成的浮点数。
如果实参是字符串:
如果实参是整数或浮点数,则返回具有相同值(在 Python 浮点精度范围内)的浮点数。如果实参在 Python 浮点精度范围外,则会触发OverflowError。
如果没有实参,则返回 0.0 。
type(float)
type
float()
0.0
float(1)
1.0
float(- 1.0)
-1.0
float(' -1.0 \n')
-1.0
float(' 01_2.1_4 ')
12.14
float('0001')
1.0
float('3.14e02')
314.0
float('-naN')
nan
float('-inf')
-inf
内置函数 format(),Python 官方文档描述如下:
help(format)
Help on built-in function format in module builtins:
format(value, format_spec='', /)
Return value.__format__(format_spec)
format_spec defaults to the empty string.
See the Format Specification Mini-Language section of help('FORMATTING') for
details.
将 value 转换为 format_spec 控制的 “格式化” 表示。format_spec 的解释取决于 value 实参的类型,但是大多数内置类型使用标准格式化语法:格式化迷你语言。详见 str.format 格式化。
默认的 format_spec 是一个空字符串,它通常和调用 str(value) 的结果相同。
format('嗨','>10')
' 嗨'
format('嗨','~^10')
'~~~~嗨~~~~~'
format(1,'05')
'00001'
format(3.14,'.3f')
'3.140'
format(123456789,'_')
'123_456_789'
format(123456789,'.2e')
'1.23e+08'
format(123456789)
'123456789'
内置函数(类)frozenset,Python 官方文档描述如下:
help(frozenset)
Help on class frozenset in module builtins:
class frozenset(object)
| frozenset() -> empty frozenset object
| frozenset(iterable) -> frozenset object
|
| Build an immutable unordered collection of unique elements.
|
将可迭代对象转换为集合,返回一个新的 frozenset 集合对象。可迭代对象为空,或不传参数,得到一个空集合。
type(frozenset)
type
frozenset()
frozenset()
frozenset([])
frozenset()
frozenset('0123')
frozenset({'0', '1', '2', '3'})
frozenset({'a':1,'b':2})
frozenset({'a', 'b'})
内置函数 getattr(),Python 官方文档描述如下:
help(getattr)
Help on built-in function getattr in module builtins:
getattr(...)
getattr(object, name[, default]) -> value
Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.
返回对象给定的属性名指向的值。name 必须是字符串。如果该字符串是对象的属性名称之一,则返回该属性的值。例如,getattr(x, 'y')
等同于 x.y
。如果指定的属性不存在,且提供了 default 值,则返回它,否则触发 AttributeError。
getattr(1,'imag')
0
getattr(1,'bool',True)
True
getattr(1,'bool')
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-6-524bb2b35e58> in <module>
----> 1 getattr(1,'bool')
AttributeError: 'int' object has no attribute 'bool'
class A:
y = 1
x = A()
x.y
1
getattr(x,'y')
1
内置函数 globals(),Python 官方文档描述如下:
help(globals)
Help on built-in function globals in module builtins:
globals()
Return the dictionary containing the current scope's global variables.
NOTE: Updates to this dictionary *will* affect name lookups in the current
global scope and vice-versa.
返回包含当前作用域的全局变量字典。这总是当前模块的字典(在函数或方法中,不是调用它的模块,而是定义它的模块)。
更新此字典 将 影响当前全局范围内的名称查找,反之亦然。
globals() 和 locals() 函数各自返回当前的全局和本地字典,因此可以将它们传递给 eval() 或 exec() 来使用。
globals()
{'__name__': '__main__',
'__doc__': 'Automatically created module for IPython interactive environment',
'__package__': None,
'__loader__': None,
'__spec__': None,
'__builtin__': <module 'builtins' (built-in)>,
'__builtins__': <module 'builtins' (built-in)>,
'_ih': ['', 'help(globals)', 'globals()'],
'_oh': {},
'_dh': ['D:\\Jupyter\\xuecn_books\\books\\xue_python_kp\\11_built-in_function'],
'In': ['', 'help(globals)', 'globals()'],
'Out': {},
'get_ipython': <bound method InteractiveShell.get_ipython of <ipykernel.zmqshell.ZMQInteractiveShell object at 0x000001E15E70D748>>,
'exit': <IPython.core.autocall.ZMQExitAutocall at 0x1e160f63978>,
'quit': <IPython.core.autocall.ZMQExitAutocall at 0x1e160f63978>,
'_': '',
'__': '',
'___': '',
'_i': 'help(globals)',
'_ii': '',
'_iii': '',
'_i1': 'help(globals)',
'_i2': 'globals()'}
内置函数 hasattr(),Python 官方文档描述如下:
help(hasattr)
Help on built-in function hasattr in module builtins:
hasattr(obj, name, /)
Return whether the object has an attribute with the given name.
This is done by calling getattr(obj, name) and catching AttributeError.
该函数实参是一个对象和一个字符串。如果字符串是对象的属性之一的名称,则返回 True,否则返回 False。
hasattr('abc', 'join')
True
class A:
y = 1
hasattr(A, 'y')
True
内置函数 hash(),Python 官方文档描述如下:
help(hash)
Help on built-in function hash in module builtins:
hash(obj, /)
Return the hash value for the given object.
Two objects that compare equal must also have the same hash value, but the
reverse is not necessarily true.
返回对象的哈希值(如果它有的话)。哈希值是整数。它们在集合或字典查找元素时用来快速比较集合的元素或字典的键。相同大小的数字有相同的哈希值。
可哈希对象必须具有相同的哈希值比较结果才会相同。
hash(1) == hash(1.0) == hash(True)
True
1 == 1.0 == True
True
hash('abc')
2812132477407752679
hash((1,2,3))
529344067295497451
hash([1,2,3])
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-35e31e935e9e> in <module>
----> 1 hash([1,2,3])
TypeError: unhashable type: 'list'
hash((1,2))
内置函数(帮助系统)help,Python 官方文档描述如下:
help(help)
Help on _Helper in module _sitebuiltins object:
class _Helper(builtins.object)
| Define the builtin 'help'.
|
| This is a wrapper around pydoc.help that provides a helpful message
| when 'help' is typed at the Python interactive prompt.
|
| Calling help() at the Python prompt starts an interactive help session.
| Calling help(thing) prints help for the python object 'thing'.
|
| Methods defined here:
|
| __call__(self, *args, **kwds)
| Call self as a function.
|
| __repr__(self)
| Return repr(self).
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
启动内置的帮助系统(此函数主要在交互式中使用)。
如果没有实参,解释器控制台里会启动交互式帮助系统。
如果实参是一个字符串,则在模块、函数、类、方法、关键字或文档主题中搜索该字符串,并在控制台上打印帮助信息。
如果实参是其他任意对象,则会生成该对象的帮助页。
type(help)
_sitebuiltins._Helper
help()
Welcome to Python 3.8's help utility!
If this is your first time using Python, you should definitely check out
the tutorial on the Internet at https://docs.python.org/3.8/tutorial/.
Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules. To quit this help utility and
return to the interpreter, just type "quit".
To get a list of available modules, keywords, symbols, or topics, type
"modules", "keywords", "symbols", or "topics". Each module also comes
with a one-line summary of what it does; to list the modules whose name
or summary contain a given string such as "spam", type "modules spam".
help> print
Help on built-in function print in module builtins:
print(...)
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.
help> q
You are now leaving help and returning to the Python interpreter.
If you want to ask for help on a particular object directly from the
interpreter, you can type "help(object)". Executing "help('string')"
has the same effect as typing a particular string at the help> prompt.
help('list.append')
Help on method_descriptor in list:
list.append = append(self, object, /)
Append object to the end of the list.
help(list.append)
Help on method_descriptor:
append(self, object, /)
Append object to the end of the list.
内置函数 hex(),Python 官方文档描述如下:
help(hex)
Help on built-in function hex in module builtins:
hex(number, /)
Return the hexadecimal representation of an integer.
>>> hex(12648430)
'0xc0ffee'
将整数转换为以 0x
为前缀的小写十六进制整数的字符串形式。
hex(123)
'0x7b'
0x7b
123
内置函数 id(),Python 官方文档描述如下:
help(id)
Help on built-in function id in module builtins:
id(obj, /)
Return the identity of an object.
This is guaranteed to be unique among simultaneously existing objects.
(CPython uses the object's memory address.)
返回对象的唯一标识。该标识是一个整数,在此对象的生命周期中保证是唯一且恒定的。
CPython 中该标识是对象的内存地址。
id(1), id(1.0)
(140736642126656, 2785998726512)
1 == 1.0
True
# 两个变量引用了同一个值为 1 的对象
a = 1
b = int('01')
id(a), id(b)
(140736642126656, 140736642126656)
# 两个值为 1000 的不同对象
a = 1000
b = 1000
id(a), id(b)
(2785998745552, 2785998745360)
# 可变对象改变值,还是同一个对象
_list = [1,2,3]
print(id(_list),_list)
del _list[:]
print(id(_list),_list)
2785999307336 [1, 2, 3]
2785999307336 []
内置函数 input(),Python 官方文档描述如下:
help(input)
Help on method raw_input in module ipykernel.kernelbase:
raw_input(prompt='') method of ipykernel.ipkernel.IPythonKernel instance
Forward raw_input to frontends
Raises
------
StdinNotImplentedError if active frontend doesn't support stdin.
如果存在 prompt 实参,则作为提示信息输出。接下来,该函数将输入转换为字符串并返回。无输入则返回空字符串。
input('输入提示:')
输入提示: 1+1
'1+1'
input('输入提示:')
输入提示:
''
内置函数(类)int,Python 官方文档描述如下:
help(int)
Help on class int in module builtins:
class int(object)
| int([x]) -> integer
| int(x, base=10) -> integer
|
| Convert a number or string to an integer, or return 0 if no arguments
| are given. If x is a number, return x.__int__(). For floating point
| numbers, this truncates towards zero.
|
| If x is not a number or if base is given, then x must be a string,
| bytes, or bytearray instance representing an integer literal in the
| given base. The literal can be preceded by '+' or '-' and be surrounded
| by whitespace. The base defaults to 10. Valid bases are 0 and 2-36.
| Base 0 means to interpret the base from the string as an integer literal.
| >>> int('0b100', base=0)
| 4
|
| Built-in subclasses:
| bool
|
将一个数字,字符串或字节串转换为整数。参数说明:
type(int)
type
int()
0
int(3.18e01), int(10), int(0x10)
(31, 10, 16)
int(' -10 '), int(b' +10')
(-10, 10)
int('10',2), int('10',8), int('z',36)
(2, 8, 35)
int('001'), int('0b10',0)
(1, 2)
int('001',0) # 001 不是合法的整数
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-12-1cf9048a8c3e> in <module>
----> 1 int('001',0)
ValueError: invalid literal for int() with base 0: '001'
int('9', 8) # 8 进制没有 9
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-13-3558097bd025> in <module>
----> 1 int('9', 8)
ValueError: invalid literal for int() with base 8: '9'
int('3.14') # 不能是浮点数形式
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-14-1456603af047> in <module>
----> 1 int('3.14')
ValueError: invalid literal for int() with base 10: '3.14'
内置函数 isinstance(),Python 官方文档描述如下:
help(isinstance)
Help on built-in function isinstance in module builtins:
isinstance(obj, class_or_tuple, /)
Return whether an object is an instance of a class or of a subclass thereof.
A tuple, as in ``isinstance(x, (A, B, ...))``, may be given as the target to
check against. This is equivalent to ``isinstance(x, A) or isinstance(x, B)
or ...`` etc.
如果对象 obj 是给定类的实例或者是其 (直接、间接或虚拟) 子类的实例则返回 True,不是则返回 False。给定的不是类则引发 TypeError 异常。
给定类可以以元组形式传参,obj 是其中任何一个类型的实例就返回 True。
isinstance(1, int)
True
isinstance('abc', (float, complex))
False
# bool 是 int 的子类型,但不是实例
isinstance(bool, int)
False
# True 是 int 的子类的实例
isinstance(True, int)
True
# bool 的实例只有 True 和 False
isinstance(1, bool)
False
# 所有的对象都是 object 的实例
isinstance(object, object)
True
import random # 模块
class A:pass # 自定义类
isinstance(1, object),\
isinstance(int, object),\
isinstance(list, object),\
isinstance(random, object),\
isinstance(A, object)
(True, True, True, True, True)
内置函数 issubclass(),Python 官方文档描述如下:
help(issubclass)
Help on built-in function issubclass in module builtins:
issubclass(cls, class_or_tuple, /)
Return whether 'cls' is a derived from another class or is the same class.
A tuple, as in ``issubclass(x, (A, B, ...))``, may be given as the target to
check against. This is equivalent to ``issubclass(x, A) or issubclass(x, B)
or ...`` etc.
如果类 cls 是给定类的 (直接、间接或虚拟) 子类则返回 True,不是则返回 False。给定的不是类则引发 TypeError 异常。
给定类可以以元组形式传参,cls 是其中任何一个类的子类就返回 True。
issubclass(1, int) # 1 不是类
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-2-257e7a8dbb04> in <module>
----> 1 issubclass(1, int)
TypeError: issubclass() arg 1 must be a class
issubclass(bool, int)
True
issubclass(bool, (set, str, list))
False
# 所有的类都是 object 的子类
class A:pass
issubclass(A, object),\
issubclass(str, object),\
issubclass(object, object)
(True, True, True)
内置函数 iter(),Python 官方文档描述如下:
help(iter)
Help on built-in function iter in module builtins:
iter(...)
iter(iterable) -> iterator
iter(callable, sentinel) -> iterator
Get an iterator from an object. In the first form, the argument must
supply its own iterator, or be a sequence.
In the second form, the callable is called until it returns the sentinel.
将一个可迭代对象(iterable)或可调用对象(callable)转换为一个迭代器。
当参数是可调用对象时,需要提供参数 sentinel,生成的迭代器,每次 迭代时都会不带实参地调用 callable,返回 sentinel 时则触 发 StopIteration。
a = iter('abcd')
a
<str_iterator at 0x1c7eea4f910>
next(a),next(a),next(a),next(a)
('a', 'b', 'c', 'd')
a = iter(int, 1)
for i in range(3):
print(next(a))
0
0
0
a = iter(int, 0)
next(a)
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-21-694e44f6d78c> in <module>
1 a = iter(int, 0)
----> 2 next(a)
StopIteration:
内置函数 len(),Python 官方文档描述如下:
help(len)
Help on built-in function len in module builtins:
len(obj, /)
Return the number of items in a container.
返回对象的长度(元素个数)。实参可以是序列(如 str、bytes、tuple、list 或 range 等的实例),集合(set 或 frozenset 的实例),或字典(dict 的实例)等。
len('123')
3
len('嗨')
1
len('嗨'.encode())
3
len([1,2,3])
3
len({'a':1,'b':2})
2
内置函数(类)list,Python 官方文档描述如下:
help(list)
Help on class list in module builtins:
class list(object)
| list(iterable=(), /)
|
| Built-in mutable sequence.
|
| If no argument is given, the constructor creates a new empty list.
| The argument must be an iterable if specified.
|
将一个可迭代对象转为列表。不传参数将得到空列表。
type(list)
type
list()
[]
list('123')
['1', '2', '3']
list({'a':1,'b':2})
['a', 'b']
内置函数 locals(),Python 官方文档描述如下:
help(locals)
Help on built-in function locals in module builtins:
locals()
Return a dictionary containing the current scope's local variables.
NOTE: Whether or not updates to this dictionary will affect name lookups in
the local scope and vice-versa is *implementation dependent* and not
covered by any backwards compatibility guarantees.
返回包含当前作用域的局部变量的字典。在模块层级上,locals() 和 globals() 是同一个字典。
globals() 和 locals() 函数各自返回当前的全局和本地字典,因此可以将它们传递给 eval() 或 exec() 来使用。
locals()
{'__name__': '__main__',
'__doc__': 'Automatically created module for IPython interactive environment',
'__package__': None,
'__loader__': None,
'__spec__': None,
'__builtin__': <module 'builtins' (built-in)>,
'__builtins__': <module 'builtins' (built-in)>,
'_ih': ['', 'help(locals)', 'locals()'],
'_oh': {},
'_dh': ['D:\\Jupyter\\xuecn_books\\books\\xue_python_kp\\11_built-in_function'],
'In': ['', 'help(locals)', 'locals()'],
'Out': {},
'get_ipython': <bound method InteractiveShell.get_ipython of <ipykernel.zmqshell.ZMQInteractiveShell object at 0x0000023E24AE89B0>>,
'exit': <IPython.core.autocall.ZMQExitAutocall at 0x23e27368898>,
'quit': <IPython.core.autocall.ZMQExitAutocall at 0x23e27368898>,
'_': '',
'__': '',
'___': '',
'_i': 'help(locals)',
'_ii': '',
'_iii': '',
'_i1': 'help(locals)',
'_i2': 'locals()'}
def f():
a = 1
print(locals())
f()
{'a': 1}
内置函数(类)map,Python 官方文档描述如下:
help(map)
Help on class map in module builtins:
class map(object)
| map(func, *iterables) --> map object
|
| Make an iterator that computes the function using arguments from
| each of the iterables. Stops when the shortest iterable is exhausted.
|
| Methods defined here:
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __iter__(self, /)
| Implement iter(self).
|
| __next__(self, /)
| Implement next(self).
|
| __reduce__(...)
| Return state information for pickling.
|
| ----------------------------------------------------------------------
| Static methods defined here:
|
| __new__(*args, **kwargs) from builtins.type
| Create and return a new object. See help(type) for accurate signature.
返回一个将函数 func 应用于 iterable 中每一项并输出其结果的迭代器。
如果传入了额外的 iterable 参数,func 必须接受相同个数的实参并被应用于从所有可迭代对象中并行获取的项。
当有多个可迭代对象时,最短的可迭代对象耗尽则整个迭代就将结束。
type(map)
type
a = map(int, '1234')
a
<map at 0x16048be3828>
list(a)
[1, 2, 3, 4]
m = map(int,'abc',(16,16))
list(m)
[10, 11]
def f(x,y):
d = {}
d[x] = y
return d
m = map(f,'abc',(1,2))
list(m)
[{'a': 1}, {'b': 2}]
内置函数 max(),Python 官方文档描述如下:
help(max)
Help on built-in function max in module builtins:
max(...)
max(iterable, *[, default=obj, key=func]) -> value
max(arg1, arg2, *args, *[, key=func]) -> value
With a single iterable argument, return its biggest item. The
default keyword-only argument specifies an object to return if
the provided iterable is empty.
With two or more arguments, return the largest argument.
返回可迭代对象中最大的元素,或多个实参中最大的项。参数说明:
max('3142')
'4'
max([], default=0)
0
max(2,4,3,4)
4
max([2,1],[2,1,1])
[2, 1, 1]
max(('a','ab','bcd'),key=len)
'bcd'
内置函数 min(),Python 官方文档描述如下:
help(min)
Help on built-in function min in module builtins:
min(...)
min(iterable, *[, default=obj, key=func]) -> value
min(arg1, arg2, *args, *[, key=func]) -> value
With a single iterable argument, return its smallest item. The
default keyword-only argument specifies an object to return if
the provided iterable is empty.
With two or more arguments, return the smallest argument.
返回可迭代对象中最小的元素,或多个实参中最小的项。参数说明:
min('3142')
'1'
min([], default=0)
0
min(2,3,2,4)
2
min([2,1],[2,1,1])
[2, 1]
min(('a','ab','bcd'),key=len)
'a'
内置函数 next(),Python 官方文档描述如下:
help(next)
Help on built-in function next in module builtins:
next(...)
next(iterator[, default])
Return the next item from the iterator. If default is given and the iterator
is exhausted, it is returned instead of raising StopIteration.
返回迭代器(iterator)的下一个元素。如果迭代器耗尽,则返回给定的 default,如果没有默认值则触发 StopIteration。
i = iter('123')
next(i,'迭代结束')
'1'
next(i,'迭代结束')
'2'
next(i,'迭代结束')
'3'
next(i,'迭代结束')
'迭代结束'
next(i,'迭代结束')
'迭代结束'
内置函数(类)object,Python 官方文档描述如下:
help(object)
Help on class object in module builtins:
class object
| The most base type
当被调用时,它不接受任何参数,并返回一个新的无特性实例,并且不能给定任何实例属性。
object 是所有类的基类。它具有所有 Python 类实例的通用方法。
type(object)
type
object()
<object at 0x1de8bc75170>
dir(object)
['__class__',
'__delattr__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__']
内置函数 oct(),Python 官方文档描述如下:
help(oct)
Help on built-in function oct in module builtins:
oct(number, /)
Return the octal representation of an integer.
>>> oct(342391)
'0o1234567'
将一个整数转换为八进制整数的字符串形式。
oct(123)
'0o173'
0o173
123
oct(0x12)
'0o22'
0x12, 0o22
(18, 18)
内置函数 open(),Python 官方文档描述如下:
help(open)
Help on built-in function open in module io:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
Open file and return a stream. Raise OSError upon failure.
file is either a text or byte string giving the name (and the path
if the file isn't in the current working directory) of the file to
be opened or an integer file descriptor of the file to be
wrapped. (If a file descriptor is given, it is closed when the
returned I/O object is closed, unless closefd is set to False.)
mode is an optional string that specifies the mode in which the file
is opened. It defaults to 'r' which means open for reading in text
mode. Other common values are 'w' for writing (truncating the file if
it already exists), 'x' for creating and writing to a new file, and
'a' for appending (which on some Unix systems, means that all writes
append to the end of the file regardless of the current seek position).
In text mode, if encoding is not specified the encoding used is platform
dependent: locale.getpreferredencoding(False) is called to get the
current locale encoding. (For reading and writing raw bytes use binary
mode and leave encoding unspecified.) The available modes are:
========= ===============================================================
Character Meaning
--------- ---------------------------------------------------------------
'r' open for reading (default)
'w' open for writing, truncating the file first
'x' create a new file and open it for writing
'a' open for writing, appending to the end of the file if it exists
'b' binary mode
't' text mode (default)
'+' open a disk file for updating (reading and writing)
'U' universal newline mode (deprecated)
========= ===============================================================
The default mode is 'rt' (open for reading text). For binary random
access, the mode 'w+b' opens and truncates the file to 0 bytes, while
'r+b' opens the file without truncation. The 'x' mode implies 'w' and
raises an `FileExistsError` if the file already exists.
Python distinguishes between files opened in binary and text modes,
even when the underlying operating system doesn't. Files opened in
binary mode (appending 'b' to the mode argument) return contents as
bytes objects without any decoding. In text mode (the default, or when
't' is appended to the mode argument), the contents of the file are
returned as strings, the bytes having been first decoded using a
platform-dependent encoding or using the specified encoding if given.
'U' mode is deprecated and will raise an exception in future versions
of Python. It has no effect in Python 3. Use newline to control
universal newlines mode.
buffering is an optional integer used to set the buffering policy.
Pass 0 to switch buffering off (only allowed in binary mode), 1 to select
line buffering (only usable in text mode), and an integer > 1 to indicate
the size of a fixed-size chunk buffer. When no buffering argument is
given, the default buffering policy works as follows:
* Binary files are buffered in fixed-size chunks; the size of the buffer
is chosen using a heuristic trying to determine the underlying device's
"block size" and falling back on `io.DEFAULT_BUFFER_SIZE`.
On many systems, the buffer will typically be 4096 or 8192 bytes long.
* "Interactive" text files (files for which isatty() returns True)
use line buffering. Other text files use the policy described above
for binary files.
encoding is the name of the encoding used to decode or encode the
file. This should only be used in text mode. The default encoding is
platform dependent, but any encoding supported by Python can be
passed. See the codecs module for the list of supported encodings.
errors is an optional string that specifies how encoding errors are to
be handled---this argument should not be used in binary mode. Pass
'strict' to raise a ValueError exception if there is an encoding error
(the default of None has the same effect), or pass 'ignore' to ignore
errors. (Note that ignoring encoding errors can lead to data loss.)
See the documentation for codecs.register or run 'help(codecs.Codec)'
for a list of the permitted encoding error strings.
newline controls how universal newlines works (it only applies to text
mode). It can be None, '', '\n', '\r', and '\r\n'. It works as
follows:
* On input, if newline is None, universal newlines mode is
enabled. Lines in the input can end in '\n', '\r', or '\r\n', and
these are translated into '\n' before being returned to the
caller. If it is '', universal newline mode is enabled, but line
endings are returned to the caller untranslated. If it has any of
the other legal values, input lines are only terminated by the given
string, and the line ending is returned to the caller untranslated.
* On output, if newline is None, any '\n' characters written are
translated to the system default line separator, os.linesep. If
newline is '' or '\n', no translation takes place. If newline is any
of the other legal values, any '\n' characters written are translated
to the given string.
If closefd is False, the underlying file descriptor will be kept open
when the file is closed. This does not work when a file name is given
and must be True in that case.
A custom opener can be used by passing a callable as *opener*. The
underlying file descriptor for the file object is then obtained by
calling *opener* with (*file*, *flags*). *opener* must return an open
file descriptor (passing os.open as *opener* results in functionality
similar to passing None).
open() returns a file object whose type depends on the mode, and
through which the standard file operations such as reading and writing
are performed. When open() is used to open a file in a text mode ('w',
'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open
a file in a binary mode, the returned class varies: in read binary
mode, it returns a BufferedReader; in write binary and append binary
modes, it returns a BufferedWriter, and in read/write mode, it returns
a BufferedRandom.
It is also possible to use a string or bytearray as a file for both
reading and writing. For strings StringIO can be used like a file
opened in a text mode, and for bytes a BytesIO can be used like a file
opened in a binary mode.
打开文件 file 并返回对应的文件对象(file object)。
参数说明:
1,file 是将要打开的文件的路径(绝对路径或者当前工作目录的相对路径),也可以是要被封装的整数类型文件描述符。(如果是文件描述符,它会随着返回的 I/O 对象关闭而关闭,除非 closefd 被设为 False )。
2,mode 是一个可选字符串,用于指定打开文件的模式。默认值是 ‘r’ ,这意味着它以文本模式打开并读取。在文本模式,如果 encoding 没有指定,则根据平台来决定使用的编码(要读取和写入原始字节,请使用二进制模式并不要指定 encoding)。可用的模式有:
模式 ‘r’,‘w’,‘x’,‘a’ 可以单独使用,也可与 ‘b’ 或 ‘+’,或两者同时组合使用。‘b’,’t’ 和 ‘+’ 不能单独使用。‘b’ 和 ’t’ 互斥,’t’ 默认省略。
默认模式为 ‘r’ (打开用于读取文本,与 ‘rt’ 同义)。模式 ‘w+’ 与 ‘w+b’ 打开文件并清空内容。模式 ‘r+’ 与 ‘r+b’ 打开文件并不清空内容。
以二进制模式打开的文件返回的内容为字节串,不进行任何解码。在文本模式下打开时,文件内容返回为字符串,首先使用指定的 encoding (如果给定)或者使用平台默认的的字节编码解码。
3,buffering 是一个可选的整数,用于设置缓冲策略。
4,encoding 是用于解码或编码文件的编码的名称。这应该只在文本模式下使用。
5,errors 是一个可选的字符串参数,用于指定如何处理编码和解码错误。这不能在二进制模式下使用。
6,newline 控制通用换行模式如何生效(它仅适用于文本模式)。
7,如果 closefd 是 False 并且打开文件给出了文件描述符而不是文件名,那么当文件关闭时,底层文件描述符将保持打开状态。如果给出文件名则 closefd 必须为 True (默认值),否则将引发错误。
8,可以通过传递可调用的 opener 来使用自定义开启器。
with open('test.txt') as f:
print(f)
<_io.TextIOWrapper name='test.txt' mode='r' encoding='cp936'>
with open('test.txt',encoding='utf-8') as f:
print(f.read())
xue.cn
自学是门手艺
with open('test.txt','rb') as f:
print(f.read())
b'xue.cn\r\n\r\n\xe8\x87\xaa\xe5\xad\xa6\xe6\x98\xaf\xe9\x97\xa8\xe6\x89\x8b\xe8\x89\xba'
内置函数 ord(),Python 官方文档描述如下:
help(ord)
Help on built-in function ord in module builtins:
ord(c, /)
Return the Unicode code point for a one-character string.
返回单个字符 Unicode 码点的整数。这是 chr() 的逆函数。
ord('a')
97
chr(97)
'a'
内置函数 pow(),Python 官方文档描述如下:
help(pow)
Help on built-in function pow in module builtins:
pow(base, exp, mod=None)
Equivalent to base**exp with 2 arguments or base**exp % mod with 3 arguments
Some types, such as ints, are able to use a more efficient algorithm when
invoked using the three argument form.
返回 base 的 exp 次幂;如果 mod 存在,则返回 base 的 exp 次幂对 mod 取余(比 pow(base, exp) % mod
更高效)。
对于混用的操作数类型,则将应用双目算术运算符的类型强制转换规则。 对于 int 操作数,结果具有与操作数相同的类型(强制转换后),除非第二个参数为负值;在这种情况下,所有参数将被转换为浮点数并输出浮点数结果。
对于 int 操作数 base 和 exp,如果给出 mod,则 mod 必须为整数类型并且 mod 必须不为零。如果给出 mod 并且 exp 为负值,则 base 必须相对于 mod 不可整除。在这种情况下,将会返回 pow(inv_base, -exp, mod)
,其中 inv_base 为 base 的倒数对 mod 取余。
在 3.8 版更改: 对于 int 操作数,三参数形式的 pow 现在允许第二个参数为负值,即可以计算倒数的余数;允许关键字参数。
pow(2, 3, 4)
0
pow(2.0, 3)
8.0
pow(2, -1)
0.5
pow(38, -1, 97) # 38 的倒数对 97 取余为 23
23
23 * 38 % 97 == 1
True
pow(38, -2, 97), pow(23, 2, 97)
(44, 44)
内置函数 print(),Python 官方文档描述如下:
help(print)
Help on built-in function print in module builtins:
print(...)
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.
将 value … 打印到 file 指定的文本流,以 sep 分隔并在末尾加上 end。sep, end, file 和 flush 如果存在,它们必须以关键字参数的形式给出。
所有非关键字参数都会被转换为字符串,就像是执行了 str() 一样,并会被写入到流。sep 和 end 都必须为字符串。sep 默认为一个空格 ’ ‘,end 默认为换行 ‘\n’。
如果没有给出 value …,则 print() 将只打印 end。
file 参数必须是一个具有 write(string)
方法的对象。如果参数不指定,则将使用解释器用于标准输出的文件对象 sys.stdout。
输出是否被缓存通常决定于 file,但如果 flush 关键字参数为真值,流会被强制刷新。
该函数返回值为 None。
print(1+1)
print('a','b')
2
a b
print('a',1,int, sep='-', end='end')
a-1-<class 'int'>end
print(end='end')
end
p = print('end')
print(p)
end
None
内置函数(类)property,Python 官方文档描述如下:
help(property)
Help on class property in module builtins:
class property(object)
| property(fget=None, fset=None, fdel=None, doc=None)
|
| Property attribute.
|
| fget
| function to be used for getting an attribute value
| fset
| function to be used for setting an attribute value
| fdel
| function to be used for del'ing an attribute
| doc
| docstring
|
| Typical use is to define a managed attribute x:
|
| class C(object):
| def getx(self): return self._x
| def setx(self, value): self._x = value
| def delx(self): del self._x
| x = property(getx, setx, delx, "I'm the 'x' property.")
|
| Decorators make defining new properties or modifying existing ones easy:
|
| class C(object):
| @property
| def x(self):
| "I am the 'x' property."
| return self._x
| @x.setter
| def x(self, value):
| self._x = value
| @x.deleter
| def x(self):
| del self._x
|
返回 property 属性。
fget 是获取属性值的函数。fset 是用于设置属性值的函数。fdel 是用于删除属性值的函数,doc 为属性对象创建文档字符串。
type(property)
type
dir(property)
['__class__',
'__delattr__',
'__delete__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__get__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__isabstractmethod__',
'__le__',
'__lt__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__set__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'deleter',
'fdel',
'fget',
'fset',
'getter',
'setter']
一个典型的用法是定义一个托管属性 x:
# 列一
class C:
def __init__(self,value):
self._x = value
def getx(self):
return self._x
def setx(self, value):
self._x = value
def delx(self):
del self._x
x = property(getx, setx, delx, "I'm the 'x' property.")
如果 c 是 C 的实例,c.x
将调用 getter,c.x = value
将调用 setter,del c.x
将调用 deleter。
如果给出,doc 将成为该 property 属性的文档字符串。否则该 property 将拷贝 fget 的文档字符串(如果存在)。
c = C(1)
c.x
1
c.x = 2
c.x
2
del c.x
c.x
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-16-d32ce31f0255> in <module>
1 del c.x
----> 2 c.x
<ipython-input-10-eaaa1d84111b> in getx(self)
4
5 def getx(self):
----> 6 return self._x
7
8 def setx(self, value):
AttributeError: 'C' object has no attribute '_x'
这令使用 property() 作为装饰器来创建只读的特征属性可以很容易地实现:
class Parrot:
def __init__(self):
self._voltage = 100000
@property
def voltage(self):
"""Get the current voltage."""
return self._voltage
以上 @property 装饰器会将 voltage() 方法转化为一个具有相同名称的只读属性的 getter,并将 voltage 的文档字符串设置为 ‘Get the current voltage.’
p = Parrot()
p.voltage
100000
p.voltage = 100
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-20-50ba7917c8b5> in <module>
----> 1 p.voltage = 100
AttributeError: can't set attribute
特征属性对象具有 getter, setter 以及 deleter 方法,它们可用作装饰器来创建该特征属性的副本,并将相应的访问函数设为所装饰的函数。
class C:
def __init__(self,value):
self._x = value
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
上述代码与 例一 完全等价。注意一定要给附加函数与原始的特征属性相同的名称。
c = C(1)
c.x
1
c.x = 2
c.x
2
del c.x
c.x
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-7-d32ce31f0255> in <module>
1 del c.x
----> 2 c.x
<ipython-input-4-356a299284e7> in x(self)
6 def x(self):
7 """I'm the 'x' property."""
----> 8 return self._x
9
10 @x.setter
AttributeError: 'C' object has no attribute '_x'
内置函数(类)range,Python 官方文档描述如下:
help(range)
Help on class range in module builtins:
class range(object)
| range(stop) -> range object
| range(start, stop[, step]) -> range object
|
| Return an object that produces a sequence of integers from start (inclusive)
| to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.
| start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.
| These are exactly the valid indices for a list of 4 elements.
| When step is given, it specifies the increment (or decrement).
|
| Methods defined here:
|
| __bool__(self, /)
| self != 0
|
| __contains__(self, key, /)
| Return key in self.
|
| __eq__(self, value, /)
| Return self==value.
|
| __ge__(self, value, /)
| Return self>=value.
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __getitem__(self, key, /)
| Return self[key].
|
| __gt__(self, value, /)
| Return self>value.
|
| __hash__(self, /)
| Return hash(self).
|
| __iter__(self, /)
| Implement iter(self).
|
| __le__(self, value, /)
| Return self<=value.
|
| __len__(self, /)
| Return len(self).
|
| __lt__(self, value, /)
| Return self<value.
|
| __ne__(self, value, /)
| Return self!=value.
|
| __reduce__(...)
| Helper for pickle.
|
| __repr__(self, /)
| Return repr(self).
|
| __reversed__(...)
| Return a reverse iterator.
|
| count(...)
| rangeobject.count(value) -> integer -- return number of occurrences of value
|
| index(...)
| rangeobject.index(value, [start, [stop]]) -> integer -- return index of value.
| Raise ValueError if the value is not present.
|
| ----------------------------------------------------------------------
| Static methods defined here:
|
| __new__(*args, **kwargs) from builtins.type
| Create and return a new object. See help(type) for accurate signature.
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| start
|
| step
|
| stop
虽然被称为函数,但 range 实际上是一个不可变的序列类型,参见 range 对象。
type(range)
type
list(range(3))
[0, 1, 2]
list(range(-5))
[]
list(range(1,5,2))
[1, 3]
list(range(0,-5,-1))
[0, -1, -2, -3, -4]
内置函数 repr(),Python 官方文档描述如下:
help(repr)
Help on built-in function repr in module builtins:
repr(obj, /)
Return the canonical string representation of the object.
For many object types, including most builtins, eval(repr(obj)) == obj.
返回包含一个对象的可打印表示形式的字符串。
对于许多类型来说,该函数会尝试返回的字符串将会与该对象被传递给 eval() 时所生成的对象具有相同的值,在其他情况下表示形式会是一个括在尖括号中的字符串,其中包含对象类型的名称与通常包括对象名称和地址的附加信息。
repr(1+1)
'2'
repr(int)
"<class 'int'>"
str('python\n')
'python\n'
repr('python\n')
"'python\\n'"
内置函数(类)reversed,Python 官方文档描述如下:
help(reversed)
Help on class reversed in module builtins:
class reversed(object)
| reversed(sequence, /)
|
| Return a reverse iterator over the values of the given sequence.
|
| Methods defined here:
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __iter__(self, /)
| Implement iter(self).
|
| __length_hint__(...)
| Private method returning an estimate of len(list(it)).
|
| __next__(self, /)
| Implement next(self).
|
| __reduce__(...)
| Return state information for pickling.
|
| __setstate__(...)
| Set state information for unpickling.
|
| ----------------------------------------------------------------------
| Static methods defined here:
|
| __new__(*args, **kwargs) from builtins.type
| Create and return a new object. See help(type) for accurate signature.
返回给定的序列逆置之后的迭代器。
type(reversed)
type
reversed('1234')
<reversed at 0x14b684fe460>
list(reversed('1234'))
['4', '3', '2', '1']
因为字典顺序会确保为插入顺序,字典和字典视图都是可逆的。3.8 新版可以返回一个逆序获取字典键的迭代器。
d = reversed({'a':1,'b':2,'c':3})
list(d)
['c', 'b', 'a']
内置函数 round(),Python 官方文档描述如下:
help(round)
Help on built-in function round in module builtins:
round(number, ndigits=None)
Round a number to a given precision in decimal digits.
The return value is an integer if ndigits is omitted or None. Otherwise
the return value has the same type as the number. ndigits may be negative.
返回 number 舍入到小数点后 ndigits 位精度的值。如果 ndigits 被省略或为 None,则返回最接近输入值的整数。
对于支持 round() 的内置类型,值会被舍入到最接近的 10 的负 ndigits 次幂的倍数;如果与两个倍数的距离相等,则选择偶数。
任何整数值都可作为有效的 ndigits (正数、零或负数)。如果 ndigits 被省略或为 None 则返回值将为整数。否则返回值与 number 的类型相同。
由于大多数十进制小数实际上都不能以浮点数精确地表示。返回值可能会不是预期的四舍五入结果。
round(3.14)
3
round(3.14, 3)
3.14
round(3.14, 0)
3.0
round(13.14,-1)
10.0
round(2.5), round(-2.5)
(2, -2)
round(1.5), round(-1.5)
(2, -2)
round(2.675, 2), round(2.665, 2)
(2.67, 2.67)
内置函数(类)set,Python 官方文档描述如下:
help(set)
Help on class set in module builtins:
class set(object)
| set() -> new empty set object
| set(iterable) -> new set object
|
| Build an unordered collection of unique elements.
|
将一个可迭代对象转换为集合。可迭代对象为空,或不传参数,将得到空集合。
type(set)
type
set([])
set()
set()
set()
set('1231')
{'1', '2', '3'}
set({'1':1, '2':2, '3':3})
{'1', '2', '3'}
内置函数 setattr(),Python 官方文档描述如下:
help(setattr)
Help on built-in function setattr in module builtins:
setattr(obj, name, value, /)
Sets the named attribute on the given object to the specified value.
setattr(x, 'y', v) is equivalent to ``x.y = v''
参数为一个对象、一个字符串和一个任意值。字符串指定一个现有属性或者新增属性。函数会将值赋给该属性,只要对象允许这种操作。
class A:
y = 1
x = A()
x.y
1
# 为实例 x 新增属性
setattr(x, 'y', 10)
x.y
10
A.y
1
# 修改类 A 的 y 属性
setattr(A, 'y', 100)
A.y
100
x.y
10
内置函数(类)slice,Python 官方文档描述如下:
help(slice)
Help on class slice in module builtins:
class slice(object)
| slice(stop)
| slice(start, stop[, step])
|
| Create a slice object. This is used for extended slicing (e.g. a[0:10:2]).
|
返回一个表示由 range(start, stop, step) 指定索引集的 slice 对象。其中 start 和 step 参数默认为 None。
切片对象具有仅会返回对应参数值(或其默认值)的只读数据属性 start, stop 和 step。它们没有其他的显式功能。
type(slice)
type
s = slice(3)
s
slice(None, 3, None)
a = list(range(5))
a[s]
[0, 1, 2]
slice(2,8,2)
slice(2, 8, 2)
list(range(10)[slice(2,8,2)])
[2, 4, 6]
内置函数 sorted(),Python 官方文档描述如下:
help(sorted)
Help on built-in function sorted in module builtins:
sorted(iterable, /, *, key=None, reverse=False)
Return a new list containing all items from the iterable in ascending order.
A custom key function can be supplied to customize the sort order, and the
reverse flag can be set to request the result in descending order.
根据 iterable 中的项返回一个新的已排序列表。
具有两个可选参数,它们都必须指定为关键字参数。
key 指定带有单个参数的函数,应用于 iterable 中的每个元素,将计算结果用来对原 iterable 排序。默认值为 None (直接比较)。
reverse 为一个布尔值。如果设为 True,则每个列表元素将按反向顺序比较进行排序。
sorted() 排序确保是稳定的。如果一个排序确保不会改变比较结果相等的元素的相对顺序就称其为稳定的 — 这有利于进行多重排序。
sorted({'b':1,'a':3,'c':2})
['a', 'b', 'c']
d = [{'age':18},{'age':30},{'age':26}]
sorted(d,key=lambda x:x['age'])
[{'age': 18}, {'age': 26}, {'age': 30}]
sorted([1.5,'2.0','1.5',3.14], key=float)
[1.5, '1.5', '2.0', 3.14]
sorted('3123', reverse=True)
['3', '3', '2', '1']
内置函数(类)staticmethod,Python 官方文档描述如下:
help(staticmethod)
Help on class staticmethod in module builtins:
class staticmethod(object)
| staticmethod(function) -> method
|
| Convert a function to be a static method.
|
| A static method does not receive an implicit first argument.
| To declare a static method, use this idiom:
|
| class C:
| @staticmethod
| def f(arg1, arg2, ...):
| ...
|
| It can be called either on the class (e.g. C.f()) or on an instance
| (e.g. C().f()). The instance is ignored except for its class.
|
| Static methods in Python are similar to those found in Java or C++.
| For a more advanced concept, see the classmethod builtin.
|
将函数转换为静态方法。
静态方法不会接收隐式的第一个参数。可以传递一个函数作为参数定义为静态方法,也可以使用装饰器的形式将一个自定义函数定义为静态方法。
type(staticmethod)
type
class A:
in_print = staticmethod(print)
a = A()
a.in_print('静态方法')
静态方法
class A:
@staticmethod
def in_print(value):
print(value)
a = A()
a.in_print('静态方法')
静态方法
内置函数(类)str,Python 官方文档描述如下:
help(str)
Help on class str in module builtins:
class str(object)
| str(object='') -> str
| str(bytes_or_buffer[, encoding[, errors]]) -> str
|
| Create a new string object from the given object. If encoding or
| errors is specified, then the object must expose a data buffer
| that will be decoded using the given encoding and error handler.
| Otherwise, returns the result of object.__str__() (if defined)
| or repr(object).
| encoding defaults to sys.getdefaultencoding().
| errors defaults to 'strict'.
|
返回对象 object 的字符串形式。如果未提供 object 则返回空字符串。
如果 encoding 或 errors 至少给出其中之一,则 bytes_or_buffer 应该是一个 bytes-like object (例如字节串或字节数组)。在此情况下,如果是一个字节串 (或字节数组) 对象,则 str(bytes, encoding, errors)
等价于 bytes.decode(encoding, errors)
。否则的话,会在调用 bytes.decode()
之前获取缓冲区对象下层的 bytes 对象。
将一个 bytes 对象传入 str() 而不给出 encoding 或 errors 参数,将直接转 bytes 对象为字符串。
type(str)
type
str()
''
str(int)
"<class 'int'>"
str([1,2,3])
'[1, 2, 3]'
str(b'\xe8\x87\xaa\xe5\xad\xa6',encoding='utf-8')
'自学'
b'\xe8\x87\xaa\xe5\xad\xa6'.decode(encoding='utf-8')
'自学'
str(b'\xe8\x87\xaa\xe5\xad\xa6')
"b'\\xe8\\x87\\xaa\\xe5\\xad\\xa6'"
内置函数 sum(),Python 官方文档描述如下:
help(sum)
Help on built-in function sum in module builtins:
sum(iterable, start=0, /)
Return the sum of a 'start' value (default: 0) plus an iterable of numbers
When the iterable is empty, return the start value.
This function is intended specifically for use with numeric values and may
reject non-numeric types.
通常对一个以数字为元素的可迭代对象求和并返回和。如果指定 start 参数,和需要加上 start。
start 不能为字符串,拼接字符串 sum() 不支持,更好更快的方式是 str.join() 方法。
sum() 还支持其他序列(列表和元组)。
sum([1,2,3])
6
sum(range(4), 10)
16
sum([(1,2),(3,4)], (5,))
(5, 1, 2, 3, 4)
sum([[1,2],[3]],[0])
[0, 1, 2, 3]
内置函数(类)super,Python 官方文档描述如下:
help(super)
Help on class super in module builtins:
class super(object)
| super() -> same as super(__class__, <first argument>)
| super(type) -> unbound super object
| super(type, obj) -> bound super object; requires isinstance(obj, type)
| super(type, type2) -> bound super object; requires issubclass(type2, type)
| Typical use to call a cooperative superclass method:
| class C(B):
| def meth(self, arg):
| super().meth(arg)
| This works for class methods too:
| class C(B):
| @classmethod
| def cmeth(cls, arg):
| super().cmeth(arg)
|
返回一个代理对象,它会将方法调用委托给类 type 的父类或兄弟类。这对于访问已在类中被重载的继承方法很有用。
super()
和 super(__class__, <first argument>)
一样。super 有两个典型用例:
类或方法的 __mro__
属性列出了 getattr() 和 super() 所共同使用的方法解析顺序(MRO)。该属性是动态的,可以在任何继承层级结构发生更新的时候被改变。
除了方法查找之外,super() 也可用于属性查找。一个可能的应用场合是在上级或同级类中调用描述器。
请注意 super() 是作为显式加点属性查找的绑定过程的一部分来实现的,例如 super().__getitem__(name)
。它做到这一点是通过实现自己的 __getattribute__()
方法,这样就能以可预测的顺序搜索类,并且支持协作多重继承。
还要注意的是,除了零个参数的形式以外,super() 并不限于在方法内部使用。两个参数的形式明确指定参数并进行相应的引用。零个参数的形式仅适用于类定义内部,因为编译器需要填入必要的细节以正确地检索到被定义的类,还需要让普通方法访问当前实例。
方法调用委托给父类:
type(super)
type
class A:
def add(self, x):
y = x + x
print(y)
class B(A):
def add(self, x):
super().add(x) # super() 等价于 super(B,self)
b = B()
b.add(5)
10
初始化委托给父类:
class A:
def __init__(self):
self.a = '父类A'
print ('A')
def print_msg(self,a):
print (f'{a}来自A')
class B(A):
def __init__(self):
# super(B, self) 可写为 super()
super(B, self).__init__()
print ('B')
def print_msg(self,b):
super().print_msg(b)
print (f'{b}来自B')
print (self.a)
b = B()
b.print_msg('HelloWorld')
A
B
HelloWorld来自A
HelloWorld来自B
父类A
内置函数(类)tuple,Python 官方文档描述如下:
help(tuple)
Help on class tuple in module builtins:
class tuple(object)
| tuple(iterable=(), /)
|
| Built-in immutable sequence.
|
| If no argument is given, the constructor returns an empty tuple.
| If iterable is specified the tuple is initialized from iterable's items.
|
| If the argument is a tuple, the return value is the same object.
|
将可迭代对象转换为元组。可迭代对象为空或不传参数,返回空元组。
type(tuple)
type
tuple('')
()
tuple('123')
('1', '2', '3')
内置函数(类)type,Python 官方文档描述如下:
help(type)
Help on class type in module builtins:
class type(object)
| type(object_or_name, bases, dict)
| type(object) -> the object's type
| type(name, bases, dict) -> a new type
|
传入一个参数时,返回对象的类型。推荐使用 isinstance() 内置函数来检测对象的类型,因为它会考虑子类的情况。
传入三个参数时,返回一个新的 type 对象。这在本质上是 class 语句的一种动态形式。name 参数是字符串即类名并且会成为 __name__
属性;bases 元组列出基类并且会成为 __bases__
属性;而 dict 字典为包含类主体定义的命名空间并且会被复制到一个标准字典成为 __dict__
属性。
type(type)
type
type(int), type(object)
(type, type)
isinstance(int, object)
True
class A:
a = 1
A.__name__, A.__bases__, A.__dict__
('A',
(object,),
mappingproxy({'__module__': '__main__',
'a': 1,
'__dict__': <attribute '__dict__' of 'A' objects>,
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'__doc__': None}))
A = type('A', (object,), dict(a=1))
A.__name__, A.__bases__, A.__dict__
('A',
(object,),
mappingproxy({'a': 1,
'__module__': '__main__',
'__dict__': <attribute '__dict__' of 'A' objects>,
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'__doc__': None}))
内置函数 vars(),Python 官方文档描述如下:
help(vars)
Help on built-in function vars in module builtins:
vars(...)
vars([object]) -> dictionary
Without arguments, equivalent to locals().
With an argument, equivalent to object.__dict__.
返回模块、类、实例或任何其它具有 __dict__
属性的对象的 __dict__
属性。
模块和实例这样的对象具有可更新的 __dict__
属性;但是,其它对象的 __dict__
属性可能会设为限制写入(例如,类会使用types.MappingProxyType
来防止直接更新字典)。
不带参数时,vars() 的行为类似 locals()。请注意,locals 字典仅对于读取起作用,因为对 locals 字典的更新会被忽略。
如果指定了一个对象但它没有 __dict__
属性则会引发TypeError 异常。
vars()
{'__name__': '__main__',
'__doc__': 'Automatically created module for IPython interactive environment',
'__package__': None,
'__loader__': None,
'__spec__': None,
'__builtin__': <module 'builtins' (built-in)>,
'__builtins__': <module 'builtins' (built-in)>,
'_ih': ['', "get_ipython().run_line_magic('pinfo', 'vars')", 'vars()'],
'_oh': {},
'_dh': ['E:\\xue\\脚本\\kp_book\\11_built-in_function'],
'In': ['', "get_ipython().run_line_magic('pinfo', 'vars')", 'vars()'],
'Out': {},
'get_ipython': <bound method InteractiveShell.get_ipython of <ipykernel.zmqshell.ZMQInteractiveShell object at 0x00000189A6512310>>,
'exit': <IPython.core.autocall.ZMQExitAutocall at 0x189a65b32e0>,
'quit': <IPython.core.autocall.ZMQExitAutocall at 0x189a65b32e0>,
'_': '',
'__': '',
'___': '',
'_i': 'vars?',
'_ii': '',
'_iii': '',
'_i1': 'vars?',
'_i2': 'vars()'}
def f():pass
vars(f)
{}
f.__dict__['a'] = 1
f.a
1
vars(1)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-9-3391faf83557> in <module>
----> 1 vars(1)
TypeError: vars() argument must have __dict__ attribute
内置函数(类)zip,Python 官方文档描述如下:
help(zip)
Help on class zip in module builtins:
class zip(object)
| zip(iter1 [,iter2 [...]]) --> zip object
|
| Return a zip object whose .__next__() method returns a tuple where
| the i-th element comes from the i-th iterable argument. The .__next__()
| method continues until the shortest iterable in the argument sequence
| is exhausted and then it raises StopIteration.
|
| Methods defined here:
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __iter__(self, /)
| Implement iter(self).
|
| __next__(self, /)
| Implement next(self).
|
| __reduce__(...)
| Return state information for pickling.
|
| ----------------------------------------------------------------------
| Static methods defined here:
|
| __new__(*args, **kwargs) from builtins.type
| Create and return a new object. See help(type) for accurate signature.
创建一个聚合了来自每个可迭代对象中的元素的迭代器。
返回一个元组的迭代器,其中的第 i 个元组包含来自每个可迭代对象的第 i 个元素。
当所输入可迭代对象中最短的一个被耗尽时,迭代器将停止迭代。
当只有一个可迭代对象参数时,它将返回一个单元组的迭代器。
不带参数时,它将返回一个空迭代器。
type(zip)
type
zip()
<zip at 0x2ac600edac8>
list(zip('123'))
[('1',), ('2',), ('3',)]
list(zip('123',{3,2,1}))
[('1', 1), ('2', 2), ('3', 3)]
list(zip([3,2,1],(1,2,3,4),'12'))
[(3, 1, '1'), (2, 2, '2')]
list(zip(*['abc','123']))
[('a', '1'), ('b', '2'), ('c', '3')]
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。是可以向调用者返回某个值(至少是 None)的一组语句。
函数使代码的组织模块化,提供了代码的利用率。例如 print() 函数实现打印功能,input() 函数实现输入功能,需要它们的地方,都可以使用。
函数通过函数名称来使用它,传入零个或多个参数,并在函数体执行中被使用。
# 函数 abs() 返回一个数的绝对值
a = abs(-3.14)
a
3.14
# print() 函数打印传入的参数值,返回 None
n = print('hello, world')
n is None
hello, world
True
按照上述定义,类也被称作函数(例如内置函数 int,list 等)。
我们通常所说的函数,是指使用 def 语句和 lambda 表达式定义的函数。
而在类内部定义,使用属性表示法来调用的函数,我们习惯称作方法。
# int 类实例化返回整数对象
int('1')
1
isinstance(1, int)
True
# list 类的方法 append 将一个对象加入列表中,返回值为 None
a = []
b = list.append(a,'123')
a, b is None
(['123'], True)
函数有内置函数和内置方法,用户也可以自定义函数和方法。定义了一个函数,即创建了一个函数对象,可以通过函数名和必要的参数调用它。
def my_sum(lst):
'将列表中的字符串数字转为数字求和' # 函数文档说明
rlt = sum(map(float,lst)) # 调用内置函数求值
return rlt # 返回结果
my_sum(['1','3.14',2]) # 调用自定义函数
6.140000000000001
函数定义有两种方式,def 语句定义有名字的函数(详见 def 定义函数),lambda 表达式定义匿名函数(详见 lambda 函数)。
定义一个函数,即是创建了一个函数可执行代码的包装器,他将函数想要实现的功能包装起来。然后通过调用它来实现其功能。def 语句 详细介绍了定义函数的语法规则,下面看看如何将一个功能包装起来。
例如下列函数,实现了将列表中的 字符串整数 以及 整数 相加求和的功能,以后只要遇到这种情况,都可以用它来求和:
sumpro([1,'2','3'])
6
# def 定义
def sumpro(lst):
return sum(int(i) for i in lst)
sumpro(['1 ',' 2',3])
6
# lambda 表达式定义
lambda lst: sum(int(i) for i in lst)
<function __main__.<lambda>(lst)>
lst = [['2','8'],['3','4']]
sorted(lst,key=lambda lst: sum(int(i) for i in lst))
[['3', '4'], ['2', '8']]
函数定义,也可以定义为实现功能,但没有返回值(默认返回 None)的过程。
例如下列函数,实现了将列表中的字符串整数都转换为整数:
def convert_to_numb(lst):
for i in range(len(lst)):
if type(lst[i]) != int:
lst[i] = int(lst[i])
lst = ['1',2,'3']
n = convert_to_numb(lst)
lst, n is None
([1, 2, 3], True)
函数定义所使用的函数名称,不能与当前作用域中以定义的名称相同,这会屏蔽掉已存在的名称,或将自定义的函数对象重新赋值给了该名称。
str(123)
'123'
def str(x):
return f'x={x}'
str(123) # 屏蔽掉了内置名称 str
'x=123'
f = 0
def f():
pass
f # f 被重新赋值
<function __main__.f()>
形参是函数定义中指定的参数名称。指定某个参数的形式,决定了该形参在函数调用时,可以接受实参的方式。关于实参详见 函数调用。
因而形参分为五种:
def f(a,b=None):
print(f'a={a},b={b}')
# 位置实参传入
f(1,2)
# 关键字实参传入
f(b=2,a=1)
a=1,b=2
a=1,b=2
/
字符来定义。/
之前的参数为仅限位置形参,之后的形参为默认形参类型。有默认值的形参也必须置于无默认值的形参之后。def f(a,b=None,/,c=None): # 因为 b 有默认值,c 必须要有默认值
print(f'a={a},b={b},c={c}')
# 按位置传参调用
f(1,2,c=3)
# 关键字传参则不允许
f(a=1,b=2)
a=1,b=2,c=3
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-6-52b3afdaad4c> in <module>
4 f(1,2,c=3)
5 # 关键字传参则不允许
----> 6 f(a=1,b=2)
TypeError: f() got some positional-only arguments passed as keyword arguments: 'a, b'
*
来定义。可变位置形参 或 *
之后的参数为仅限关键字形参。def f(*a,b=None,c=None): # b 和 c 必须有默认值
print(f'a={a},b={b},c={c}')
# 位置传参将被解读为可变位置参数
f(1,2,3)
# 关键字传参
f(1,b=2,c=3)
a=(1, 2, 3),b=None,c=None
a=(1,),b=2,c=3
def f(*,a,b=None,c):
print(f'a={a},b={b},c={c}')
# 关键字传参
f(b=2,a=1,c=3)
# 位置传参不允许
f(1,2,3)
a=1,b=2,c=3
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-1-9d584fa28622> in <module>
4 f(b=2,a=1,c=3)
5 # 位置传参不允许
----> 6 f(1,2,3)
TypeError: f() takes 0 positional arguments but 3 were given
*
来定义,并将接受到的参数封装成一个元组。该参数如果接受到了实参,它前面的参数必须为仅限位置参数。def f(a,b=None,*c):
print(f'a={a},b={b},c={c}')
# c 没有接受参数
f(1); f(b=2,a=1)
# c 接受到了参数
f(1,2,3,4,5)
a=1,b=None,c=()
a=1,b=2,c=()
a=1,b=2,c=(3, 4, 5)
**
来定义,并将接受到的参数封装成一个字典。def f(a,b=None,**c):
print(f'a={a},b={b},c={c}')
f(1,2,c=3,d=4)
f(d=4,b=2,a=1,c=3)
a=1,b=2,c={'c': 3, 'd': 4}
a=1,b=2,c={'d': 4, 'c': 3}
带默认值的参数,可变位置参数和可变关键字参数,调用函数时可以不传参。
def f(a=1,*b,c=3,**d):
print(f'a={a},b={b},c={c},d={d}')
f()
a=1,b=(),c=3,d={}
默认值只会执行一次,这条规则很重要。如果参数有默认值且为可变对象,则需要做必要的限制:
def f(a=[]):
print(id(a))
a.append(1)
print(a)
f() # 多次调用会引用参数指向的同一个对象
f()
2399568560064
[1]
2399568560064
[1, 1]
# 可以拷贝一个副本
def f(a=[]):
b = a.copy()
b.append(1)
print(b)
f()
f()
[1]
[1]
# 或者修改参数
def f(a=None):
if a == None:
a = []
a.append(1)
else:
a.append(1)
print(a)
f()
f([])
[1]
[1]
函数的形参可以使用标注,标注的语法是参数后面接一个冒号 :
,然后接一个表达式(任意表达式),通常用来指明应该(不是必须)传递什么类型的参数等。标注提高了代码的可读性:
# a 标注为字符串类型,b 标注为整数,并设置默认值 2
def f(a:str,b:int=2):
return a*b
f('Hi',3)
'HiHiHi'
def f(a:'字符串',b:'整数'=2):
return a*b
f('Hi')
'HiHi'
函数返回值通过 return 语句 来实现,调用函数时,返回 return 语句之后表达式的值,没有 return 语句或 return 语句之后为空的函数,调用函数默认返回 None。
def f(x):
return x**2
f(2)
4
def f():
pass
f() is None
True
函数执行到 return 语句,则结束当前函数的调用,可以通过条件判断,返回特定结果:
def f(x=None):
if x == None:
return 0 # 使用默认值调用函数,接下来的代码将不被执行
print(f'x={x}')
if x != None:
return f'x²={x**2}'
f()
0
f(2)
x=2
'x²=4'
return 之后的表达式可以是多个表达式用逗号隔开(其实是一个元组),可用赋值语句分别接收返回值:
def f(x):
return sum(x), max(x), min(x)
f([1,2,3,4])
(10, 4, 1)
sum_x, max_x, min_x = f([1,2,3,4])
sum_x, max_x, min_x
(10, 4, 1)
返回值可以是任何值。如果 return 之后的表达式中包含函数自身的调用,则该函数称为递归函数。详见 递归函数。
# 返回函数自身
def f(x):
print(x)
return f
f(1)(2)(3)
1
2
3
<function __main__.f(x)>
# 返回函数自身的调用
def f(x):
if x == 0:
return 0
else:
print(x-1)
return f(x-1)
f(3)
2
1
0
0
函数 return 语句的表达式中包含函数自身的调用,则称该函数为递归函数。
递归函数必须设定退出条件,并且调用过程能够逐步达到退出条件,否则将引发 RecursionError。
例如定义一个计算阶乘的函数:
上述函数的退出条件是 x == 0
,并且 return 语句中函数调用的参数是 x-1
,第一层调用函数的参数 x
为 5,return 语句进入第二层调用,就变成了 x-1
为 4,依此类推,最终以 0 调用函数,达到了退出条件,但是值还没有最终返回,以退出条件下的返回值层层向上返回,最终得到结果。详情查看 递归函数。
def f(x):
if x == 0:
return 1
else:
return f(x-1)*x
f(5)
120
关键字 def 引入一个函数定义。构成函数体的语句从下一行开始,并且必须缩进。
函数体的第一个语句可以是字符串文字(可选的),这个字符串文字即是函数的文档字符串。有些工具使用文档字符串自动生成在线或印刷文档,或者让用户以交互式的形式浏览代码。在你编写的代码中包含文档字符串是一种很好的做法,所以要养成习惯。
文档字符串的内容和格式的约定:
第一行应该是函数目的的简要概述。为简洁起见,它不应显式声明对象的名称或类型,因为这些可通过其他方式获得(除非名称恰好是描述函数操作的动词)。这一行应以大写字母开头,以句点结尾。
如果文档字符串中有更多行,则第二行应为空白,从而在视觉上将摘要与其余描述分开。后面几行应该是一个或多个段落,描述对象的调用约定,它的副作用等。
可以使用函数的 __doc__
属性或 help() 函数查看函数文档。
help(my_function)
Help on function my_function in module __main__:
my_function()
Do nothing, but document it.
def my_function():
'Do nothing, but document it.'
pass
my_function.__doc__
'Do nothing, but document it.'
# 多行的函数文档
def my_func():
"""Do nothing, but document it.
No, really, it doesn't do anything.
"""
pass
print(my_func.__doc__)
Do nothing, but document it.
No, really, it doesn't do anything.
help(my_func)
Help on function my_func in module __main__:
my_func()
Do nothing, but document it.
No, really, it doesn't do anything.
print(print.__doc__)
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.
函数名之后带一个圆括号,圆括号内,根据形参的类型(详见函数形参),给函数传递相应的实参,即可调用函数,执行函数体中的代码。
函数调用传递的实参分为:位置参数和关键字参数。
*
将可迭代对象的元素拆包传入函数,但元素个数不能多于可接收位置参数的形参个数,除非有接收多个位置参数的可变位置形参。def f(a,b=None,*c,d=None):
print(f'a={a},b={b},c={c},d={d}')
f(*[1,2,3,4,5]) # d 只能接收关键字参数
a=1,b=2,c=(3, 4, 5),d=None
def f(a,b=None,*,c=None):
print(f'a={a},b={b},c={c}')
f(1,2)
f(1,2,3) # c 只能接收关键字参数
a=1,b=2,c=None
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-2-9cc318bcfef7> in <module>
2 print(f'a={a},b={b},c={c}')
3 f(1,2)
----> 4 f(1,2,3)
TypeError: f() takes from 1 to 2 positional arguments but 3 were given
**
将字典里的元素传入函数,但元素个数不能多于可接收关键字参数的形参个数。关键字参数的标识符或字典的键,必须与可接收关键字参数的形参的名称相同,除非有可接收任意关键字参数的可变关键字形参。def f(a,/,b=None,*,c=None):
print(f'a={a},b={b},c={c}')
f(1,c=3,b=2) # a 仅限位置传参
f(a=1,c=3,b=2)
a=1,b=2,c=3
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-3c39aaeac558> in <module>
3
4 f(1,c=3,b=2) # a 仅限位置传参
----> 5 f(a=1,c=3,b=2)
TypeError: f() got some positional-only arguments passed as keyword arguments: 'a'
def f(a,/,b=None,**c):
print(f'a={a},b={b},c={c}')
# a 仅限位置,b 没有对应的名称,因此全部传给 c
f(1,**{'a':1,'d':4,'c':3})
a=1,b=None,c={'a': 1, 'd': 4, 'c': 3}
位置参数必须在关键字参数前面:
def f(a,b=None,**c):
print(f'a={a},b={b},c={c}')
f(b=2,1)
File "<ipython-input-13-59f3b615f9f3>", line 4
f(b=2,1)
^
SyntaxError: positional argument follows keyword argument
位置参数的位置不能传错,关键字参数的则可以任意位置:
def f(a,b=None,/,c=None,**d):
print(f'a={a},b={b},c={c},d={d}')
f(1,2,c=3,d=4)
f(2,1,d=4,c=3,e=5)
a=1,b=2,c=3,d={'d': 4}
a=2,b=1,c=3,d={'d': 4, 'e': 5}
标注并不影响传参规则,但按照标注传参是更明智的做法:
def f(a:int,b:str='b')-> str:
print(a*b)
f(2,'hi')
f(2,3)
hihi
6
lambda 函数由 lambda 表达式创建,表达式的语法为:
lambda parameters: expression
形参 parameters
是可选的,表达式 expression
会在函数调用时被求值并作为返回值返回。
表达式必须显示地确定为一个表达式,而不能像 return 语句那样返回多个表达式(默认为一个元组)。
lambda 表达式会创建一个没有名字的函数,函数不能包含语句或标注,可以像调用函数一样直接调用它。
(lambda x,y: x**y)(2,3)
8
lambda x,y: x**y
<function __main__.<lambda>(x, y)>
# 返回值必须显示地确定为一个表达式
f = lambda x: sum(x),max(x),min(x)
f([2,3,4])
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-5-1652333b2bc4> in <module>
1 # 必须显示地确定为一个表达式
----> 2 f = lambda x: sum(x),max(x),min(x)
3 f([2,3,4])
NameError: name 'x' is not defined
f = lambda x: (sum(x),max(x),min(x))
f([2,3,4])
(9, 4, 2)
lambda 函数通常在以函数作为参数的高阶函数中使用,没有名称,用完即弃。
a = ['2 2', '2 1 ','2 3']
sorted(a,key=lambda x:''.join(x.split()))
['2 1 ', '2 2', '2 3']
list(map(lambda x:''.join(x.split()), a))
['22', '21', '23']
函数定义中使用了 yield 语句,该定义创建的函数是生成器函数。生成器函数通常也直接叫生成器。
当一个生成器函数被调用的时候,它返回一个迭代器,也称为生成器(全称是生成器迭代器,下面所说生成器均指生成器迭代器)。然后通过这个生成器来控制生成器函数的执行。
生成器是一个迭代器,也是一个可迭代对象。但一个生成器生成的 “元素” 只能被使用一次,原因如下:
迭代生成器的时候,生成器函数开始执行,执行到 yield,然后执行被挂起,给生成器的调用者返回 yield 之后的表达式的值。挂起后,所有局部状态都被保留下来,包括局部变量的当前绑定,指令指针,内部求值栈和任何异常处理的状态。
继续迭代生成器,生成器函数从挂起状态继续执行,执行到 yield,然后执行又被挂起,给生成器的调用者返回 yield 之后的表达式的值。
生成器迭代完成时,引发 StopIteration。
在一个生成器函数中,return 语句表示生成器已完成并将导致 StopIteration 被引发。返回值(如果有的话)会被当作一个参数用来构建 StopIteration 并成为 StopIteration.value 属性。
next(g)
0
def f(n):
yield n
g = f(0)
print(f)
print(g)
<function f at 0x000002480120ACA0>
<generator object f at 0x000002480122E040>
next(g) # 迭代结束
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-3-c91425ed1388> in <module>
----> 1 next(g) # 迭代结束
StopIteration:
def f(n):
yield n
n += 1
yield n
n += 1
yield n
# 生成器已完成,后面的不被执行
return 'end'
n += 1
yield n
g = f(0)
while True:
try:
print(next(g))
except StopIteration as s:
print(s.value) # StopIteration.value 属性
break
# 迭代结束,不能再次迭代生成器
next(g)
0
1
2
end
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-10-3ebb4e469fc1> in <module>
19 break
20 # 迭代结束,不能再次迭代生成器
---> 21 next(g)
StopIteration:
yield from
将可迭代对象中的每一项作为生成器的迭代项:
def f(*args):
yield from args
g = f(1,2,3)
next(g),list(g)
(1, [2, 3])
def f(arg):
yield from arg
g = f('123')
print(list(g))
# g 使用结束,再次使用什么也没有,创建了一个空列表
print(list(g))
# 如要再次使用可再创建一个生成器
list(f('123'))
['1', '2', '3']
[]
['1', '2', '3']
异常中断代码块的正常控制流程以便处理 错误 或 其他异常条件 。它是 Python 中的一类对象。一个异常表示一个或一类错误。
异常会在错误被检测到的位置引发,它可以被 当前包围发生错误的代码块 或是 任何直接或间接调用发生错误的代码块的其他代码块 所处理。
Python 解析器会在检测到代码运行错误的时候引发异常。也可以通过 raise 语句显式地引发异常。
异常处理通过 try 语句 来指定。该语句的 finally 子句可被用来指定清理代码,它并不处理异常,而是无论之前的代码是否发生异常都会被执行。
Python 的错误处理采用的是 “终止” 模型:异常处理器可以找出发生了什么问题,并在外层继续执行,但它不能修复错误的根源并重试失败的操作(除非通过从顶层重新进入出错的代码片段)。
当一个异常完全未被处理时,解释器会终止程序的执行,或者返回交互模式。无论是哪种情况,它都会打印栈回溯信息,除非是当异常为 SystemExit 的时候。
异常是通过类实例来标识的。except 子句必须引用实例的类或是其所属的基类。实例可通过处理器被接收,并可携带有关异常条件的附加信息。
在 Python 中,所有异常必须为一个派生自 BaseException 的类的实例。
内置异常类可以被子类化以定义新的异常。鼓励从 Exception 类或它的某个子类而不是从 BaseException 来派生新的异常。
内置异常的类层级结构如下:
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
| +-- ModuleNotFoundError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning
异常处理通过 try 语句(详细语法及使用规则见 try 语句)来实现。
通过 try 语句处理程序已经出现或可能出现异常,使代码能够继续执行,否则异常未被处理,程序终止执行。
例如下列代码要求用户输入有效的整数:
while True:
try:
x = int(input("Please enter a number: "))
break
except ValueError:
print("Oops! That was no valid number. Try again...")
Please enter a number: 3.14
Oops! That was no valid number. Try again...
Please enter a number: 314
try 语句的工作原理如下:
首先执行 try 子句;
如果没有异常发生,则跳过 except 子句并完成 try 语句的执行;
如果在执行 try 子句时发生了异常,则跳过该子句中剩下的部分。然后,如果异常的类型和 except 关键字后面的异常匹配,则执行 except 子句,然后继续执行 try 语句之后的代码;
如果发生的异常和 except 子句中指定的异常不匹配,则将其传递到外部的 try 语句中;如果没有找到处理程序,则它是一个未处理异常,执行将停止并显示异常信息。
一个 try 语句可能有多个 except 子句,以指定不同异常的处理程序,但最多会执行一个处理程序。
处理程序只处理相应的 try 子句中发生的异常。如果发生的异常和 except 子句中的类是同一个类或者是它的基类,则异常和 except 子句中的类是兼容的。如果首先处理了基类,子类不再被处理(子类也被基类处理了):
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
for cls in [B, C, D]:
try:
raise cls()
except D:
print("D")
except C:
print("C")
except B:
print("B")
B
C
D
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
for cls in [B, C, D]:
try:
raise cls()
except B: # 下列都是 B 的子类,不再被处理
print("B")
except C:
print("C")
except D:
print("D")
B
B
B
最后的 except 子句可以省略异常名,以用作通配符。但请谨慎使用,因为以这种方式很容易掩盖真正的编程错误!它还可用于打印错误消息,然后重新引发异常:
import sys
try:
3/0
except ValueError as v:
print(v)
except:
print("Unexpected error:", sys.exc_info()[0])
raise
Unexpected error: <class 'ZeroDivisionError'>
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-13-f0b3e840c5ab> in <module>
2
3 try:
----> 4 3/0
5 except ValueError as v:
6 print(v)
ZeroDivisionError: division by zero
可选的 else 子句,在使用时必须放在所有的 except 子句后面。对于在 try 子句不引发异常时必须执行的代码来说很有用:
try:
f = open('../11_built-in_function/test.txt',
'r',encoding='utf-8')
except OSError:
print('cannot open')
else:
print(len(f.readlines()), 'lines')
f.close()
3 lines
异常处理程序不仅处理 try 子句中遇到的异常,还处理 try 子句中调用(即使是间接地)的函数内部发生的异常。
如果 try 子句中有多个可能的异常,只处理最先引发的:
def f():
return 3/0
try:
f() * int('a')
except ValueError as v:
print(v)
except ZeroDivisionError as z:
print(z)
division by zero
raise 语句 允许强制发生指定的异常。
raise NameError('HiThere')
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-1-72c183edb298> in <module>
----> 1 raise NameError('HiThere')
NameError: HiThere
如果你需要确定是否引发了异常但不打算处理它,则可以使用更简单的 raise 语句形式重新引发异常:
try:
raise NameError('HiThere')
except NameError:
print('An exception flew by!')
raise
An exception flew by!
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-2-bf6ef4926f8c> in <module>
1 try:
----> 2 raise NameError('HiThere')
3 except NameError:
4 print('An exception flew by!')
5 raise
NameError: HiThere
可以通过创建新的异常类来自定义代码执行错误引发的异常。许多标准模块定义了它们自己的异常,以报告它们定义的函数中可能出现的错误。
异常通常应该直接或间接地从 Exception 类派生。定义的异常类,可以执行任何其他类可以执行的任何操作,但通常保持简单,只提供一些属性,这 些属性允许处理程序为异常提取有关错误的信息。
在创建可能引发多个不同错误的模块时,通常的做法是为该模块定义的异常创建基类,并为不同错误条件创建特定异常类的子类。大多数异常都定义为名称以 Error
结尾,类似于标准异常的命名:
class Error(Exception):
"""Base class for exceptions in this module."""
pass
class InputError(Error):
"""Exception raised for errors in the input.
Attributes:
expression -- input expression in which the error occurred
message -- explanation of the error
"""
def __init__(self, expression, message):
self.expression = expression
self.message = message
class TransitionError(Error):
"""Raised when an operation attempts a state transition that's not allowed.
Attributes:
previous -- state at beginning of transition
next -- attempted new state
message -- explanation of why the specific transition is not allowed
"""
def __init__(self, previous, next, message):
self.previous = previous
self.next = next
self.message = message
raise InputError(3/1,'分母不能为 1')
---------------------------------------------------------------------------
InputError Traceback (most recent call last)
<ipython-input-2-d0c6938bc1c4> in <module>
29 self.message = message
30
---> 31 raise InputError(3/1,'分母不能为 1')
InputError: (3.0, '分母不能为 1')
try 语句有另一个可选子句 finally,用于定义必须在所有情况下执行的清理操作(详见 try 语句)。
例如,在 finally 子句中关闭打开的文件:
def read_file():
try:
f = open('../11_built-in_function/test.txt',
encoding='utf-8')
return f.read()
except OSError:
print('不能打开')
finally:
print('执行清理操作')
f.close()
read_file() # 先执行关闭,在执行返回
执行清理操作
'xue.cn\n\n自学是门手艺'
如果 finally 子句中引发了新的异常,清理操作本身无效,则达不到清理目的:
def read_file():
try:
f = open('../11_built-in_function/test.txt',
encoding='utf-8')
return f.read()
except OSError:
print('不能打开')
finally:
print(执行清理操作) # 清理操作引发异常
f.close()
read_file()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-13-af7cdb6d88f0> in <module>
10 f.close()
11
---> 12 read_file() # 先执行关闭,在执行返回
<ipython-input-13-af7cdb6d88f0> in read_file()
7 print('不能打开')
8 finally:
----> 9 print(执行清理操作) # 清理操作引发异常
10 f.close()
11
NameError: name '执行清理操作' is not defined
某些对象(例如文件对象)定义了在不再需要该对象时,要执行的标准清理操作,无论使用该对象的操作是成功还是失败,清理操作都会被执行。此时使用 with 语句允许像文件这样的对象能够以一种确保它们得到及时和正确的清理的方式使用。
with 语句相当于将引发异常情况下的清理操作放到了 except 子句中,正常情况下的清理操作放到了 finally 子句中。详情见 with 语句。
def read_file():
with open('../11_built-in_function/test.txt',
encoding='utf-8') as f:
return f.read()
read_file()
'xue.cn\n\n自学是门手艺'
文件对象是指对外提供面向文件 API 以使用下层资源的对象(带有 read() 或 write() 这样的方法),也被称作流或文件类对象。
有三种类别的文件对象: 原始二进制文件, 缓冲二进制文件 以及 文本文件。三种类别下还有子类别,因创建方式的不同得到不同类别文件对象。它们的接口定义均在 io 模块中。创建文件对象的规范方式是使用 open() 函数。
用户代码直接操作原始流的用法非常罕见。不过,可以通过在禁用缓冲的情况下以二进制模式打开文件来创建原始流:
f = open("test.txt","rb", buffering=0)
f
<_io.FileIO name='test.txt' mode='rb' closefd=True>
缓冲二进制流不执行编码、解码或换行转换。这种类型的流可以用于所有类型的非文本数据(例如图片,视频),并且还可以在需要手动控制文本数据的处理时使用。创建缓冲二进制流的最简单方法是使用 open(),并在模式中指定 ‘b’:
f = open("test.txt","rb")
f
<_io.BufferedReader name='test.txt'>
文本流生成 str 对象。这意味着,无论何时后台存储是由字节组成的,数据的编码和解码都是透明的,并且可以选择转换特定于平台的换行符。创建文本流的最简单方法是使用 open(),可以选择指定编码:
f = open("test.txt",encoding="utf-8")
f
<_io.TextIOWrapper name='test.txt' mode='r' encoding='utf-8'>
所有流对提供给它们的数据类型都很敏感。例如将 str 对象给二进制流的 write() 方法会引发 TypeError。
f = open("test.txt","ab")
f.write('写入内容')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-19-a9efd264aca2> in <module>
1 f = open("test.txt","ab")
----> 2 f.write('写入内容')
TypeError: a bytes-like object is required, not 'str'
内存中的流也可以作为文件对象使用:
import io
f = io.StringIO("some initial text data")
print(f)
f.read()
<_io.StringIO object at 0x000001BE348D2040>
'some initial text data'
f = io.BytesIO(b"some initial binary data: \x00\x01")
print(f)
f.read()
<_io.BytesIO object at 0x000001BE348D3310>
b'some initial binary data: \x00\x01'
open() 函数打开文件,创建流后,会使文件在一段不确定的时间内处于打开状态。这在简单脚本中不是问题,但对于较大的应用程序来说可能是个问题。此时用 close() 方法刷新并关闭流(或直接使用 with 语句打开)是明智的做法。
f = open("test.txt",encoding="utf-8")
print(f.read())
f.close()
为什么要掌握自学能力?
未来还很长。
打开方式不同,会创建不同类型的文件对象(流),不同类型的文件对象,可能有不同的属性或方法。
下列检查或读取内容的属性或方法,是多数文件对象通用的:
f = open('test.txt')
f.readable()
True
read(size=-1) 从对象中读取 size 个字节并将其返回。作为一个便捷选项,如果 size 未指定或为 -1,则返回所有字节直到 EOF。流的位置与读取内容同步,不重设流的位置,内容只能被读取一次。
tell() 返回当前流的位置。
f = open('test.txt',encoding='utf-8')
f.read()
'为什么一定要掌握自学能力?\n未来的日子还很长,\n这世界进步得太快,\n没有自学能力,\n没有未来。'
f = open('test.txt',encoding='utf-8')
f.read(12)
'为什么一定要掌握自学能力'
f.tell()
36
f.read() # 再次读取,将读取剩下未读部分
'?\n未来的日子还很长,\n这世界进步得太快,\n没有自学能力,\n没有未来。'
f.read() # 已经没有内容
''
f.seek(0, 0)
0
f.read() # 从新位置读取
'为什么一定要掌握自学能力?\n未来的日子还很长,\n这世界进步得太快,\n没有自学能力,\n没有未来。'
f = open('test.txt',encoding='utf-8')
f.readline()
'为什么一定要掌握自学能力?\n'
f.readline(2) # 再次读取,将读取剩下未读部分
'未来'
f = open('test.txt',encoding='utf-8')
f.readlines(1)
['为什么一定要掌握自学能力?\n']
f.readlines(10) # 再次读取,将读取剩下未读部分
['未来的日子还很长,\n', '这世界进步得太快,\n']
for line in file: ...
就足够对文件对象进行迭代了,可以不必调用 file.readlines()。f = open('test.txt',encoding='utf-8')
for line in f:
print(line)
为什么一定要掌握自学能力?
未来的日子还很长,
这世界进步得太快,
没有自学能力,
没有未来。
f.closed
False
f.close()
f.close()
f.closed
True
打开方式不同,会创建不同类型的文件对象(流),不同类型的文件对象,可能有不同的属性或方法。
打开模式不同,写入内容的方式也会不同,详见 open() 打开文件。
下列检查或写入内容的属性或方法,是多数文件对象通用的:
f = open('test.txt','a',encoding='utf-8')
f.writable()
True
f = open('test.txt')
f.writable()
f.write('这世界进步得太快,')
---------------------------------------------------------------------------
UnsupportedOperation Traceback (most recent call last)
<ipython-input-1-7bf449cf8958> in <module>
1 f = open('test.txt')
2 f.writable()
----> 3 f.write('这世界进步得太快,')
UnsupportedOperation: not writable
f = open('test.txt','a+',encoding='utf-8')
f.write('\n这世界进步得太快,')
10
f.flush()
f = open('test.txt','a+',encoding='utf-8')
f.writelines(['\n没有自学能力,\n', '没有未来。'])
f.tell() # 流的位置在末尾
137
f.read() # 从末尾读取内容为空
''
f.seek(0, 0) # 重设流的位置为开头
0
f.read()
'为什么一定要掌握自学能力?\n未来的日子还很长,\n这世界进步得太快,\n没有自学能力,\n没有未来。'
f.closed
False
f.close()
f.close()
f.closed
True
模块是 Python 代码的一种组织单位,也是一种对象。各模块具有独立的命名空间,可包含任意 Python 对象。
一个 .py
文件是一个模块;一个文件夹是一个模块(包);文件夹(包)中还可以再有 .py
文件(子模块)和文件夹(子包)。例如 内置模块 random,和第三方包 pandas。
文件夹中包含一个 __init__.py
文件的包是常规包;无 __init__.py
文件的是命名空间包,仅被用作子包的容器。
模块无论是用 Python、C 还是别的语言实现均可。
import random, pandas
type(random), type(pandas)
(module, module)
所有包都是模块,但并非所有模块都是包。或者换句话说,包只是一种特殊的模块。
可以使用属性 __packge__
查看包名,如果只是模块不是包,该属性为空字符串。
__name__
属性是模块的名字。
特别地,主模块(你正在运行代码的当前模块)的 __packge__
属性总是 None;__name__
属性总是 '__main__'
(__main__
是一个在解释器启动时直接初始化的特殊模块),这可以控制当前模块能够执行,而导入到其他模块不能被执行的代码,然后用来测试当前模块。
random.__package__, pandas.__package__
('', 'pandas')
print(__package__)
None
random.__name__, pandas.__name__
('random', 'pandas')
__name__
'__main__'
a = 3 + 2 - 5
def f():
print(a+1)
print(a)
if __name__ == '__main__':
# 以下代码导入其他模块不会执行
print(a == 0)
0
True
使用 import 语句将其他模块导入当前模块;使用属性表示法调用模块中的属性。
import pandas as pd
pd.core
<module 'pandas.core' from 'C:\\ProgramData\\Anaconda3\\lib\\site-packages\\pandas\\core\\__init__.py'>
pd.core.series.Series
pandas.core.series.Series
还可以以脚本的方式执行不属于包的模块(此时 __name__
属性为 "__main__"
)。
import this
this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
<module 'this' from 'C:\\ProgramData\\Anaconda3\\lib\\this.py'>
# %run 是 jupyter 的魔法命令,在终端使用 python 命令
# F:\anaconda\lib\this.py 根据自己电脑的路径调整
%run F:\anaconda\lib\this.py
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
创建一个模块非常简单,有两种方式:
创建一个 .py
文件,即可创建一个模块;
创建一个文件夹,则该文件夹也是一个模块(包)。
模块中可以无任何内容。但模块是用来组织代码,实现处理各类问题或完成各种功能的,这更便于应用或开发。例如正则模块 re,科学计算库 pandas 等。
创建一个文件夹,如果文件夹中包含一个 __init__.py
模块,则该文件夹是一个常规包;否则是一个命名空间包。包中还可以再创建子包或子模块。
__init__.py
文件中可以无任何内容,但因为当一个常规包被导入时,这个 __init__.py
文件会隐式地被执行,所以通常用来写入一些导入包即可执行的代码,或导入子包,或导入子包中模块的属性等,从而可以直接调用某些属性,例如 pandas 包的文档描述属性 __doc__
和 DataFrame 数据结构。
import folder # 创建的空文件夹
folder
<module 'folder' (namespace)>
import pandas as pd
print(pd.__doc__)
pandas - a powerful data analysis and manipulation library for Python
=====================================================================
**pandas** is a Python package providing fast, flexible, and expressive data
structures designed to make working with "relational" or "labeled" data both
easy and intuitive. It aims to be the fundamental high-level building block for
doing practical, **real world** data analysis in Python. Additionally, it has
the broader goal of becoming **the most powerful and flexible open source data
analysis / manipulation tool available in any language**. It is already well on
its way toward this goal.
Main Features
-------------
Here are just a few of the things that pandas does well:
- Easy handling of missing data in floating point as well as non-floating
point data.
- Size mutability: columns can be inserted and deleted from DataFrame and
higher dimensional objects
- Automatic and explicit data alignment: objects can be explicitly aligned
to a set of labels, or the user can simply ignore the labels and let
`Series`, `DataFrame`, etc. automatically align the data for you in
computations.
- Powerful, flexible group by functionality to perform split-apply-combine
operations on data sets, for both aggregating and transforming data.
- Make it easy to convert ragged, differently-indexed data in other Python
and NumPy data structures into DataFrame objects.
- Intelligent label-based slicing, fancy indexing, and subsetting of large
data sets.
- Intuitive merging and joining data sets.
- Flexible reshaping and pivoting of data sets.
- Hierarchical labeling of axes (possible to have multiple labels per tick).
- Robust IO tools for loading data from flat files (CSV and delimited),
Excel files, databases, and saving/loading data from the ultrafast HDF5
format.
- Time series-specific functionality: date range generation and frequency
conversion, moving window statistics, date shifting and lagging.
# 直接调用子包 core 中模块 frame 的属性 DataFrame
pd.DataFrame
pandas.core.frame.DataFrame
每一个 .py
文件模块,都是 Python 的可执行文件。文件内容可以为空,但执行什么也不发生。
你可以在某些编辑工具里打开文件执行,也可以在命令行使用 python 文件路径
或 python -m 模块
的方式执行。这些方式都是主模块中直接执行文件。
主模块(你正在运行代码的当前模块)的 __name__
属性总是 '__main__'
(__main__
是一个在解释器启动时直接初始化的特殊模块),因此直接执行文件,if __name__ == '__main__':
语句下的代码一定会被执行,而如果导入到其他模块则不会。
__name__
'__main__'
下面举例说明:
当前文件路径下,有一个 myfile
的包,包里有 space.py
和 mycode.py
模块,内容如下:
# space.py 为空
# mycode.py 的内容, 在此源码直接执行
_a = '自学'
def __f():
print(_a)
msg1 = '我是mycode模块中的代码'
print(msg1)
if __name__ == '__main__':
msg2 = '我是导入其他模块不会执行的代码'
print(msg2)
我是mycode模块中的代码
我是导入其他模块不会执行的代码
# 导入不会执行 __name__ == '__main__' 下面的代码
from myfile import mycode
print(mycode.msg1)
mycode.msg2
我是mycode模块中的代码
我是mycode模块中的代码
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_21344/86150704.py in <module>
2 from myfile import mycode
3 print(mycode.msg1)
----> 4 mycode.msg2
AttributeError: module 'myfile.mycode' has no attribute 'msg2'
命令行直接执行模块效果同上。下面使用命令执行(%run
是 jupyter 的魔法命令,终端请改为 python
):
# 文件路径必须带 .py,可以是相对或绝对路径
%run myfile/space.py
%run myfile/mycode.py
我是mycode模块中的代码
我是导入其他模块不会执行的代码
import warnings # 忽略警告
warnings.filterwarnings("ignore")
# 模块可以使用属性表示法,但不能有 .py
%run -m myfile.mycode
我是mycode模块中的代码
我是导入其他模块不会执行的代码
导入操作使用 import 语句,详细的语法规则查看 import 导入语句。
import ...
只能导入模块:import random as r, pandas.core as pc
r, pc
(<module 'random' from 'F:\\anaconda\\lib\\random.py'>,
<module 'pandas.core' from 'F:\\anaconda\\lib\\site-packages\\pandas\\core\\__init__.py'>)
# 导入方法报错
import random.randint
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
<ipython-input-2-8d4ecd1fe339> in <module>
1 # 导入方法报错
----> 2 import random.randint
ModuleNotFoundError: No module named 'random.randint'; 'random' is not a package
from ... import ...
从模块中导入子模块,类,函数等:from pandas import core
core
<module 'pandas.core' from 'F:\\anaconda\\lib\\site-packages\\pandas\\core\\__init__.py'>
from pandas import DataFrame as df
df
pandas.core.frame.DataFrame
from random import randint
randint
<bound method Random.randint of <random.Random object at 0x000001E44ED52020>>
from math import pi
pi
3.141592653589793
from ... import *
将导入模块中所有的公有属性:当前文件路径下,有一个 myfile
的包,包里有 space.py
,mycode.py
和 __init__.py
等模块,__init__.py
内容为空,则 myfile
包里的模块都不是它的属性,无法导入
import myfile
dir(myfile)
['__builtins__',
'__cached__',
'__doc__',
'__file__',
'__loader__',
'__name__',
'__package__',
'__path__',
'__spec__']
from myfile import *
mycode
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_21108/1508979804.py in <module>
1 from myfile import *
----> 2 mycode
NameError: name 'mycode' is not defined
如果在文件 __init__.py
中我们定义了属性 __all__
,从包 myfile
导入则只能导入该属性中的列出名称。
# 修改 myfile/__init__.py
__all__ = ['mycode','xue']
from myfile import *
mycode
我是mycode模块中的代码
<module 'myfile.mycode' from 'D:\\Jupyter\\jupyter\\jupyter-python\\15_module\\myfile\\mycode.py'>
在文件 myfile/mycode.py
中,以下划线打头的属性名,从模块 mycode.mycode
导入时都不可导入。
# myfile/mycode.py
_a = '自学'
def __f():
print(_a)
msg1 = '我是mycode模块中的代码'
print(msg1)
if __name__ == '__main__':
msg2 = '我是导入其他模块不会执行的代码'
print(msg2)
from myfile.mycode import *
_a
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_9512/1217097939.py in <module>
1 from myfile.mycode import *
----> 2 _a
NameError: name '_a' is not defined
__f
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_9512/3733874203.py in <module>
----> 1 __f
NameError: name '__f' is not defined
通常情况下不应使用这个功能,因为它在解释器中引入了一组未知的名称,而它们很可能会覆盖一些你已经定义过的名称。而且会导致代码的可读性很差。
# 其他方式则可以导入
from myfile.mycode import __f
print(__f)
del __f
<function __f at 0x00000157E4BA53A0>
存在相对导入代码的模块,通常是不能直接执行的。因为直接执行,解释器认为该模块即为顶级模块,属性 __package__
的值为 None。
print(__package__)
None
但可以使用 python -m 模块
命令直接执行。
例如,当前文件路径下,文件 myfile/test.py
中相对导入的代码可以使用 python -m 模块
命令直接执行,因为该命令将属性 __package__
重新设置为顶级模块的名称:
# xue.py 模块在 myfile 包中,内容是 “msg = '自学是门手艺'”
# myfile/test.py 的内容
from . import xue
print(xue.msg)
print(__package__)
%run -m myfile.test
自学是门手艺
myfile
模块导入之后,即可使用属性表示法调用模块中属性:
import random, math
random.randint, math.pi
(<bound method Random.randint of <random.Random object at 0x000002811CF98C80>>,
3.141592653589793)
面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。它把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式。
例如生活中我们会遇到各种数字及其运算,于是计算机科学家们就把数字抽象出来,成为一类对象。它们有别于其他事物(例如文字,图像)的特征,有自己的一套运算、操作方法。
Python 中的数字当然非常类似数学中的数字,但也受限于计算机中的数字表示方法。
为了方便,又把数字这一类对象,基本分成了整数,浮点数,复数三类对象。这对应 Python 中的 int,float,comlex 三种数字类型,三种数字类型下具体的整数,浮点数,复数也是对象。它们有共同的特征和计算方法,也有各自特有的特征和方法。例如都可以进行加减乘除,只有整数有按位运算。
整数中,0 和 1 的特殊性,又使得可以将整数类中再分出一类对象,布尔类型对象。布尔类型的对象,只有两个对象,True 和 False。
从数字类对象,到三类数字对象,到布尔类对象,到具体的数字对象以及 True 和 False 对象,层层细分,最终是具体的一个个对象,它们都是对象。这也是为什么称 Python 一切皆对象的原因。
类似地,对数据,因为要实现的目的不同,将装数据的 “容器” 分为字符串,列表,元组,集合,字典等类型的对象。
函数抽象出函数对象,模块又抽象出模块对象…… 甚至连空都是对象(None)。
具体的对象,称为实例,它归属于某个类。而所有的类,又都是 object 对象的子类。各种类(类型),又统一归为类型对象(type)。
type(1), isinstance(1,int) # 1 是 int 类的实例
(int, True)
issubclass(int,object) # int 类是 object 的子类
True
type(int), isinstance(int,type) # int 是 type 的实例
(type, True)
按照面向对象的思想,我们可以定义一个 “人” 类对象,然后很方便地给这个 “人” 加上现有的各种函数,类,以及模块的功能,造出更多更多有各种特异功能的 “人”。这是不是非常伟大的设计思想呢?
类是用来创建用户定义对象的模板,是抽象的对象(类对象)。例如我们说鱼类,指的就是一类抽象的对象,而具体到武昌鱼,鲈鱼,鲫鱼…… 就是具体的对象。
定义了一个类,就可以用这个模块来创建它的具体对象(实例)。类定义的详细语法规则见 class 定义类。
创建一个类,需要继承另一个类。新创建的类是子类,继承的类是基类。如不指定,创建类默认继承自所有类的基类 object。
下面是一个没有任何自定义属性的简单类:
class A:
pass
A
__main__.A
type(A)
type
A.__bases__ # 查看基类
(object,)
继承一个指定的类,可以对它进行定制化开发。需要注意参数 self, 它是约定名称(可自定义但不推荐),它就代表类创建的实例对象自身。
例如创建一个自定义的列表类,增加 add() 方法:
class Mylist(list):
def add(self,value):
self.append(value)
lst = Mylist('123') # 创建实例赋值给 lst
lst.add(4) # lst 调用 add 方法,self 参数就是 lst
lst
['1', '2', '3', 4]
或者自定义一个字典,当访问的键不存在时,不报错,而是返回 None(__missing__()
是用来定义字典子类时找不到键如何处理的魔法方法):
class Mydict(dict):
def __missing__(self, key):
return
d = Mydict(a=1,b=2)
d, d['c']
({'a': 1, 'b': 2}, None)
我们也可以自定义任意的类,其中 __init__()
方法是创建实例时用来初始化实例对象的魔法方法,可以用它来增加一些自定义属性。没有该方法,创建实例时,将自动调用基类的该方法完成初始化。
例如定义一个 “人” 类:
class Person:
'这是人类'
# 定义人的属性
def __init__(self, name):
self.name = name
self.ears = '耳朵'
self.brain = '大脑'
self.hands = '双手'
# 人有生活
def live(self):
print(f'{self.name}用{self.ears}'
'听着音乐,'
'享受美好生活。')
# 还有工作
def work(self):
print(f'{self.name}用{self.brain}和'
f'{self.hands}'
'勤劳致富。')
# 造人
xm = Person('小明')
xz = Person('小张')
xm.live() # 小明在享受生活
xz.work() # 小张在努力工作
小明用耳朵听着音乐,享受美好生活。
小张用大脑和双手勤劳致富。
实例是调用类对象创建的具体对象。例如调用内置类型 int,创建的所有整数,都是 int 类的实例。可通过内置函数 isinstance() 进行实例检查。
int('1')
1
isinstance(1,int)
True
Python 中所有的实例对象,都是 object 的实例。所有的类都是 object 的子类,也被视为 object 的实例;所有的类也被视为默认的元类(创建类的类)type 的实例。
如果一个实例对象应该视为某个类的实例,可以通过魔法方法 __instancecheck__()
来重载 isinstance() 函数,自定义实例检查行为。
isinstance(1,object), isinstance([],object)
(True, True)
isinstance(int,object)
True
isinstance(int,type)
True
下面定义一个 “人” 类,来对实例进行说明:
class Person:
'这是人类'
# 定义人的属性
def __init__(self, name):
self.name = name
self.ears = '耳朵'
self.brain = '大脑'
self.hands = '双手'
# 人有生活
def live(self):
print(f'{self.name}用{self.ears}'
'听着音乐,'
'享受美好生活。')
# 还有工作
def work(self):
print(f'{self.name}用{self.brain}和'
f'{self.hands}'
'勤劳致富。')
# 造人
xm = Person('小明')
xz = Person('小张')
上述 “人” 类对象 Person 是类对象,调用类对象创建的 xm 和 xz,是两个具体的 “人”,是实例对象。
Person
__main__.Person
xm
<__main__.Person at 0x24cf9ef6d68>
xz
<__main__.Person at 0x24cf9ef6d30>
isinstance(xm, Person), isinstance(xz, Person)
(True, True)
isinstance(Person, object), isinstance(Person, type)
(True, True)
对象是 Python 中对数据的抽象。Python 程序中的所有数据都是由对象或对象间关系来表示的。
例如计算 x + y
就有对象 x
和 y
,+
其实是调用了 __add__
方法对象。
[1,2] + [3,4]
[1, 2, 3, 4]
list.__add__
<slot wrapper '__add__' of 'list' objects>
[1,2].__add__([3,4])
[1, 2, 3, 4]
每个对象都有各自的编号、类型和值。一个对象被创建后,它的编号就绝不会改变,可以将其理解为该对象在内存中的地址。
id([1,2]), type([1,2]) # 实例对象 [1,2] 的编号 和 类型
(2229938322504, list)
id(list), type(list) # 类对象 list 的编号 和 类型
(140736641645872, type)
对象的值在 Python 中是一个相当抽象的概念:
# 列表对象 [1,2] 和类对象 list
# 是两个不同对象,值是不相等的
[1,2] == list
False
具有固定值的对象为不可变对象,例如数字,字符串,元组(包含的对象集不可变),相等的两个值,可能会也可能不会指向同一个对象,看具体实现。
# 元组的对象集固定不可变
t = ([1,2],(3,4))
print(id(t[0]),id(t[1]),t)
del t[0][:]
print(id(t[0]),id(t[1]),t)
2229937078536 2229937013960 ([1, 2], (3, 4))
2229937078536 2229937013960 ([], (3, 4))
# 同一个对象 1
print(id(1))
print(id(1))
140736642126656
140736642126656
# 两个不同对象 1000
print(id(1000))
print(id(1000))
2229938479344
2229938479248
对象的编号保持不变,可以改变值的对象为可变对象。对于可变对象,分别创建两个相等的值,一定是不同对象。
# 可变对象 a,值改变了还是 a
a = [1,2]
print(id(a), a)
del a[:]
print(id(a), a)
2229937082056 [1, 2]
2229937082056 []
# 类对象 A,增加属性 a 还是 A
class A:pass
print(id(A), A)
A.a = 0
print(id(A), A)
2229917928424 <class '__main__.A'>
2229917928424 <class '__main__.A'>
a = []
b = []
print(id(a))
print(id(b))
a == b
2229937416840
2229937416648
True
类或函数对象的哈希值基于其 id,创建两个看起来完全一样的类或函数,id 是不一样的,而可哈希对象必须具有相同的哈希值,比较结果才会相同。
def f():pass
print(id(f))
a = f
def f():pass
print(id(f))
b = f
a == b
2229938263992
2229938264128
False
名称(标识符)用于指代对象。当名称被绑定到一个对象时,对该名称求值将返回相应对象。当名称未被绑定时,尝试对其求值将引发 NameError 异常。Python 的保留字或称关键字是特殊的名称,不可被用作普通名称,例如不可用做变量名,函数名,模块名。
# 将 1 绑定名称 a
a = 1
a
1
# 将自定义类对象绑定到名称 A
class A:
pass
A
__main__.A
# 将模块 random 绑定到名称 r
import random as r
r
<module 'random' from 'F:\\anaconda\\lib\\random.py'>
# 迭代的每一项循环绑定到名称 i
for i in 'xue':
display(i)
i
'x'
'u'
'e'
'e'
# 未绑定的名称 m
m
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-4-2469ef96c490> in <module>
1 # 未绑定的名称 m
----> 2 m
NameError: name 'm' is not defined
help('keywords') # 保留字
Here is a list of the Python keywords. Enter any keyword to get more help.
False class from or
None continue global pass
True def if raise
and del import return
as elif in try
assert else is while
async except lambda with
await finally nonlocal yield
break for not
False = 0
File "<ipython-input-9-223dbc74e028>", line 1
False = 0
^
SyntaxError: cannot assign to False
检查一个名称是否有效可用字符串方法 str.isidentifier():
'for'.isidentifier()
True
'my_name'.isidentifier()
True
'函数'.isidentifier()
True
普通名称命名规则:
数字一 = 1
数字一
1
def 函数():
pass
函数
<function __main__.函数()>
命名模式以下划线字符打头和结尾,有特殊含义的名称(*
代表任意数量可用名称字符):
_*
不会被 from module import *
导入。特殊标识符 _
在交互式解释器中被用来存放最近一次求值结果;它保存在 builtins 模块中。当不处于交互模式时,_
无特殊含义也没有预定义。
__*__
系统定义的名称,这些名称是由解释器及其实现(包括标准库)定义的特殊属性和方法名称。未来的 Python 版本中还将定义更多此类名称。任何情况下任何不遵循文档所显式指明的 __*__
名称使用方式都可能导致无警告的错误。
__*
类的私有名称。这种名称在类定义中使用时,会以一种混合形式重写以避免在基类及派生类的 “私有” 属性之间出现名称冲突。例如,出现在一个名为 Ham
的类中的名称 __spam
会被转换为 _Ham__spam
。如果类名仅由下划线组成,则不会进行转换。
b = 100
b
100
_
100
dir(object)
['__class__',
'__delattr__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__']
class B:
__b = 0
dir(B)
['_B__b',
'__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__']
del 语句可删除名称绑定:
c = 3
print(f'c={c}')
del c
c
c=3
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-23-5ba97d2f3254> in <module>
2 print(f'c={c}')
3 del c
----> 4 c
NameError: name 'c' is not defined
Python 中绑定对象的名称即为变量。
人们称呼模块、类、函数和方法对象的名称时,习惯直接指代对象本身,而不是把它们当作变量,例如 random,int,print 等,当将它们绑定到另外的名称时,才称新名称为变量(或化名)。
# 函数名称 f 绑定自定义函数对象
def f(x, func):
print(func(x))
a = '1231' # 变量 a
b = [int,list,set] # 变量 b
c = f # 名称 f 起别名 c
for i in b: # 变量 b 中的项循环赋值给变量 i
c(a,i)
1231
['1', '2', '3', '1']
{'3', '1', '2'}
如果名称绑定在一个代码块中,则为该代码块的局部变量,除非声明为 nonlocal 或 global。
如果名称绑定在模块层级,则为全局变量。(模块代码块的变量既为局部变量又为全局变量。)
如果变量在一个代码块中被使用但不是在其中定义,则为自由变量。
# 第一个代码块中全局变量 n
n = 100
# 第二个代码块
# random 模块中的全局变量 randint,
# 在此为局部变量,引用后赋值给全局变量 r
import random
r = random.randint
# 第三个代码块中 x 为局部变量
# n 和 r 不在该代码块中定义,在该代码块为自由变量
def f(x):
print(r(x,n))
f(1)
22
如果代码块中定义了一个局部变量,则其作用域包含该代码块。如果定义发生于函数代码块中,则其作用域会扩展到该函数所包含的任何代码块,除非有某个被包含代码块引入了对该名称的不同绑定。
m = 0
n = 1 # 全局变量 n
def f():
n = 2 # 局部变量 n
print(m,n)
f()
0 2
改变变量作用域,详见 global 语句 和 nonlocal 语句。
类变量和实例变量:
self.name
命名的变量为实例变量,类不能访问。class A:
a = 1 # 类变量
def __init__(self):
self.a = 100 # 实例变量
self.b = 2
a = A()
A.a, a.a, a.b
(1, 100, 2)
A.b # 类 A 不能访问它的实例的变量 b
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-11-f92f3bcfde9d> in <module>
----> 1 A.b # 类 A 不能访问它的实例的变量 b
AttributeError: type object 'A' has no attribute 'b'
属性指关联到一个对象的值,可以使用点号表达式通过其名称来引用。
可以使用 dir() 函数查看任意对象的属性。
如果属性是可调用对象(例如类,函数,方法等),引用之后可直接调用,也可先赋值给变量再调用。
# 查看 list 对象的属性
dir(list)
['__add__',
'__class__',
'__contains__',
'__delattr__',
'__delitem__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getitem__',
'__gt__',
'__hash__',
'__iadd__',
'__imul__',
'__init__',
'__init_subclass__',
'__iter__',
'__le__',
'__len__',
'__lt__',
'__mul__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__reversed__',
'__rmul__',
'__setattr__',
'__setitem__',
'__sizeof__',
'__str__',
'__subclasshook__',
'append',
'clear',
'copy',
'count',
'extend',
'index',
'insert',
'pop',
'remove',
'reverse',
'sort']
# 通过名称 __add__ 引用属性
list.__add__
<slot wrapper '__add__' of 'list' objects>
# 直接调用属性
list.__add__([1,2],[3,4])
[1, 2, 3, 4]
# 赋值给变量再调用
la = list.__add__
la([1,2],[3,4])
[1, 2, 3, 4]
有时也只将具体的值称为属性从而与抽象的值(类,函数,方法等对象的值)区分开来。犹如将一个人有身体和四肢的属性和这个人会唱歌跳舞的属性区分开来。
import pandas as pd
pd.Series # pandas 模块的属性 Series 类
pandas.core.series.Series
import math
math.pi # math 模块的属性圆周率
3.141592653589793
class A:
a = 1
def f(self):
print(self)
a = A()
A.a, a.a # 类 A 及其实例的数据属性 a
(1, 1)
A.f, a.f # 类 A 及其实例的方法属性 f
(<function __main__.A.f(self)>,
<bound method A.f of <__main__.A object at 0x000001B569DC0860>>)
# 方法属性的等价调用
# 实例直接调用,第一个参数 self 就是它自身
a.f()
# 类直接调用,则需要传入实例作为参数
A.f(a)
<__main__.A object at 0x000001B569DC0860>
<__main__.A object at 0x000001B569DC0860>
属性名以一个下划线开头的属性应该视为 “私有” 属性,但可以直接访问。
属性名以两个下划线开头,非两个下划线结尾的属性,在模块中视为 “私有” 属性,但可以直接访问;在类中属于私有属性,这种名称在类定义中使用时,会以一种混合形式重写以避免在基类及派生类的 “私有” 属性之间出现名称冲突。类的私有属性并非不可访问(使用重写名称可访问),全靠自觉。
class A:
_a = 1
def __f():
pass
dir(A)
['_A__f',
'__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'_a']
A._a
1
A._A__f
<function __main__.A.__f()>
方法指在类内部定义的函数。但并不严格要求一定要在类内部定义。
def f(self):
pass
class A:
f = f
A().f
<bound method f of <__main__.A object at 0x00000290DC56E198>>
下列方法看起来是模块中的函数,其实是模块中,类实例方法重新赋值的名称:
from random import randint
type(randint)
method
import random
# randint 完整路径
random.Random.randint
# 例如重新赋值后即可直接调用
r = random.Random()
randint = r.randint
randint(0,3)
2
普通方法(第一个参数通常命名为 self)如果作为该类的实例的一个属性来调用,方法将会获取实例对象作为其第一个参数。
# list 类的方法 append
help('list.append')
Help on method_descriptor in list:
list.append = append(self, object, /)
Append object to the end of the list.
# list 的实例 [] 调用,
# 方法将会获取实例对象 [] 作为其第一个参数
a = []
a.append(1)
a
[1]
# 等价于
a = []
list.append(a,1)
a
[1]
类方法(第一个参数通常命名为 cls)则无论是类或是实例调用,方法都将获取类对象作为其第一个参数。类方法定义详见 classmethod 封装函数为类方法。
class A:
@classmethod
def f(cls,x):
print(cls,x)
print(f'A = {A}')
A.f('类方法')
A().f('类方法')
A = <class '__main__.A'>
<class '__main__.A'> 类方法
<class '__main__.A'> 类方法
静态方法则不会接收隐式的第一个参数。调用它需要正常传递参数。静态方法详见 staticmethod 封装函数为静态方法。
class A:
@staticmethod
def in_print(value):
print(value)
a = A()
a.in_print('静态方法')
A.in_print('静态方法')
静态方法
静态方法
特殊方法(也称魔术方法):一种由 Python 隐式调用的方法,用来对某个类型执行特定操作例如相加等等。这种方法的名称的首尾都为双下划线。可以通过方法重载,对某个类型定义特定操作。
# 1 + 2 操作其实是隐式调用了 __add__
1 + 2
3
(1).__add__(2)
3
# 列表没有 “-” 操作符,自定义一个
class Mlist(list):
def __sub__(self, other):
return list(set(self) - set(other))
a = Mlist('123')
b = Mlist('13')
a, b, a - b
(['1', '2', '3'], ['1', '3'], ['2'])
命名空间是存放变量的场所。命名空间有局部、全局和内置的,还有对象中的嵌套命名空间。不同命名空间中的变量没有关系。
命名空间通过防止命名冲突来支持模块化。例如,函数 builtins.open 与 os.open 可通过各自的命名空间来区分。
# 函数的局部命名空间,在函数调用时创建
def f():
x = '函数 f 命名空间中的变量 x'
print(x)
# 全局命名空间
x = '全局命名空间中的变量 x'
# 调用函数 f,与全局命名空间中的 x 无关
f()
函数 f 命名空间中的变量 x
# 模块 random 导入创建它自己的局部命名空间
import random
# 定义一个全局变量 randint
def randint():
print('全局 randint')
# random 局部命名空间中的 randint
# 与全局变量 randint 无关
randint()
random.randint(0,3)
全局 randint
1
# 上述定义的变量 f, x, randint,导入的变量 random,
# 都存放在了当前全局命名空间中
f, x, random, randint
(<function __main__.f()>,
'全局命名空间中的变量 x',
<module 'random' from 'C:\\ProgramData\\Anaconda3\\lib\\random.py'>,
<function __main__.randint()>)
内置命名空间是在 Python 解释器启动时创建,存放的变量包括内置函数、异常等。
# 全局命名空间中定义变量 str,
# 将屏蔽内置命名空间中的 str
def str(x):
return f'x = {x}'
str(123)
'x = 123'
# 但可以在 builtins 中继续调用
import builtins
builtins.str(123)
'123'
递归函数,每次递归调用,都会有一个新的命名空间。
def f(x):
if x > 0:
print(f'x={x}调用,x-1={x-1}继续调用')
if x == 0:
print(f'x={x},调用结束')
else:
# 以 x-1 作为参数调用函数 f
return f(x-1)
f(3)
x=3调用,x-1=2继续调用
x=2调用,x-1=1继续调用
x=1调用,x-1=0继续调用
x=0,调用结束
嵌套的命名空间:
a = '全局变量 a'
class A:
a = '类变量 a'
def f(self):
a = '函数局部变量 a'
return a
print(a)
print(A.a)
print(A().f())
全局变量 a
类变量 a
函数局部变量 a
作用域定义了一个代码块中名称的可见性。如果代码块中定义了一个局部变量,则其作用域包含该代码块。如果定义发生于函数代码块中,则其作用域会扩展到该函数所包含的任何代码块,除非有某个被包含代码块引入了对该名称的不同绑定。
当一个名称在代码块中被使用时,会由包含它的最近作用域来解析。对一个代码块可见的所有这种作用域的集合称为该代码块的环境。
一个作用域是一个 命名空间 可直接访问的 Python 程序的文本区域。这里的 “可直接访问” 意味着对名称的非限定引用(限定引用指点号表达式例如 math.pi)会尝试在命名空间中查找名称。
# 全局变量作用域为当前模块
a = '全局变量'
def f():
# print 内置名称作用域包含全局
print(f'print 函数的命名空间可以访问:{a}')
return f'f 的命名空间可以访问:{a}'
print(a)
print(f())
全局变量
print 函数的命名空间可以访问:全局变量
f 的命名空间可以访问:全局变量
# 全局变量作用域为当前模块
# 但被包含命名空间引入了同名的局部变量
a = '全局变量'
def f():
# f 中定义的局部变量
# 作用域为函数内部
a = '局部变量'
print(f'print 函数的命名空间可以访问:{a}')
return f'f 的命名空间可以访问:{a}'
print(a)
print(f())
全局变量
print 函数的命名空间可以访问:局部变量
f 的命名空间可以访问:局部变量
虽然作用域是静态地确定的,但它们会被动态地使用。嵌套作用域的搜索顺序:
# 搜索最内部作用域名称 str
# 屏蔽上层作用域
def f():
str = 0
def f1():
str = 1
return str
return f1()
f(), str
(1, str)
# 搜索最近封闭作用域名称 str
# 屏蔽上层作用域
def f():
str = 0
def f1():
return str
return f1()
f(), str
(0, str)
# 搜索当前模块作用域名称 str
# 屏蔽上层作用域
str = '当前模块str'
def f():
def f1():
return str
return f1()
f()
'当前模块str'
# 搜索最外面作用域名称 str
# 删除前面对 str 的绑定
del str
# 注意,运行多次会将内置名称 str 都删除
def f():
def f1():
return str
return f1()
f()
str
可见,当前模块中的全局名称,最好不要和内置名称相同,它会屏蔽掉内置名称,从而不可以直接使用内置功能。内置名称如下:
import builtins
dir(builtins)
['ArithmeticError',
'AssertionError',
'AttributeError',
'BaseException',
'BlockingIOError',
'BrokenPipeError',
'BufferError',
'BytesWarning',
'ChildProcessError',
'ConnectionAbortedError',
'ConnectionError',
'ConnectionRefusedError',
'ConnectionResetError',
'DeprecationWarning',
'EOFError',
'Ellipsis',
'EnvironmentError',
'Exception',
'False',
'FileExistsError',
'FileNotFoundError',
'FloatingPointError',
'FutureWarning',
'GeneratorExit',
'IOError',
'ImportError',
'ImportWarning',
'IndentationError',
'IndexError',
'InterruptedError',
'IsADirectoryError',
'KeyError',
'KeyboardInterrupt',
'LookupError',
'MemoryError',
'ModuleNotFoundError',
'NameError',
'None',
'NotADirectoryError',
'NotImplemented',
'NotImplementedError',
'OSError',
'OverflowError',
'PendingDeprecationWarning',
'PermissionError',
'ProcessLookupError',
'RecursionError',
'ReferenceError',
'ResourceWarning',
'RuntimeError',
'RuntimeWarning',
'StopAsyncIteration',
'StopIteration',
'SyntaxError',
'SyntaxWarning',
'SystemError',
'SystemExit',
'TabError',
'TimeoutError',
'True',
'TypeError',
'UnboundLocalError',
'UnicodeDecodeError',
'UnicodeEncodeError',
'UnicodeError',
'UnicodeTranslateError',
'UnicodeWarning',
'UserWarning',
'ValueError',
'Warning',
'WindowsError',
'ZeroDivisionError',
'__IPYTHON__',
'__build_class__',
'__debug__',
'__doc__',
'__import__',
'__loader__',
'__name__',
'__package__',
'__spec__',
'abs',
'all',
'any',
'ascii',
'bin',
'bool',
'breakpoint',
'bytearray',
'bytes',
'callable',
'chr',
'classmethod',
'compile',
'complex',
'copyright',
'credits',
'delattr',
'dict',
'dir',
'display',
'divmod',
'enumerate',
'eval',
'exec',
'filter',
'float',
'format',
'frozenset',
'get_ipython',
'getattr',
'globals',
'hasattr',
'hash',
'help',
'hex',
'id',
'input',
'int',
'isinstance',
'issubclass',
'iter',
'len',
'license',
'list',
'locals',
'map',
'max',
'memoryview',
'min',
'next',
'object',
'oct',
'open',
'ord',
'pow',
'print',
'property',
'range',
'repr',
'reversed',
'round',
'set',
'setattr',
'slice',
'sorted',
'staticmethod',
'str',
'sum',
'super',
'tuple',
'type',
'vars',
'zip']
直接调用类对象,即可创建该类的实例对象。
int() # 调用 int 类
0
list('123') # 传参调用 list 类
['1', '2', '3']
class A:
def __init__(self, name):
self.name = name
def __repr__(self):
return self.name
A('实例1'), A('实例2') # 调用自定义类
(实例1, 实例2)
实例对象是由特殊方法 __new__()
创建,__init__()
定制完成。两个方法是隐式地完成创建和定制的,当然也可以显式地创建并定制。
class A:
def __init__(self):
self.name = '实例'
A # 类对象 A
__main__.A
# 显式地创建类 A 的一个实例 a
a = object.__new__(A)
a
<__main__.A at 0x20d23e95d30>
# 未初始化,无属性
a.name
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-36-b3a4d04d98fc> in <module>
1 # 未初始化,无属性
----> 2 a.name
AttributeError: 'A' object has no attribute 'name'
# 也可以使用 a.__init__(),
# 它会自动将实例作为第一个参数完成初始化
A.__init__(a)
a
<__main__.A at 0x20d23e95d30>
a.name
'实例'
Python 是动态语言,对象的属性不仅可以查看、访问、调用,还可以动态地增、删、改。
下面定义一个没有自定义属性的类 A 举例:
dir() 函数查看属性,双下划线 __
包围的属性是继承自 object 的特殊属性:
# 定义一个类,查看属性
class A:
pass
dir(A)
['__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__']
# 访问属性 __class__ 相当于调用 type() 函数
A.__class__, A().__class__
(type, __main__.A)
给类 A 及其实例动态添加属性,属性可以是数据属性和方法。类层级添加的属性,将作为所有实例的属性;实例添加的属性,只有对应的实例能访问。
# 添加数据属性
a1 = A()
a2 = A()
A.a = '类变量'
a1.x = 'a1 的属性'
a2.y = 'a2 的属性'
# 类层级添加方法
def f(self):
print(self.a)
A.f = f
# 类 A 调用刚添加的属性
A.f(a1)
A.f(a2)
类变量
类变量
# 实例调用刚添加的属性
a1.f()
a2.f()
类变量
类变量
# 实例 a1 没有 y 属性
# 同理,a2 没有 x 属性
a1.y
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-44-178a7ac627a0> in <module>
1 # 实例 a1 没有 y 属性
2 # 同理,a2 没有 x 属性
----> 3 a1.y
AttributeError: 'A' object has no attribute 'y'
实例直接添加一个函数作为属性,将不会隐式地将自身作为第一个参数,而是和正常函数一样使用:
def p(self):
print(self)
a1.p = p
a1.p('正常传参')
a1.p()
正常传参
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-45-4ebdece61250> in <module>
4 a1.p = p
5 a1.p('正常传参')
----> 6 a1.p()
TypeError: p() missing 1 required positional argument: 'self'
如果要通过实例添加实例方法(第一个参数 self 即是自身的方法),可以通过 types 模块添加。添加的属性,类不可访问,只有对应的实例可访问:
from types import MethodType
# 改变了 a1 的上述 p 属性
a1.p = MethodType(p, a1)
a1.p()
<__main__.A object at 0x000001D40578D730>
A.p
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-47-94cb580acfb0> in <module>
----> 1 A.p
AttributeError: type object 'A' has no attribute 'p'
a2.p
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-48-29321b2aa581> in <module>
----> 1 a2.p
AttributeError: 'A' object has no attribute 'p'
删除属性使用 del 语句:
del a1.p
a1.p()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-49-9cf9b7e7dc86> in <module>
1 del a1.p
2
----> 3 a1.p()
AttributeError: 'A' object has no attribute 'p'
一个从父类继承过来的方法,如果不满足子类的需求,可以进行重写,重写的方法将屏蔽父类的方法,但可以显示地调用,或使用 super() 委托给父类调用,实现父类、子类的方法都可调用。
class A:
def f(self,x):
y = x + x
print(y)
class B(A):
def f(self,x):
y = (x + x)**2
print(y)
b = B()
b.f(2)
16
# 显示地调用
A.f(b, 2)
4
class A:
def f(self,x):
y = x + x
print(y)
class B(A):
def f(self,x):
super().f(x)
y = (x + x)**2
print(y)
b = B()
b.f(2)
4
16
还可使用装饰器修改方法,或添加丰富功能等。
# 将方法定义为静态方法
class C:
@staticmethod
def f(value):
print(value)
c = C()
c.f('必须传参调用')
必须传参调用
# 将私有属性定义为只读,
# 直接用不带下划线的名称访问
class C:
def __init__(self):
self.__name = '私有属性'
@property
def name(self):
return self.__name
c = C()
c.name
'私有属性'
# 尝试修改不被允许
c.name = 0
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-11-c0f354f546f5> in <module>
1 # 尝试修改不被允许
----> 2 c.name = 0
AttributeError: can't set attribute
用特殊方法定制类:
class D:
pass
d = D()
bool(d)
True
# 上述类的实例逻辑值检查为 True
# 定义为 False
class D:
def __bool__(self):
return False
d = D()
bool(d)
False
# 让数字字符串也可以相减
class Mystr(str):
def __sub__(self, other):
return str(float(self) - float(other))
m = Mystr('123')
n = Mystr('3.14')
m, n, m - n
('123', '3.14', '119.86')
所有的类都继承自 object。被继承的类称为基类(或父类,超类),继承者称为子类。
对于多数应用来说,在最简单的情况下,你可以认为搜索从父类所继承属性的操作是深度优先、从左至右的,当层次结构中存在重叠时不会在同一个类中搜索两次。
class A():
def show(self):
print('A')
class B(A):
pass
class C():
pass
class D():
def show(self):
print('D')
class E(C, B, D): # C -> B -> A -> D
pass
e = E()
e.show()
A
真实情况比这个更复杂一些;方法解析顺序会动态改变以支持对 super() 的协同调用。这种方式在某些其他多重继承型语言中被称为 后续方法调用,它比单继承型语言中的 super 调用更强大。
动态改变顺序是有必要的,因为所有多重继承的情况都会显示出一个或更多的菱形关联(即至少有一个父类可通过多条路径被最底层类所访问)。例如,所有类都是继承自 object,因此任何多重继承的情况都提供了一条以上的路径可以通向 object。为了确保基类不会被访问一次以上,动态算法会用一种特殊方式将搜索顺序线性化,保留每个类所指定的从左至右的顺序,只调用每个父类一次,并且保持单调(即一个类可以被子类化而不影响其父类的优先顺序)。
总而言之,这些特性使得设计具有多重继承的可靠且可扩展的类成为可能。
一个基类如果有 __init__()
方法,则其所派生的类如果也有 __init__()
方法,就必须显式地调用它以确保实例基类部分的正确初始化:
class A:
def __init__(self):
self.a = 'A'
def f(self):
print(self.a)
class B(A):
def __init__(self):
self.b = 'B'
b = B()
b.f() # 基类未初始化,属性 a 不可调用
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-5-cda60db4451f> in <module>
11
12 b = B()
---> 13 b.f()
<ipython-input-5-cda60db4451f> in f(self)
4
5 def f(self):
----> 6 print(self.a)
7
8 class B(A):
AttributeError: 'B' object has no attribute 'a'
A.__init__(b) # 将实例 b 传给 A 初始化
b.f()
A
# 或者直接用 super()
class A:
def __init__(self):
self.a = 'A'
def f(self):
print(self.a)
class B(A):
def __init__(self):
super().__init__()
self.b = 'B'
b = B()
b.f()
A