第一章 快速上手:基础知识
书籍:《Python基础教程(第3版)》
1、运算符
1/2 # 除法,返回浮点数 ans = 0.5
1//2 # 整除,返回整数 ans = 0
1%3 # 求余 ans = 1
1%-3 # 求余 ans = -2
-1%3 # 求余 ans = 2
3*3 # 乘法 ans = 9
3**3 # 乘方(求幂) ans = 27
-3**2 # 乘方(求幂) ans = -9
(-3)**2 # 乘方(求幂) ans = 9
2、进制显示
十六进制、八进制、二进制显示
>>> 0xAF
175
>>> 0o67
55
>>> 0b1011010010
722
>>>
3、打印获取输入
>>> y=input("y: ")
y: 34
>>> print(3*y)
343434
>>> x=input("x: ")
x: 34
>>> print(3*x)
343434
>>> print(int(x)*int(y))
1156
4、函数
>>> pow(2,3)
8
>>> 10+pow(2, 3*5)/3.0
10932.666666666666
>>> abs(-10)
10
>>> round(2/3)
1
5、模块
>>> import math #可将模块视为扩展
>>> math.floor(32.9)
32
>>> int(32.9)
32
>>> math.ceil(32.1)
33
>>> from math import sqrt #如果确定不会从不同模块导入多个同名函数,可以不用每次调用函数时都指定模块名
>>> sqrt(9)
3.0
>>> import cmath #cmath模块和复数
>>> cmath.sqrt(-1)
1j
>>> (1+3j)*(9+4j)
(-3+31j)
6、运行Python脚本
脚本的第一行
#!/usr/bin/env python
7、单双引号以及引号转义 (作用一样,都是成对截取)
>>> "Let's go" #单双引号成对出现(最近原则),否则会报错
"Let's go"
>>> print(''Let\'s go'') #成对组合错误
File "<stdin>", line 1
print(''Let\'s go'')
^
SyntaxError: invalid syntax
>>> 'Let's go' #成对组合错误
File "<stdin>", line 1
'Let's go'
^
SyntaxError: invalid syntax
>>> '"Let\'s go"' #反斜杠对引号转义
'"Let\'s go"'
>>> "Let's "+"go" #不使用转义,可以使用拼接字符串
"Let's go"
8、字符串表示str和repr
>>> "hello,\nworld!" #机制1:保留其在代码中的样子
'hello,\nworld!'
>>> print("hello,\nworld") #机制2: 希望用户看到的样子
hello,
world
>>> print(repr("hello,\nworld!")) #机制1 (repr是一个函数)
'hello,\nworld!'
>>> print(str("hello,\nworld!")) #机制2(str像int一样,也是一个类)
hello,
world!
>>> str("hello,\nworld!")
'hello,\nworld!'
9、长字符、原始字符串和字节(考虑\n的出现情况,原始字符串中引号与\位置的影响)
>>> print('''This is a #一个很长的字符串,使用三引号(单或双),表示开始和结尾
... very long string.''')
This is a
very long string.
>>> path = 'C:\program files\nowhere'
>>> print(path) #文件为nowhewe,直接打印,反斜杠会进行转义(print里加入反斜杠?)
C:\program files
owhere
>>> print(r'C:\program files\nwhere') #使用原始字符串成功解决
C:\program files\nwhere
>>> print(r'C:\program files\nwhere\') #特殊情况1:单个反斜杠结尾,且未对其进行转义,Python将无法判断字符串是否到此结束
File "<stdin>", line 1
print(r'C:\program files\nwhere\')
^
SyntaxError: EOL while scanning string literal
>>> print(r'C:\program files\nwhere\\') #如果采用转义,转义反斜杠也将是字符串的一部分
C:\program files\nwhere\\
>>> print(r'C:\program files\nowhere''\\') #技巧:将反斜杠单独作为一个字符串
C:\program files\nowhere\
>>> print(r'Let's go') #特殊情况2:原始字符串中,也要考虑引号的使用规则
File "<stdin>", line 1
print(r'Let's go')
^
SyntaxError: invalid syntax
>>> print(r'Let\'s go') #如果采用转义,转义反斜杠也将是字符串的一部分
Let\'s go
10、Unicode
Unicode Transformation Format 8 bits
>>> "Hello, worlf!".encode("ASCII")
b'Hello, worlf!'
>>> "Hello, worlf!".encode("UTF-8")
b'Hello, worlf!'
>>> "Hello, worlf!".encode("UTF-32")
b'\xff\xfe\x00\x00H\x00\x00\x00e\x00\x00\x00l\x00\x00\x00l\x00\x00\x00o\x00\x00\x00,\x00\x00\x00 \x00\x00\x00w\x00\x00\x00o\x00\x00\x00r\x00\x00\x00l\x00\x00\x00f\x00\x00\x00!\x00\x00\x00'
第二章 列表,Python的主力
数据结构:序列:列表和元组
1、索引 使用[下标]进行取值(考虑索引正负,在哪使用)
>>> person = ["Edward", 42]
>>> person[-1] #从后往前对序列进行索引
42
>>> 'hello'[3] #直接对字符串进行索引
'l'
>>> fourth = input('year: ')[3] #直接对函数返回序列进行索引
year: 2020
>>> fourth
'0'
2、切片 访问特定范围内的元素 (考虑第二个索引)
>>> tag = '<a href="http://www.python.org">Python web site</a>'
>>> tag[9:30] #注意,不是索引9到30的字符,而是9到29,第二个索引表示切片后剩下元素的第一个元素的编号
'http://www.python.org'
>>> tag[32:-4]
'Python web site'
>>> number = [1,2,3,4,5,6,7,8]
>>> number[0:3] #0到2的位置
[1, 2, 3]
>>> number[0:3][2] # [2]是对number[0:3]序列的索引
3
>>> number[0:3][1:3]
[2, 3]
>>> number[-3:0] #如果第一个索引指定的元素位于第二个索引指定的元素后面,返回为空
[]
更大的步长 (考虑步长正负)
>>> number[::2] #两个索引为空,表示整个序列,2为步长
[1, 3, 5, 7]
>>> number[8:1:-2] #步长为负数时,索引也需先大后小,否则返回空
[8, 6, 4]
>>> number[1:8:-2]
[]
3、序列运算
序列相加 (考虑序列类型)
>>> person = ["Edward", 42]
>>> person1 = ["Edward", 42]
>>> person+person1 #列表 + 列表 可行
['Edward', 42, 'Edward', 42]
>>> [1,2,3]+[4,5,6] #列表 + 列表 可行
[1, 2, 3, 4, 5, 6]
>>> ["Edward"]+ [42] #列表 + 列表 可行(即使内部元素类型不同)
['Edward', 42]
>>> "Edward"+[42] #列表 + 字符串 不可行(虽然都是序列)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't convert 'list' object to str implicitly
序列相乘(就是将序列复制n次)
>>> 'python'*5
'pythonpythonpythonpythonpython'
>>> [1,2]*3
[1, 2, 1, 2, 1, 2]
成员资格 (in的使用,判断存在)
>>> users = ['xx', 'yy']
>>> input("your name: ") in users
your name: xx
True
最大值,最小值,长度
>>> number = [1,2,3,4,5,6,7,8]
>>> len(number)
8
>>> max(number)
8
>>> min(number)
1
4、列表函数
list(字符串)函数的使用 (算作内置函数,python2.2后,list是一个类)
列表的一些基本操作:索引赋值,删除元素, 切片赋值, 按切片插入, 切片替换
>>> ls = list('hello') #list 将字符串转列表
>>> ls
['h', 'e', 'l', 'l', 'o']
>>> ''.join(ls)
'hello'
#列表的一些基本操作
>>> ls[0]=3 # 使用索引赋值, (Python列表啥都可以放,真是....)
>>> ls
[3, 'e', 'l', 'l', 'o']
>>> del ls[1] #删除元素
>>> ls
[3, 'l', 'l', 'o']
>>> ls[2:] = list('ar') #按切片赋值
>>> ls
[3, 'l', 'a', 'r']
>>> ls[2:2] = list('mn') #按切片插入
>>> ls
[3, 'l', 'm', 'n', 'a', 'r']
>>> ls[2:4] = [] #按切片替换
>>> ls
[3, 'l', 'a', 'r']
append(arguments) 列表尾部添加元素 (类成员函数)
>>> ls.append('s')
>>> ls
[3, 'l', 'a', 'r', 's']
>>> ls.append(['t','u'])
>>> ls
[3, 'l', 'a', 'r', 's', ['t', 'u']]
clear()
>>> ls.clear()
>>> ls
[]
copy(复制 (考虑与常规复制 = 的区别)
>>> a = [1, 2, 3, 4]
>>> b=a # 常规复制=,只是将另一个名称关联到列表(相当于C++中的引用)
>>> b[2]=8
>>> a
[1, 2, 8, 4]
>>> a = [1, 2, 3, 4]
>>> c=a.copy()
>>> c[2]=8
>>> a
[1, 2, 3, 4]
a.copy() 相当于 a[:] 或 list(a)---------------> 这些都是相当于返回一个副本,然后再b=副本,所以不会影响a
>>> a = [1, 2, 3, 4]
>>> b=a[:]
>>> b[2]=8
>>> a
[1, 2, 3, 4]
>>> c=list(a)
>>> c[2]=8
>>> a
[1, 2, 3, 4]
count(arg) 返回指定元素的个数
>>> x=[[1,2],1,'1']
>>> x.count(1)
1
extend(序列)合并列表
>>> a = [1, 2, 3, 4]
>>> b=[5,6,7]
>>> a.extend(b) #直接修改的是对象a本身
>>> a
[1, 2, 3, 4, 5, 6, 7]
a.extend(b) 相当于a=a+b 或 a[len(a):]=b
>>> a = [1, 2, 3, 4]
>>> b=[5,6,7]
>>> a=a+b #将新的副本传给了a
>>> a
[1, 2, 3, 4, 5, 6, 7]
>>> a = [1, 2, 3, 4]
>>> a[len(a):]=b #列表尾部切片赋值
>>> a
[1, 2, 3, 4, 5, 6, 7]
index(元素)找到指定元素第一次出现的索引
>>> a = [1, 2, 3, 3, 5, 6, 7]
>>> a.index(3)
2
>>> a.index(100)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 100 is not in list
insert(索引,元素) 将一个对象插入列表
>>> numbers=[1,2,3,4,5]
>>> numbers.insert(3, 'four')
>>> numbers
[1, 2, 3, 'four', 4, 5]
>>> numbers[4:4]='five' #犯错了,插入了一个字符串序列
>>> numbers
[1, 2, 3, 'four', 'f', 'i', 'v', 'e', 4, 5]
>>> numbers[4:4]=['five'] #插入一个列表序列
>>> numbers
[1, 2, 3, 'four', 'five', 'f', 'i', 'v', 'e', 4, 5]
pop(索引)删除一个元素
>>> x = [1, 2, 3, 4]
>>> x.pop()
4
>>> x
[1, 2, 3]
>>> x.pop(0)
1
>>> x
[2, 3]
remove(元素)删除一个指定元素
>>> ls = ['h', 'e', 'l', 'l', 'o']
>>> ls.remove('l')
>>> ls
['h', 'e', 'l', 'o']
>>> ls.remove('u')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
reverse() 列表反转
>>> ls.reverse()
>>> ls
['o', 'l', 'e', 'h']
sort()排序, 相当于sorted(序列)内置函数
>>> a=[4,2,8,0]
>>> a.sort() #默认从小到大排序
>>> a
[0, 2, 4, 8]
>>> a=[4,2,8,0]
>>> sorted(a)
[0, 2, 4, 8]
>>> sorted('hello') #可用于任何序列,且总是返回一个列表
['e', 'h', 'l', 'l', 'o']
如何相反的顺序排列?
先使用sort(或者 sorted),然后使用reverse。
高级排序,参数按名称指定,称为关键字参数
>>> a=[4,2,8,0]
>>> a.sort(reverse=True)
>>> a
[8, 4, 2, 0]
>>> x=['aaaa','b','cc']
>>> x.sort(key=len)
>>> x
['b', 'cc', 'aaaa']
5、元组:不可修改的序列
>>> 1,2,3 #元组语法简单,逗号分隔
(1, 2, 3)
>>> (1,2,3)
(1, 2, 3)
>>> () #空元组
()
>>> (42)
42
>>> 42, #单元素元组,也要加逗号
(42,)
>>> 3*(40+2,)
(42, 42, 42)
>>> tuple([1,2,3]) #tuple可将列表或字符串转成元组
(1, 2, 3)
>>> tuple('abc')
('a', 'b', 'c')
>>>
>>> x=1,2,3
>>> x[0:2] #元组的切片返回的还是元组
(1, 2)
6、list、for、if组合使用
https://www.liaoxuefeng.com/wiki/1016959663602400/1017317609699776
>>> [x for x in range(10) if x > 4]
[5, 6, 7, 8, 9]
>>> [x if x > 4 else -x for x in range(10)]
[0, -1, -2, -3, -4, 5, 6, 7, 8, 9]
因为跟在for后面的if是一个筛选条件,不能带else,否则如何筛选?
因为for前面的部分是一个表达式,它必须根据x计算出一个结果。
其实应该从for字段分前后两段:
1:for x in range(10) if x > 4: #筛选
2:x #计算
1:for x in range(10): #筛选
2:x if x > 4 else -x #计算,三目运算
第三章 使用字符串
字符串是不可变的
>>> a='hello'
>>> a[-2:]='xx'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
1、设置字符串的格式 : 精简版
将值转换成字符串并设置其格式
%s为转换格式
>>> format = "hello, %s. %s enough for ya?"
>>> values = ('world', 'hot')
>>> format % values
'hello, world. hot enough for ya?'
类似于unix shell的语法:
>>> from string import Template
>>> tmpl=Template("Hello, $who! $what enough for ya?")
>>> tmpl.substitute(who='Mars', what='Dusty')
'Hello, Mars! Dusty enough for ya?'
替换字段没有名称或将索引引用作名称
>>> "{}, {} and {}".format("first", "second", "third")
'first, second and third'
>>> "{2}, {1} and {}".format("first", "second", "third")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: cannot switch from manual field specification to automatic field numbering
>>> "{2}, {1} and {0}".format("first", "second", "third")
'third, second and first'
>>> from math import pi
>>> "{name} is approximately {value:.2f}.".format(value=pi,name="pa")
'pa is approximately 3.14.'
如果变量和替换字段同名
Python 3,6
>>> from math import e
>>> f"Euler's constant is roughly {e}"
当前:
>>> "Euler's constant is roughly {e}.".format(e=e)
"Euler's constant is roughly 2.718281828459045.
2、设置字符串的格式 : 完整版
…
3、字符串方法
center(n) 两边填充字符(默认为空),让字符串居中对齐
>>> "hello, world!".center(20)
' hello, world! '
>>> "hello, world!".center(20,'*')
'***hello, world!****'
find(元素) 查找字符串,找到返回索引,否则返回-1
>>> "hello, world!".find('lo')
3
>>> "hello, world!, hello".find('lo', 5) #设置查找起始位置
18
>>> "hello, world!, hello".find('lo', 5, 15)
-1
分隔符.join(字符串列表), 与split相反
>>> seq=['1','2','3',4]
>>> sep.join(seq)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sequence item 3: expected str instance, int found
>>> seq=['1','2','3','4']
>>> sep.join(seq)
'1+2+3+4'
>>>
>>> dirs ='', 'usr', 'bin', 'env'
>>> '/'.join(dirs)
'/usr/bin/env'
>>> print('C:'+'\\'.join(dirs))
C:\usr\bin\env
>>> a="xyz"
>>> "+".join(a) #字符串也是个序列
'x+y+z'
lower 返回字符串的小写版本
>>> "Hello, World!".lower()
'hello, world!'
replace(原,目)将指定字符串替换成目标字符串
>>> "Hello, World!".replace(' Wo', 'wo')
'Hello,world!'
split(分隔符)将字符串拆分成序列(分隔符默认为空符号)
>>> '1+2+3+4'.split('+')
['1', '2', '3', '4']
strip 删除开头和末尾的空白 (lstrip, rstrip)
>>> " Hello, World! ".strip()
'Hello, World!'
translate 单字符替换,可同时替换多个
>>> table = str.maketrans('cs', 'kz') #条用函数创建转换表
>>> str
<class 'str'>
>>> table
{115: 122, 99: 107}
>>> 'this is incredible test'.translate(table)
'thiz iz inkredible tezt'
4、字符串判断条件
isalnum、isalpha、isdecimal、isdigital…
第四章 当索引行不通时
1、字典
dict 从其他映射(如其他字典)或键-值对序列创建字典
>>> items=[('name','Bob'),('age',42)]
>>> d=dict(items)
>>> d
{'name': 'Bob', 'age': 42}
字典基本操作
len(d)
d[k]
d[k]=v
del d[k]
k in d
>>> x=[]
>>> x[42]='Foo'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range
>>> x={}
>>> x[42]='Foo'
>>> x
{42: 'Foo'}
将字符串格式设置功能用于字典
>>> template='''<html>
... <head><title>{title}</title></head>
... <body>
... <p>{text}</p>'''
>>> data={'title':'my page','text':'welcome'}
>>> template.format_map(data)
'<html>\n<head><title>my page</title></head>\n<body>\n<p>welcome</p>'
>>> print(template)
<html>
<head><title>{title}</title></head>
<body>
<p>{text}</p>
2、字典方法
clear()
copy() 浅复制,因为值本身是原件,而非副本;
如果修改副本中的值(就地修改而不是替换),原本也将发生变化
>>> x={'username':'admin','machine':['foo','bar','baz']}
>>> y=x.copy()
>>> y['username']='new'
>>> y['machine'].remove('bar')
>>> x
{'machine': ['foo', 'baz'], 'username': 'admin'}
>>> y
{'machine': ['foo', 'baz'], 'username': 'new'}
deepcopy深复制
>>> x={}
>>> x['name']=['Bob','Tom']
>>> c=x.copy()
>>> dc=deepcopy(x)
>>> x['name'].append('clive')
>>> c
{'name': ['Bob', 'Tom', 'clive']}
>>> dc
{'name': ['Bob', 'Tom']}
fromkeys 创建一个新字典,其中包含指定的键,且每个键对应的值为None
dict是所有字典所属的类型
>>> {}.fromkeys(['name','age'])
{'name': None, 'age': None}
>>> dict.fromkeys(['name','age'],'(unkown)')
{'name': '(unkown)', 'age': '(unkown)'}
get访问字典,即使没有的项,也不会报错
>>> d ={}
>>> d['name']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'name'
>>> d.get('name')
>>> print(d.get('name'))
None
>>> print(d.get('name', 'N/A'))
N/A
items 以(key, value)形式返回一个包含所有字典项的列表
>>> data={'title':'my page','text':'welcome'}
>>> data.items()
dict_items([('title', 'my page'), ('text', 'welcome')])
>>> list(data.items())
[('title', 'my page'), ('text', 'welcome')]
popitem
list.pop弹出列表中最后一个元素,而popitem随机弹出一个字典项,因为字典项的顺序是不确定的,没有最后一个元素的概念;也因为无序,所以没有append对应的方法。
在Python里,翻找字典这一过程对应着哈希算法,对key进行哈希运算,然后得到value。所以我们就会遇到顺序插入字典元素,但是输出则是无序元素的情况。
>> data={'title':'my page','text':'welcome'}
>>> data.popitem()
('title', 'my page')
setdefault 设置value默认值
>>> d={}
>>> d.setdefault('name','N/A')
'N/A'
>>> d.setdefault('name', 'x')
'N/A'
>>> d={}
>>> d.setdefault('name')
>>> print(d.setdefault('name'))
None
>>> d
{'name': None}
update 使用一个字典中 的项来更新另一个字典
>>> d={'title': 'python web site', 'url': 'http://'}
>>> x={'title': 'python language website'}
>>> d.update(x)
>>> d
{'title': 'python language website', 'url': 'http://'}
values 返回一个有字典中的值组成的字典视图
>>> d={}
>>> d[1]=1
>>> d[2]=2
>>> d.values()
dict_values([1, 2])
第五章 条件、循环及其他语句
1、print和import
>>> print("age: ",42) #打印多个参数
age: 42
>>> print("Hello, ",end='') #自定义结束字符串,以替换默认的换行符
>>> print("world")
Hello, world
导入时重命名
>>> import math as foobar
>>> foobar.sqrt(4)
2.0
>>> from math import sqrt as foobar
>>> foobar(4)
2.0
2、赋值魔法
序列解包
>>> x,y,z=1,2,3
>>> value=1,2,3
>>> a,b,*rest=1,2,3,4
>>> rest
[3, 4]
>>> a,*b,c="abc"
>>> b
['b']
>>> a,*b,c="abcde"
>>> b
['b', 'c', 'd']
链式赋值
将多个变量关联到同一个值,只涉及一个值
>>> x=y=sqrt(4) #1
>>> x=sqrt(4) #2
>>> y=x
>>> x=3 #这里x被赋值,重新指向了另一个值
>>> y
2.0
>>> x=y=[1,2,3]
>>> y
[1, 2, 3]
>>> x[1]=5 #只是修改了指向的值
>>> y
[1, 5, 3]
增强赋值
x *=2 x+=2
3、条件和条件语句
if :
elif:
else:
status = "friend" if name.endswith("GUmy") else "stranger" #三目运算符
>>> x=[1,2]
>>> y=[1,2]
>>> x==y
True
>>> x is y #是不是同一个对象
False
字符是根据顺序值排列的。要获取字母的顺序值,可使用函数ord(与函数chr相反)
>>> ord("🙈")
128584
>>> chr(128584)
'🙈'
断言 assert
>>> age=10
>>> assert 0<age<100
>>> age=-1
>>> assert 0<age<100, 'The age must be realistic'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: The age must be realistic
循环
while
for
>>> for number in range(1,100): #从1到99
... print(number)
...
1
zip内置函数,将两个序列“缝合”起来,并返回一个有元组组成的序列
>>> list(zip(range(5),range(100)))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
反向迭代
sorted()、list(reverse())、‘’.join(reverse())
跳出循环
break,continue,while True/break
for else
>>> from math import sqrt
>>> for n in range(99,81,-1):
... if sqrt(n)==int(sqrt(n)):
... break
... else:
... print("didn't find")
...
didn't find
>>> [x*x for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
4、三人行
什么都不做
pass
>>> x=3
>>> if x > 10:
... pass
...
删除对象
del 对象
>>> x=y=[1,2]
>>> del x #虽然x,y指向同一个对象,但是只是删除了名称
>>> y
[1, 2]
执行字符串及计算其结果
exec() eval()
第六章 抽象
import math
y=math.sqrt
callable(y)
True
1、自定义函数
放在函数开头的字符串称为文档字符串,将作为函数的一部分存储起来。
收集参数
>>> def in_the_middle(x,*y,z):
... print(x,y,z)
...
>>> in_the_middle(1,2,3,4,5,z=7)
1 (2, 3, 4, 5) 7
>>> def in_the_middle2(**params):
... print(params)
...
>>> in_the_middle2(x=1,y=2,z=3)
{'x': 1, 'y': 2, 'z': 3}
分配参数
>>> def add1(x,y):
... return x+y
...
>>> params=(1,2)
>>> add1(*params)
3
>>> def with_stars(**kwds):
... print(kwds['name'], 'is', kwds['age'], 'years old')
...
>>> def without_stars(kwds):
... print(kwds['name'], 'is', kwds['age'], 'years old')
...
>>> args={'name':'Mr.xu', 'age':42}
>>> with_stars(**args)
Mr.xu is 42 years old
>>> without_stars(args)
Mr.xu is 42 years old
>>> def without_stars2(name='a',age=10):
... print(name, 'is', age, 'years old')
...
>>> without_stars2(**args) #字典拆开了,只是传入值
Mr.xu is 42 years old
改变全局值
>>> x=1
>>> def change_global():
... global x
... x=x+1
...
>>> change_global()
>>> x
2
函数式编程
>>> list(map(str, range(10)))
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
>>> [str(i) for i in range(10)]
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
第七章 再谈抽象
2、创建自定义类
参数self是什么?它指向对象。
当对对象调用函数时,对象都会作为第一个参数自动传递进去。
关联的方法:可以将属性关联到一个普通函数 (理解成一个个函数指针);甚至可以将一个变量关联到属性函数
>>> class Class:
... def method(self):
... print('I have a self')
...
>>> def function():
... print("I don't....")
...
>>> ins = Class()
>>> ins.method()
I have a self
>>> ins.method = function
>>> ins.method()
I don't....
>>> ss = ins.method
>>> ss()
I don't....
要让方法或属性变成私有的,只需要让名称以两个下划线打头即可。
幕后处理方法:在类定义中,对所有以两个下划线打头的名称进行转换,即在开头加一个下划线和类名
>>> class Class1:
... def __method(self):
... print('I have a self')
...
>>> Class1._Class1__method
<function Class1.__method at 0x7fe29cd6d048>
>>> c=Class1()
>>> c._Class1__method()
I have a self
指定超类
class Filter:
def init(self):
self.blocked = []
def filter(self, sequence):
return [x for x in sequence if x not in self.blocked]
class SPAMfilter(Filter):
def init(self):
self.blocked = ['SPAM' ]
>>> issubclass(SPAMfilter, Filter) #是不是子类
True
>>> SPAMfilter.__bases__ #查询基类
(<class 'class1.Filter'>,)
>>> s=SPAMfilter()
>>> isinstance(s, SPAMfilter) #对象是否是特例类的实例
True
>>> isinstance(s, Filter)
True
多个超类,多重继承,方法解析顺序
class Calculator:
def calculate(self, expression):
self.value = eval(expression)
class Talker:
def talk(self):
print('Hi, my value is ', self.value)
class TalkingCalculator(Calculator, Talker):
pass
>>> tc = TalkingCalculator()
>>> tc.calculate('1+2*3')
>>> tc.talk()
Hi, my value is 7
>>> hasattr(tc, 'talk')
True
>>> callable(getattr(tc, 'talk', None))
True
3、抽象类
from abc import ABC, abstractmethod
class Talker(ABC):
@abstractmethod #装饰器,将方法标记为抽象的,再子类中必须实现的方法
def talk(self):
pass
>>> class knigget(Talker):
... def talk(self):
... print('yes')
...
>>> class Herr:
... def talk(self):
... print('yes')
...
>>> Talker.register(Herr) #注册子类
>>> issubclass(Herr, Talker)
>>> True