Python 是一种相当高级的语言,通过 Python 解释器把符合语法的程序代码转换成 CPU 能够执行的机器码,然后执行。Python 非常简洁,完成同一个任务,C 语言要写  1000 行代码,Java 只需要写 100 行,而 Python 可能只要 20 行,但是 Python 的运行速度稍慢。

安装 python 后可以通过文本编辑器来保存代码 .py,通过命令行模式来运行代码,而 Python 自带的 IDLE(交互模式)可以用来验证代码。也可以直接用 IDE 集成开发环境来编写和运行代码。

第一部分 Python基础

数据类型和变量、输入输出、字符串和编码、list tuple dict set 、条件判断、循环、函数、切片 迭代 列表生成器 生成器 迭代器

1. Python 用 # 来注释,用缩进表示语法。Python 区分大小写。

缩进按照约定俗成的习惯,坚持使用 4 个空格的缩进(把 tab 设置为 4 个空格)。

优点:强迫写出缩进较小的代码,把一段很长的代码拆分成若干函数。

缺点:“复制-粘贴”功能失效,需要在 IDLE 上重新检查缩进。

1. 数据类型、常变量、四种运算

2. 字符串和编码

3. 输入和输出

3.1 输出

print('hello,world')

print('100+300=',100+300)

print('hello ,','world')

print('hello,'+'world')

# 结果:hello,world

print('bang ! '*3)

# 结果:bang ! bang ! bang !

print(type(2))

# 结果:

复制代码

search = '168'

num_a = '138-6168-0006'

num_b = '168-1222-0006'

print(search + ' is at ' + str(num_a.find(search)) + ' to ' + str(num_a.find(search)+len(search)) + ' of num_a ')

print(search + ' is at ' + str(num_b.find(search)) + ' to ' + str(num_b.find(search)+len(search)) + ' of num_b ')

# 结果:

168 is at 5 to 8 of num_a

168 is at 0 to 3 of num_b

复制代码

2. 输出多个字符串用逗号 "," 隔开,print() 依次打印每个字符串,遇到逗号 ","会输出一个空格。

3. 在 print() 函数中,"+" 在整数和浮点数中为运算符,在字符型中为连接符。字符串与整数、浮点数一起输出必须用 ",",不能用 "+" 。

3.2 输入

name=input('please enter your name')

print('hello,',name)

4. 在 input() 函数中添加字符串可以提示用户输入内容。

3.3 格式化

3.3.1 用 % 格式化

5.  %d 整数   %f 浮点数    %s 字符串    %x 十六进制整数。

print( 'Hello, %s' % 'world')

print('Hi, %s, you have $%d.') % ('Michael', 1000000)

print('%2d-%02d' % (3, 1))   # 结果:3-01

print( '%.2f' % 3.1415926)    # 结果:3.14

6. 有几个 %? 占位符,后面就跟几个变量或者值,顺序要对应好。如果只有一个 %?,括号可以省略。

7. 格式化整数和浮点数可以指定是否补 0 和整数与小数的位数。

8. 如果不太确定应该用什么,%s 永远起作用,它会把任何数据类型转换为字符串。

9. 字符串里面的 % 是一个普通字符,用 %% 来表示一个 % 。

3.3.2 用 format 格式化

print('Hello, {}'.format('world'))

print('Hi, {}, you have ${}.'.format ('Michael', 1000000))

4. list 和 tuple

4.1 列表 list []

10. list 是一种有序的集合,可以随时添加和删除其中的元素。

classmates = ['Michael', 'Bob', 'Tracy']

print(classmates)  # 结果:['Michael', 'Bob', 'Tracy']

11. 用 len() 函数可以获得 list 元素的个数。

print(len(classmates))  # 结果:3

12. 顺序索引、逆序索引。

print(classmates[0],classmates[1],classmates[2])  # 结果:Michael Bob Tracy

print(classmates[-1], classmates[-2],classmates[-3])  # 结果:Tracy Bob Michael

13. 在 list 末尾添加元素、在 list 指定位置添加元素、添加多个元素。

classmates.append('Adam')

print(classmates)  # 结果:['Michael', 'Bob', 'Tracy', 'Adam']

classmates.insert(1, 'Jack')

print(classmates)  # 结果:['Michael', 'Jack', 'Bob', 'Tracy']

classmates = ['Michael', 'Bob', 'Tracy']

classmates.extend(['Adam', 'Jack'])

print(classmates)

# 结果:['Michael', 'Bob', 'Tracy', 'Adam', 'Jack']

14. 删除 list 末尾的元素、删除指定位置的元素。

classmates.pop()

print(classmates)  # 结果:['Michael', 'Bob']

classmates.pop(1)

print(classmates)  # 结果:['Michael', 'Tracy']

classmates = ['Michael', 'Bob', 'Tracy']

classmates.remove('Bob')    # 用 remove 删除要指定元素

print(classmates)

classmates = ['Michael', 'Bob', 'Tracy']

del classmates[2]

print(classmates)

15. 更新某个元素。

classmates[1] = 'Sarah'

print(classmates)  # 结果:['Michael', 'Sarah', 'Tracy']

16. list 中可以包含各种数据类型。

L = ['Apple', 123, True]

17. 嵌套 list。

s = ['python', 'java', ['asp', 'php'], 'scheme']

print(len(s))    # 结果:4

print(s[2][0])  # 结果:asp

4.2 元组 tuple ()

18. tuple 初始化后不能修改,其它同 list ( len()、索引、可以是任何数据类型、嵌套)。

classmates = ('Michael', 'Bob', 'Tracy')

19. 只有1个元素的 tuple 定义时必须加一个逗号 “,” ,来消除歧义(数学计算意义上的括号)。

t = (1,)

print(t)  # 结果:(1,)

20. "可变的"tuple (嵌套) 。

t = ('a', 'b', ['A', 'B'])

t[2][0] = 'X'

t[2][1] = 'Y'

print(t)  # 结果:('a', 'b', ['X', 'Y'])

21. tuple 所谓的"不变"是说 tuple 的每个元素指向永远不变,即指向 'a' ,不能改成指向 'b' ,指向一个 list ,不能改成指向其他对象,但指向的这个 list 本身是可变的。要创建一个内容也不变的 tuple ,就必须保证 tuple 的每一个元素本身也不能变。

5. dict 和 set

5.1 字典 dic {}

22. 内置的字典,全称dictionary,在其他语言中称为map,使用键-值(key-value)存储,具有极快的查找速度。

d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}

print(d['Michael'])  # 结果:95

23. 用 len() 函数可以获得 dict 元素的个数。

d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}

print(len(d))  # 结果:3

24. 添加 key-value 、添加多个 key-value。

d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}

d['Adam']=67

print(d)  # 结果:{'Adam': 67, 'Bob': 75, 'Tracy': 85, 'Michael': 95}

d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}

d.update({'Adam':67,'Jack':99})

print(d)

25. 更新 value 。

d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}

d['Bob'] = 90

print(d['Bob'])  # 结果:90

26. 删除 key-value 。dict 没有 remove

d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}

d.pop('Bob')

print(d)  # 结果:{'Michael': 95, 'Tracy': 85}

d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}

del d['Bob']

print(d)

27. 检查 key 是否在 dict 中。

d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}

print('Thomas' in d)  # 结果:False

d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}

print('Michael' in d)  # 结果:True

d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}

print(d.get('Thomas'))  # 结果:None

d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}

print(d.get('Michael'))  # 结果:95

28. dict 查找和插入快,占用空间大,dict 无序;list 查找和插入慢,占用空间小,list 有序;

dict 的 key 必须是不可变对象 (字符串、整数等都是不可变的,list 是可变的)。

5.2 set

29. set 和 dict 类似,也是一组 key 的集合,但不存储 value。由于 key 不能重复,所以,在 set 中,没有重复的 key 。

30. set 自动过滤重复的元素, set 中的元素是无序的。

s = set([2,1,2,3])

print(s)  # 结果:{1, 2, 3}

# {1, 2, 3} 只是告诉你这个 set 内部有 1,2,3 这 3 个元素,显示的顺序并不表示 set 是有序的

31. 添加元素。

s = set([2,1,2,3])

s.add(4)

print(s)  # 结果:{1, 2, 3, 4}

32. 删除元素。set 没有 del pop 。

s = set([2,1,2,3,4])

s.remove(4)

print(s)  # 结果:{1, 2, 3}

s = {1,2,3,4}

s.discard(4)

print(s)

33. 检查 key 是否在 set 中。

s = set(['Adam', 'Lisa', 'Bart', 'Paul'])

print('adam' in s)    # 结果:False

print('Adam' in s)  # 结果:True

34. set 可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的并、交、差操作。

s1 = set([1, 2, 3])

s2 = set([2, 3, 4])

s3 = set([1, 2, 3, 4, 5])

print(s1 & s2)   # 交      结果:{2, 3}

print(s1 | s2)   # 并      结果:{1, 2, 3, 4}

print(s3 - s1)   # 差      结果:{4, 5}

35. set 和 dict 的唯一区别仅在于没有存储对应的 value ,但是,set 的原理和 dict 一样。set 不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set 内部 “不会有重复元素”。

5.3 再议不可变对象

a = [6,74,2,3,5,36,5]

a.sort(reverse=True)

print(a)

# 结果:[74, 36, 6, 5, 5, 3, 2]

a = ['a', 'd', 'c']

a.sort()

print(a)  # 结果:['a', 'c', 'd']

a = 'abc'

a.replace('a','A')

print(a)  # 结果:abc

a = 'abc'

b = a.replace('a','A')

print(a)    # 结果:abc

print(b)    # 结果:Abc

当我们调用 a.replace('a','A') 时,实际上调用方法 replace 是作用在字符串对象 'abc' 上的,而这个方法虽然名字叫 repalce,但却没有改变字符串 'abc' 的内容。相反,replace 方法创建了一个新字符串 'Abc' 并返回。如果我们用变量 b 指向该新字符串,则变量 a 仍指向原有的字符串 'abc',但变量 b 却指向新字符串 'Abc' 了。

6. 条件判断

比较运算符    ==, !=,>, <, <=, >=

成员运算符    in,not in

身份运算符    is,is not

布尔元素符    not,and, or

36.不同类型的对象不能使用 >, <, <=, >= 进行比较,但可以使用 ==, != 比较。浮点数和整数可以比较大小。布尔类型可以比较大小,False 为 0,True 为 1。

复制代码

a = 'a'

b = 'a'

print(a is b)

print(a is not b)

# 结果:

True

False

复制代码

复制代码

age = 20

if age >= 6:

print('teenager')

elif age >= 18:

print('adult')

else:

print('kid')

复制代码

36. 如果 if 语句判断是 True ,就执行缩进的语句。注意 if、else、elif 后面的 ":" 。

37. if 语句从上往下判断,如果在某个判断上是 True ,把该判断对应的语句执行后,就忽略掉剩下的 elif 和 else。

38. if 判断条件可以简写,非零数值、非空字符串、非空 list tuple dict set 等,都判断为 True,否则为 False 。

x = 8

if x:

print('True')

39. input() 返回的数据类型是 str ,str不能直接和整数比较,要把 str 用 int() 转为整数。

s = input('birth: ')

birth = int(s)

if birth < 2000:

print('00前')

else:

print('00后')

当 if 后面的布尔表达式过长或者难于理解,可以采取给变量赋值的办法来储存布尔表达式返回的布尔值 True 或 False 。

复制代码

password_list = ['*#*#', '12345']

def account_login():

password = input('Password')

password_correct = password == password_list[-1]

password_reset = password == password_list[0]

if password_correct :

print('Login success!')

elif password_reset :

new_password = input('Enter a new password:')

password_list.append(new_password)

print('Your password has changed successfully')

account_login()

else:

print('Wrong password or invalid input!')

account_login()

account_login()

复制代码

7. 循环

7.1 for...in 循环,遍历 list、tuple、disc、set

40. for x in y 循环就是把 y 中每个元素代入变量 x ,然后执行缩进块的语句。

names = ['Michael', 'Bob', 'Tracy']

for name in names:

print(name)

复制代码

# 对list中的每一个元素,如果在set中,就将其删除,如果不在set中,就添加进去

s = set(['Adam', 'Lisa', 'Paul'])

L = ['Adam', 'Lisa', 'Bart', 'Paul']

for a in L:

if a in s :

s.remove(a)

else:

s.add(a)

print(s)

复制代码

# 遍历如下的dict,打印 name: score

d = {'Adam': 95,'Lisa': 85,'Bart': 59}

for key in d :

print(key+':',d[key])

# 遍历如下的set,打印出 name: score

s = set([('Adam', 95), ('Lisa', 85), ('Bart', 59)])

for x in s:

print(x[0] + ':', x[1])

41. range() 函数生成整数序列,list() 函数把整数序列转换为 list。 [ set()、tuple() 同 ]

例如 range(5) 生成从0开始小于5的整数序列。

print(list(range(5)))  # 结果:[0, 1, 2, 3, 4]

print(set(range(5)))   # 结果:{0, 1, 2, 3, 4}

sum = 0

for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:

sum = sum + x

print(sum)

sum = 0

for x in range(101):

sum = sum + x

print(sum)

7.2 while 循环,条件满足时进行循环,条件不满足时退出循环

复制代码

# 计算100以内所有奇数之和

sum = 0

n = 99

while n > 0:

sum = sum + n

n = n - 2

print(sum)

复制代码

7.3 break 提前退出循环

复制代码

n = 1

while n <= 100:

if n > 10: # 当n = 11时,条件满足,执行break语句

break # break语句会结束当前循环

print(n)

n = n + 1

print('END')

复制代码

7.4 continue 跳过当前循环,进入下一循环

n = 0

while n < 10:

n = n + 1

if n % 2 == 0: # 如果n是偶数,执行continue语句

continue # continue语句会直接继续下一轮循环,后续的print()语句不会执行

print(n)

42.不要滥用 break 和 continue 语句。break 和 continue 会造成代码执行逻辑分叉过多,容易出错。大多数循环并不需要用到 break 和 continue 语句,上面的两个例子,都可以通过改写循环条件或者修改循环逻辑,去掉 break 和 continue 语句。

7.5 嵌套循环

for x in ['A', 'B', 'C']:

for y in ['1', '2', '3']:

print(x + y)

复制代码

# 打印出100以内所有十位数数字比个位数数字小的数

a = set(range(10))

a.remove(0)

for x in a:

for y in a:

if x < y:

print(x*10+y)

else:

continue

复制代码

8. 函数

8.1 调用函数

Python内置了很多有用的函数,我们可以直接调用。

abs()    返回一个数的绝对值

max()    返回多个数中最大的数

cmp(x, y)    如果 xy,返回 1

int()    把其他数据类型转换为整数

float()    把其它数据类型转换为浮点数

str()    把其它数据类型转换为字符串

bool()    把其它数据类型转换为布尔值

hex()    把一个整数转换成十六进制表示的字符串

list()、set()、tuple()    把某序列转换为 list、set、tuple

对函数使用别名

a = abs # 变量a指向abs函数

print(a(-1)) # 所以也可以通过a调用abs函数

8.2 定义函数

43. 定义一个函数要使用 def 语句,依次写出函数名、括号、括号中的参数和冒号":",然后,在缩进块中编写函数体,函数的返回值用 return 语句返回。如果没有 return 语句时,自动 return None 。

def my_abs(x):

if x >= 0:

return x

else:

return -x

44.在 Python 交互环境中定义函数时,注意 Python 会出现 ...的提示。函数定义结束后需要按两次回车重新回到 >>> 提示符下。

45. 定义一个空函数,再没有想好函数代码时让整个代码能运行起来。

def nop():

pass

# pass 也可以在其它语句

if age >= 18:

pass

46. 调用函数时,Python 解释器会检查内置函数的参数个数和参数类型是否正确,而对自定义的函数只检查参数个数,所以我们要在函数定义中对参数类型进行检查。数据类型检查可以用内置函数 isinstance() 实现。

复制代码

def my_abs(x):

if not isinstance(x, (int, float)):

raise TypeError('bad operand type')

if x >= 0:

return x

else:

return -x

复制代码

47. Python 的函数返回多值其实就是返回一个 tuple 。在语法上,返回一个 tuple 可以省略括号,而多个变量可以同时接收一个 tuple ,按位置赋给对应的值。

复制代码

# 给出一点的坐标,给出移动位移、角度,计算出新坐标

import math    #导入 math 包

def move(x, y, step, angle=0):

nx = x + step * math.cos(angle)

ny = y + step * math.sin(angle)

return nx, ny

x, y = move(100, 100, 60, math.pi / 6)

print(x, y)          # 结果:151.96152422706632 130.0

r = move(100, 100, 60, math.pi / 6)

print(r)             # 结果:(151.96152422706632, 130.0)

复制代码

8.3 函数的参数

8.3.1 位置参数

# 计算一个数的平方

def power(x):

return x * x

复制代码

# 计算一个数的n次方

def power(x, n):

s = 1

while n > 0:

n = n - 1

s = s * x

return s

复制代码

48. 位置参数,调用函数时,传入的两个值按照位置顺序依次赋给参数 x 和 n 。

8.3.2 默认参数

复制代码

# 在不传入n时,n默认为2

def power(x, n=2):

s = 1

while n > 0:

n = n - 1

s = s * x

return s

print(power(5))    # 结果:25

print(power(5,3))    # 结果:125

复制代码

49.设置默认参数时,有几点要注意:可以加下QQ群:533807627

一是必选参数在前,默认参数在后,否则Python的解释器会报错;

二是当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。

50. 默认参数降低调用的难度。一旦需要更复杂的调用时,又可以传递更多的参数来实现。无论是简单调用还是复杂调用,函数只需要定义一个。

51. 有多个默认参数时,调用的时候,既可以按顺序提供默认参数,也可以不按顺序提供部分默认参数。当不按顺序提供部分默认参数时,需要把参数名写上。

def enroll(name, gender, age=6, city='Beijing'):

print('name:', name,'    gender:', gender,'    age:', age,'    city:', city)

enroll('Sarah','F')  # 结果:name: Sarah     gender: F     age: 6     city: Beijing

enroll('Bob','M',7)  # 结果:name: Bob     gender: M     age: 7     city: Beijing

enroll('Adam','M',city='Changsha')  # 结果:name: Adam     gender: M     age: 6     city: Changsha

52. 默认参数必须指向不变对象。因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。

复制代码

def add_end(L=[]):  # 默认参数为list,为可变对象

L.append('END')

return L

# 正常调用

print(add_end([1, 2, 3]))        # 结果:[1, 2, 3, 'END']

print(add_end(['x', 'y', 'z']))  # 结果:['x', 'y', 'z', 'END']

# 默认调用

print(add_end())  # 结果:['END']

print(add_end())  # 结果:['END', 'END']

print(add_end())  # 结果:['END', 'END', 'END']

# 因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了

复制代码

8.3.3 可变参数

53. 可变参数就是传入的参数个数是可变的,可以是 0 个或任意个参数,这些可变参数在函数调用时自动组装为一个 tuple 。

复制代码

def calc(*numbers): # 参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple

sum = 0

for n in numbers :

sum = sum + n*n

return sum

print(calc(1,2))

print(calc())

nums = [1, 2, 3]

print(calc(nums[0], nums[1], nums[2]))

print(calc(*nums))  # *nums表示把nums这个list的所有元素作为可变参数传进去

复制代码

8.3.4 关键字参数

54. 关键字参数允许你传入 0 个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个 dict 。

55. 在调用该函数时,可以只传入必选参数。也可以传入任意个数的关键字参数。

复制代码

def person(name, age, **kw):

print('name:', name, 'age:', age, 'other:', kw)

person('Michael', 30)                            # 结果:name: Michael age: 30 other: {}

person('Bob', 35, city='Beijing')                # 结果:name: Bob age: 35 other: {'city': 'Beijing'}

person('Adam', 45, gender='M', job='Engineer')   # 结果:name: Adam age: 45 other: {'job': 'Engineer', 'gender': 'M'}

extra = {'city': 'Beijing', 'job': 'Engineer'}

person('Jack', 24, city=extra['city'], job=extra['job'])   # 结果:name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}

person('Jack', 24, **extra)                                # 结果:name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}

# **extra表示把extra这个dict的所有key-value用关键字参数传入到函数的**kw参数,kw将获得一个dict,注意kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra

复制代码

56. 默认参数是所有的调用函数都有定义的所有参数(个数不变),只是默认参数的值是默认的;而关键字参数在调用函数时用户可以传入任意个数关键字参数(个数可变),只是需要含参数名,而且定义关键字参数在函数内部自动组装为一个 dict 。

8.3.5 命名关键字参数

对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。至于到底传入了哪些,就需要在函数内部通过 kw 检查。以 person() 函数为例,我们希望检查是否有 city 和 job 参数,但是调用者仍可以传入不受限制的关键字参数。可以加下QQ群:533807627

复制代码

def person(name, age, **kw):

if 'city' in kw:

# 有city参数

pass

if 'job' in kw:

# 有job参数

pass

print('name:', name, 'age:', age, 'other:', kw)

person('Jack', 24, city='Beijing', addr='Chaoyang', zipcode=123456)

复制代码

57. 命名关键字参数,只接受指定名字的关键字参数。命名关键字参数必须传入参数名。如果没有传入参数名,调用将报错(看作位置参数)。

58. 命名关键字参数需要一个特殊分隔符 *,* 后面的参数被视为命名关键字参数,如果缺少 *,Python 解释器将无法识别位置参数和命名关键字参数。如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符 * 。

59. 命名关键字参数可以有缺省值,从而简化调用。

def person(name, age, *, city, job):

print(name, age, city, job)

person('Jack', 24, city='Beijing', job='Engineer')    # 结果:Jack 24 Beijing Engineer

def person(name, age, *args, city, job):

print(name, age, args, city, job)

person('Jack', 24, city='Beijing', job='Engineer')    # 结果:Jack 24 () Beijing Engineer

person('Jack', 24, 1, 2, 3, city='Beijing', job='Engineer')    # 结果:Jack 24 (1, 2, 3) Beijing Engineer

def person(name, age, *, city='Beijing', job):

print(name, age, city, job)

person('Jack', 24, job='Engineer')        # 结果:Jack 24 Beijing Engineer

60. 关键字参数,调用者可以传或不传关键字参数,关键字参数将在函数内部组成 dict ;命名关键字参数调用者必须传入所有的参数(定义缺省值的除外),而且需要传入参数名,但是不组成 dict 。命名关键字参数只是限制参数的名字;

8.3.6 参数组合

61. 在 Python 中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数这 5 种参数组合使用。但参数定义的顺序必须是:参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

复制代码

def f1(a, b, c=0, *args, **kw):

print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)

f1(1, 2)                        # 结果:a = 1 b = 2 c = 0 args = () kw = {}

f1(1, 2, 3)                     # 结果:a = 1 b = 2 c = 3 args = () kw = {}

f1(1, 2, 3, 'a', 'b')           # 结果:a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}

f1(1, 2, 3, 'a', 'b', x=99)     # 结果:a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}

args = (1, 2, 3, 4)

kw = {'d': 99, 'x': '#'}

f1(*args, **kw)                 # 结果:a = 1 b = 2 c = 3 args = (4,) kw = {'x': '#', 'd': 99}

# *args相当于传入tuple中的数字

复制代码

复制代码

def f2(a, b, c=0, *, d, **kw):

print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)

f2(1, 2, d=99, ext=None)    # 结果:a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}

args = (1, 2, 3)

kw = {'d': 88, 'x': '#'}

f2(*args, **kw)             # 结果:a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}

# 若把 kw 中的第一个 key d 改为其它会报错,因为没有传入命名关键字参数

复制代码

8.4递归函数

一个函数在内部调用自身本身,这个函数就是递归函数。典型的例子就是计算阶乘。

# n! = 1 x 2 x 3 x ... x n

# (n-1)! = 1 x 2 x 3 x ... x (n-1)

# n! = (n-1)! x n

def fact(n):

if n==1:

return 1

return n * fact(n - 1)

复制代码

# fact(5)计算过程

===> fact(5)

===> 5 * fact(4)

===> 5 * (4 * fact(3))

===> 5 * (4 * (3 * fact(2)))

===> 5 * (4 * (3 * (2 * fact(1))))

===> 5 * (4 * (3 * (2 * 1)))

===> 5 * (4 * (3 * 2))

===> 5 * (4 * 6)

===> 5 * 24

===> 120

复制代码

汉诺塔的移动可以用递归函数非常简单地实现。

复制代码

def move(n, a, b, c):   #将n个盘从a柱移到到c

if n ==1:

print(a, '-->', c)  #a柱为一个盘时,将仅有的一块盘a柱移动到c柱

return

else:

move(n-1, a, c, b)  #a柱盘多于一个时,将n-1个盘从a柱移动到b柱

print(a, '-->', c)  #当a柱剩一个盘时,将这个盘移动到c柱

move(n-1, b, a, c)  #将n-1盘从b柱移动到c

move(4, 'a', 'b', 'c')

复制代码

9. 高级特性

9.1 切片 slice  取 list 、tuple、str 的部分元素

复制代码

L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']

print(L[0:3])     # L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3

print(L[:3])      # 如果第一个索引是0,可以省略

print(L[1:3])     #从索引1开始,取出2个元素出来

# 结果:['Michael', 'Sarah', 'Tracy']

# 结果:['Michael', 'Sarah', 'Tracy']

# 结果:['Sarah', 'Tracy']

print(L[-3:])      # 从索引-3开始开始取,一直到结束

print(L[-3:-1])    # 从索引-3开始取,直到索引-1,但不包括-1

# 结果:['Tracy', 'Bob', 'Jack']

# 结果:['Tracy', 'Bob']

print(L[0:5:2])    # 从索引0到索引4,每2个取一个

# 结果:['Michael', 'Tracy', 'Jack']

复制代码

对 list( range() ) 取部分元素。

复制代码

L = list(range(100))

print(L)

print(L[:10])    # 取前十个元素

print(L[-10:])    # 取后十个元素

print(L[11:21])  # 取11-20个元素

print(L[:20:2])    # 取前20个元素,每2个取一个

print(L[::5])    #取所有元素,每5个取一个

print(L[:])      # 取所有元素

复制代码

对 tuple、str 取部分元素。

print((0, 1, 2, 3, 4)[:3])

print('ABCDEFG'[:3])

print('ABCDEFG'[::2])

phone_number = '138-6666-0006'

hiding_number = phone_number.replace(phone_number[:9],'*'*9)

print(hiding_number)

# 结果:*********0006

set 、dict 不可 slice。

9.2 迭代  遍历可迭代对象

复制代码

# 迭代 list tuple

L=[1, 2, 3, 4]

for a in L:

print(a)

T=(1, 2, 3, 4)

for b in T

print(b)

复制代码

复制代码

# 迭代 dict 的 key

d = {'a': 1, 'b': 2, 'c': 3}

for key in d:

print(key)

# 结果:

b

a

c

# 迭代 dict 的 value

d = {'a': 1, 'b': 2, 'c': 3}

for value in d.values():

print(value)

# 结果:

2

3

1

# 迭代 dict 中的 key 与 value

d = {'a': 1, 'b': 2, 'c': 3}

for k, v in d.items():

print('k:',v)

# 结果:

b: 2

c: 3

a: 1

复制代码

复制代码

# 迭代字符串

for ch in 'ABC':

print(ch)

# 结果:

A

B

C

复制代码

62. 当我们使用 for 循环时,只要作用于一个可迭代对象,for 循环就可以正常运行,而不太关心该对象究竟是 list 还是其他数据类型。可以通过 collections 模块的 Iterable 进行类型判断。

复制代码

from collections import Iterable

print(isinstance('abc', Iterable))           # str是否可迭代

print(isinstance([1,2,3], Iterable))        # list是否可迭

print(isinstance({1, 2, 3},Iterable))       # set是否可迭代

print(isinstance({'a':2 ,'b':2},Iterable))    # dict是否可迭代

print(isinstance(123, Iterable))            # 整数是否可迭代

# 结果:True

# 结果:True

# 结果:True

# 结果:True

# 结果:False

复制代码

63. 如果要知道迭代的下标,可以使用内置的 enumerate 函数。

for i, value in enumerate(['A', 'B', 'C']):

print(i, value)

# 结果:

0 A

1 B

2 C

64. for 循环同时引用两个变量。

for x, y in [(1, 1), (2, 4), (3, 9)]:

print(x, y)

# 结果:

1 1

2 4

3 9

for x,y in zip( ['A', 'B', 'C'],['1', '2', '3']):

print(x + y)

# 结果:

A1

B2

C3

9.3  列表生成式

print([x * x for x in range(1, 11)])    # 生成 [1x1, 2x2, 3x3, ..., 10x10]

print([x * x for x in range(1, 11) if x % 2 == 0])    # 筛选出仅偶数的平方

# 结果:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# 结果:[4, 16, 36, 64, 100]

print([m + n for m in 'ABC' for n in 'XYZ'])    # 两层循环,生成全排列

# 结果:['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

d = {'x': 'A', 'y': 'B', 'z': 'C' }

print([k + '=' + v for k, v in d.items()])    # for循环同时使用两个变量

# 结果:['y=B', 'x=A', 'z=C']

复制代码

# 通过一个复杂的列表生成式把 dict 变成一个 HTML 表格

d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }

%s%s

print( '' )

NameScore

print( ' '.join(tds) )

print( '' )

# 字符串的join()方法可以把一个 list 拼接成一个字符串

# 结果:

NameScore

Bart59

Lisa85

Adam95

# 把打印出来的结果保存为一个html文件,就可以在浏览器中看到效果

复制代码

# lower() 函数的参数类型只能是 str ,用列表生成器修改列表 L1 ,保证lower() 正确调用

L1 = ['Hello', 'World', 18, 'Apple', None]

L2 = [x.lower() for x in L1 if isinstance (x, str)]

print(L2)

# 结果:['hello', 'world', 'apple']

9.4 生成器 generator可以加下QQ群:533807627

列表容量有限,而且占用很大的存储空间。通过生成器,列表元素可以按照某种算法推算出来,可以在循环的过程中不断推算出后续的元素。

9.4.1 把列表生成式改成 generator

L = [x * x for x in range(10)]    # 列表生成器

g = (x * x for x in range(10))    # 生成器 把[]改成()

print(g)

# 结果: at 0x1022ef630>

打印出 generator 的每个元素有两种方法:一种是通过 next() 获得;二是通过 for 循环 (一般用此方法)。

复制代码

# 通过 next() 打印出 generator 的每个元素

g = (x * x for x in range(3))

print(next(g))

print(next(g))

print(next(g))

print(next(g))  # 没有更多的元素时,抛出StopIteration的错误

# 结果:

0

1

4

Tracebacke (most recent call last):

File xxxxx,line x , in xx

StopIteration

复制代码

复制代码

# 通过 for 循环来迭代

g = (x * x for x in range(3))

for n in g:            # 不会产生 StopIteration 的错误

print(n)

# 结果:

0

1

4

复制代码

9.4.2 通过函数实现复杂逻辑的 generator

如果推算的算法比较复杂,用类似列表生成式的 for 循环无法实现的时候,还可以用函数来实现。

65. generator 的函数,在每次调用 next() 的时候执行,遇到 yield 语句返回,再次执行时从上次返回的 yield 语句处继续执行。

复制代码

# 用函数生成斐波拉契数列(除第一个和第二个数外,任意一个数都可由前两个数相加得到)1, 1, 2, 3, 5, 8, 13, 21, 34, ...

def fib(max):

n, a, b = 0, 0, 1

while n < max:

yield b                              # 把函数中的 return 改为 yield,函数就变成 generator

a, b = b, a + b

n = n + 1

return 'done'

f = fib(6)

print(f)

# 结果 :

for n in f:

print(n)

# 结果 :

1

1

2

3

5

8

复制代码

a, b = b, a + b 的解释

复制代码

# 用函数生成杨辉三角

def triangles():

L = [1]

while True:

yield L

L.append(0)

L = [L[i-1] + L[i] for i in range(len(L))]

n = 0

for t in triangles():

print(t)

n = n + 1

if n == 10:

break       # 如果没有 break ,将无限循环

# 结果:

[1]

[1, 1]

[1, 2, 1]

[1, 3, 3, 1]

[1, 4, 6, 4, 1]

[1, 5, 10, 10, 5, 1]

[1, 6, 15, 20, 15, 6, 1]

[1, 7, 21, 35, 35, 21, 7, 1]

[1, 8, 28, 56, 70, 56, 28, 8, 1]

[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]

复制代码

杨辉三角的算法解释(来源:半分幻的凶鳥)

9.5 迭代器 Iterator

可以用 for 循环的对象统称为可迭代对象 Iterable 。包括:list tuple dict set str / generator [isinstance(xxx,Iterable)]

可以被 next() 函数调用并不断返回下一个值的对象称为迭代器 Iterator 。生成器都是 Iterator 对象 [isinstance(xxx,Iterator)]

Python 的 Iterator 对象表示的是一个数据流,Iterator 对象可以被 next() 函数调用并不断返回下一个数据,直到没有数据时抛出 StopIteration 错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过 next() 函数实现按需计算下一个数据,所以 Iterator 的计算是惰性的,只有在需要返回下一个数据时它才会计算。Iterator 甚至可以表示一个无限大的数据流,例如全体自然数。而使用 list 是永远不可能存储全体自然数的。可以加下QQ群:533807627

使用 iter() 函数可以把 list tuple dict set str 等 Iterable 变成 Iterator。

复制代码

from collections import Iterator

print(isinstance([], Iterator))     # 结果:False

print(isinstance({}, Iterator))     # 结果:False

print(isinstance('', Iterator))     # 结果:False

print(isinstance(iter([]), Iterator))     # 结果:True

print(isinstance(iter({}), Iterator))   # 结果:True

print(isinstance(iter(''), Iterator))     # 结果:True

复制代码

小结:

文中对 list 、tuple、dict、set 的区别与联系写的不够清晰,在这里再总结一下

有/无序    可切片    可迭代    可列表生成    len()    删除    添加    更改

list    有    可    可[enumerate()]    可    可    .pop(索引)/.remove(元素)/del [索引]    .append(元素)/.insert(索引,元素)/.extend([])    [索引]=

tuple    有    可    可    —    可    —    —    —

dict    无    不可    可[key/.values()/.items()]    —    可    .pop(key)/del [key]    [key]=/.update({})    [key]=

set    无    不可    可    —    可    .remove(元素)/.discard(元素)    .add(元素)

自己如何确定目标

在生活中学会不断挖掘自己的潜力。我们都是一个普通人,可能并不清楚自己到底在哪方面占有优势。所以,学着在生活中找到自己的优势,并根据优势选择一定的就业方向。

不随波逐流。不要看周围的人做什么,自己就做什么,也许别人做的并不适合你。别人的优势很可能会成为你的劣势。所以,坚定自己的想法,让自己知道那些方面适合自己,自己可以胜任。

不断尝试可能成为自己的优势。你不知道什么适合自己,所以才要大胆、勇敢地尝试。找到一种可以属于你的独特的优势。

坚定信念。一旦你坚定了自己的信念,就不要被别人的意见或是讽刺或是嘲笑所干扰。别人不是你,不懂的你在想什么,不清楚你开始这件事的源头。你的事情,不了解你的人,没有资格轻易评说。

不茫然,不多想。别让太多的事干扰到你奋斗下去的信念。梦想不容许太多的杂念。那些杂念只会让你的心愈来愈脆弱,多为一个人考虑,到头来,伤害的还是自己。

选择自己学习方法

每个人都有适合自己的方法,有的人去选择自学,有的人选择看视频学习,有的人选择报名培训班,那在这个时候,你就要自己考虑清楚,到底那样对的帮助是最大的,个人觉得是跟着培训班最好的,毕竟人家的实战项目多,我们学软件开发的都知道实战项目对于学好一门语言是 很重要的。

学习python有那些误区

具体里面的误区非常的多,那些就不需要我去写出来,我给你说的一般都是心态的问题,首先一个觉得自己会java和c++,然后我学习python就很牛,但是你要知道语言是有很多相同的地方,但是不是通用,一定要自己学习的仔细。还有一种就是觉得我不会英语,我要先去把英语学习好在来学python。因为自己想还坏主意然后学习,这样的都是容易找进误区的。