第一章 快速上手:基础知识

书籍:《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