简单语法
-
退出python交互模式
exit()
-
输出
print()
-
输入
input()
a = 5
b = input('你的输入:') #输入提示语
print("result",a+b) #中间会有空格隔开
print('''1
2
3''') #用三个单引号包裹 打印会换行
-
空值
None
数据类型
数值
-
科学计数法
1.23e9
1.23x10^91.2e-5
0.000012 -
除
/
-
整除
//
-
余数
%
9 / 3 # 3.0
10//3 # 3
10%3 # 1
布尔型
True
False
-
或
or
(a or b) -
且
and
(a and b) -
非
not
(not a)
字符型
-
转义符
\
表示的字符就是 -
r''
表示不转义print(r' ')
' ' -
获取某字符的ASCII值
ord()
-
获取某ASCII值的字符
chr()
ord('a') # 97
chr(97) # 'a'
- 整数编码(十六进制)
'u4e2du6587' #'中文'
- bytes 是以字节为单位的数据类型,用于保存和传输,可以节省空间
bytes类型的数据用带b
前缀的单引号或双引号表示
x = b'abc'
y = b"abc"
字符方法
-
字符型转成bytes
encode()
-
bytes转成字符型
decode()
'ABC'.encode('ascii') # b'ABC'
'中文'.encode('utf-8') # b'xe4xb8xadxe6x96x87'
b'ABC'.decode('ascii') # 'ABC'
b'xe4xb8xadxe6x96x87'.decode('utf-8') # '中文'
b'xe4xb8xadxff'.decode('utf-8', errors='ignore') # '中' 小部分无效字节,忽略它
-
获取字符长度
len() 【 也可获取bytes字节数】
len('ABC') # 3
len(b'ABC') # 3
len('中文'.encode('utf-8')) # 6
-
字符格式化
用 % 占位,用变量填充模板
%d
-- 整数%s
-- 字符串%f
-- 浮点数%x
-- 十六进制整数
用了占位符还想输%
,可以用%%
来转义
'Hello, %s' % 'world' # 'Hello, world'
'name: %s,age: %d' % ('李白',32) # 'name: 李白,age: 32'
'%2d-%02d' % (3, 1) # '3-01'
'%.2f' % 3.1415926 # '3.14'
'growth rate: %d %%' % 7 #'growth rate: 7 %'
format()
第二种格式化方法
'Hello, {0}, 成绩提升了 {1}%'.format('小明', 17.125)
#'Hello, 小明, 成绩提升了 17.125%'
'Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125)
#'Hello, 小明, 成绩提升了 17.1%'
列表类型
list 是python内置的一种数据类型
list 是一种有序的集合,可以随时添加和删除其中的元素。【也就是数组咯】
创建
students = ['李白','杜甫','白居易']
取值
len(students) # 3
students[0] # '李白'
students[2] # '白居易'
### 可以逆序
students[-1] # '白居易'
students[-2] # '杜甫'
-
获取list长度
len(list)
len(students) # 3
-
添加元素到末尾
list.append(value)
students.append('小胖')
-
插入元素到指定位置
list.insert(i,value)
students.insert(1,'小胖')
-
删除list末尾元素
list.pop()
students.pop() # '白居易'
-
删除指定位置元素
list.pop(i)
students.pop(1) # '杜甫'
-
排序
list.sort() 改变本身
a = ['c', 'b', 'a'] a.sort() a # ['a', 'b', 'c']
元组类型
tuple 是另一种有序的集合,特点为一旦初始化,元素就不能重新赋值。且它也没有能操作元素的方法。
创建
ages = (16,18,30)
取值
len(ages) # 3
ages[2] # 30
ages[0] # 16
特别注意
ages = () # 空元组
ages = (1) # 并不是元组,而是1
ages = (1,) # 包含一个元素的元组
字典
dict 类型,全称 dictionary,其他语言里称为 map
,使用键值存储,查找速度快。
ages = {
'李白':17,
'杜甫':18,
'白居易':19
}
ages['李白'] # 17
写
ages['李白'] = 50
读
ages['唐太宗'] # 报错,不存在对应的key
ages.get('唐太宗') # None
ages.get('唐太宗',-1) # -1
####或者
'唐太宗' in ages # False
删除元素
ages.pop('李白')
set
set 和 dict类似,也是一组key的集合,但不存储value,可以看成数学意义上的无序和无重复元素的集合。
创建一个set,需要提供一个list作为输入集合
s = set([1,2,2,3,3])
s # {1,2,3} 重复元素会被过滤
-
添加元素
s.add()
s.add(4) # {1,2,3,4} s.add(4) # {1,2,3,4} 重复添加的元素会被过滤
-
删除元素
s.remove()
s.remove(4) # {1,2,3} s.remove(4) # 报错,不存在 4
-
交集 并集
s1 = set([1,2,3]) s2 = set([2,3,4]) s1 & s2 # {2,3} s1 | s2 # {1,2,3,4}
基本语法
注意语法的冒号
条件判断
if <条件判断1>:
<执行1>
elif <条件判断2>:
<执行2>
elif <条件判断3>:
<执行3>
else:
<执行4>
循环
names = ['李白','杜甫','白居易']
for name in names:
print(name)
for i in range(100): # 从0开始,小于100的整数
print(i)
n = 99
while n > 0:
print(n)
n = n - 2
break 退出循环
continue 跳过该次循环
函数
常用函数
-
数学函数
abs() 绝对值
abs(-20) # 20 abs(1.34) # 1.34
max() 取最大值
max(1,1.78,-5,55.55) # 55.55
hex() 数字转十六进制字符
hex(255) # '0xff'
-
数据类型转换
int('123') # 123 int(12.34) # 12 转整数 float('12.34') # 12.34 float('222') # 222.0 转浮点数 str(1.23) # '1.23' 转字符型 bool(1) # True 转布尔型 list(range(5)) # 转列表
函数定义
格式
def 函数名(参数):
def plus(x,y):
return x+y
空函数
def fun():
pass # 用 pass 占位,防止报错
返回多个值
实际上是返回一个tuple,赋值操作时tuple特性会逐一赋值
def add(x,y):
return x+1,y+1
a,b = add(4,7)
print(a,b) # 5 8
c = add(4,7)
print(c) # (5,8)
默认参数(可选参数)
def fun(x = 5) 提前给予默认值
def fun(x = 5):
return x*x
fun() # 25
fun(4) # 16
当可选参数较多时,调用时可选择性输入
def login(name,age = 18,city = "杭州"):
pass
login('小明',city = "常州") # 调用时,选择性输入
可变参数(多个参数)
*形参 定义时,形参会是一个tuple来接收所有参数
def sum(*num):
res = 0
for i in num:
res = res + i
return res
sum() # 0
sum(3,1,6) # 10
*实参 调用时,允许直接使用 list 和 tuple,相当于直接赋给形参了
sum(*[1,2,3]) # 6
sum(*(2,3,6)) # 11
关键字参数
**形参 定义时,用dict接收所有参数
def func(**some):
print(some)
func() # {}
func(3) # 报错,不接受该种形式传参
func(name = '小白',age = 18) # {'name': '小白', 'age': 18}
####### 修改
def func(lv = 0,**some):
print(some)
func() # {}
func(3) # {}
func(name = '小白',age = 18) # {'name': '小白', 'age': 18}
**实参 调用时,直接使用dict传递,形参获得实参的拷贝
obj = {
'name':'小白',
'age':18,
}
func(**obj) # {'name': '小白', 'age': 18}
命名关键字参数
只接收特定key的参数,用*分隔
def note(name,age,*,city,job):
print(name,age,city,job)
note('小白',18,city="杭州",job='teacher') # 小白 18 杭州 teacher
note('小白',18) # 报错,缺少2个 keyword-only arguments
#### 修改
def note(name,age,*,city = "常州",job):
print(name,age,city,job)
note('小白',18,job='teacher') # 小白 18 杭州 teacher
note('小白',18) # 报错,缺少1个 keyword-only arguments
参数组合
参数在定义时可以组合使用,但必须保证一定的顺序,该顺序为
必选参数 → 默认参数 → 可变参数 → 命名关键字参数 → 关键字参数
递归函数
def fact(n):
if n == 1:
return 1
return n * fact(n-1)
防止栈溢出
解决递归调用栈溢出的方法是通过尾递归
优化
尾递归 在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。
示例函数由于使用了乘法表达式,所以就不是尾递归了。尾递归要求只能返回一个表达式,所以,我们就需要把上一次的执行结果放到参数中传递下去。
def fact(n,result = 1):
if n == 1:
return result
return fact(n-1,n*result)
不过python解释器并未对尾递归做优化,所以栈溢出还是会存在
高级特性
切片:
# 获取list或tuple指定索引范围的数据
L = [1,2,3,"haha"]
L[0:3] # [1,2,3] 序号0开始,不包括序号3
L[:3] # 同上
L[-2:] # [3, 'haha'] 支持倒数序号
L[-2:-1] # [3]
L[:2:2] # [1] 前2个,每两个取一个
L[::2] # [1,3] 所有元素,每两个取一个
复制list
L[:] # 复制了L
字符切片
'ABCDEFG'[:3] # 'ABC'
'ABCDEFG'[::2] # 'ACEG'
迭代:
for循环遍历
迭代list或tuple
a = [1,2,3]
for i in a:
print(i)
迭代dict
# 迭代顺序不一定
d = {'a': 1, 'c': 2, 'b': 3}
for key in d:
print(key)
# a
# c
# b
# 迭代 value
d = {'a': 1, 'c': 2, 'b': 3}
for value in d.values():
print(value)
# 迭代 key & value
d = {'a': 1, 'c': 2, 'b': 3}
for k, v in d.items():
print(k,v)
# a 1
# c 2
# b 3
迭代字符串
for ch in 'ABC':
print(ch)
# A
# B
# C
判断是否可迭代 通过collections模块的Iterable类型判断
from collections import Iterable
isinstance('abc', Iterable) # True str是否可迭代
isinstance([1,2,3], Iterable) # True list是否可迭代
isinstance(123, Iterable) # False 整数是否可迭代
迭代下标 -- Python内置的enumerate函数
# enumerate
for i, value in enumerate(['A', 'B', 'C']):
print(i, value)
# 0 A
# 1 B
# 2 C
迭代内容
for x, y in [(1, 1), [2, 4], (3, 9)]:
print(x, y)
# 1 1
# 2 4
# 3 9
## 子 tuple 或 子 list 长度只能为 2
列表生成式:
list()
list(range(1, 11)) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
生成更复杂的列表
### 常规做法
L = []
for x in range(1, 11):
L.append(x * x)
print(L)
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
### 类似map的做法
[x * x for x in range(1, 11)]
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[x * x for x in range(1, 11) if x % 2 == 0]
# [4, 16, 36, 64, 100] 加判断
[m + n for m in 'ABC' for n in 'XYZ']
# ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ'] 双重循环
小结: 复杂的列表生成式包含js中map
和filter
方法,并且扩展性更大,可以循环dict,还可以可以双重循环,总的来说自由度更高,使用需要上点心。
生成器:
不必创建完整的list,边循环边推演获得后续元素,从而可以节约空间。这种机制被称为生成器:generator
L = [x * x for x in range(10)] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
g = (x * x for x in range(10)) # <generator object <genexpr> at 0x000000CC0A38A518>
和列表生成器的区别就在于外层是()
获取generator的下一个元素
next(g) # 0
next(g) # 1
next(g) # 4
next(g) # 9
...
循环generator
g = (x * x for x in range(10))
for n in g:
print(n)
# 0
# 1
# 4
# ...
# 81
generator函数
#### 普通斐波那契数列
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a + b
n = n + 1
return 'done'
fib(5) # 1
# 1
# 2
# 3
# 5
# 'done'
#### generator函数 yield关键字
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done' # 执行到这句会终止函数 但是返回值无法直接获取
fib(5) # <generator object fib at 0x0000003C89A1A570>
for n in fib(5):
print(n)
# 1
# 1
# 2
# 3
# 5
generator函数的执行顺序
### 遇到 yield就中断,但依靠循环可以不断执行下去
def odd():
print('step 1')
yield 1
print('step 2')
yield(3)
print('step 3')
yield(5)
a = odd() # a赋值成一个generator对象
next(a) # 打印'step1' 返回值为1
next(a) # 打印'step2' 返回值为3
next(a) # 打印'step3' 返回值为5
小结: 生成器有两种形式,简单逻辑通过()
包装即可,复杂逻辑则需要通过函数形式并配合yield
关键字实现。两种方式都是为了保存某种算法,通过算法可以计算推导出每一项。
迭代器:
可直接作用于for
循环的对象统称为可迭代对象:Iterable
判断对象是否可迭代
from collections import Iterable
isinstance([], Iterable) # True
isinstance({}, Iterable) # True
isinstance('abc', Iterable) # True
isinstance((x for x in range(10)), Iterable) # True
isinstance(100, Iterable) # False
可以被next()
方法调用并不断返回下一个值的对象称为迭代器:Iterator
判断对象是否是迭代器对象
from collections import Iterator
isinstance([], Iterator) # False
isinstance({}, Iterator) # False
isinstance('abc', Iterator) # False
isinstance((x for x in range(10)), Iterator) # True
isinstance(100, Iterator) # False
### iter()方法可将 list、dict、str等变成迭代器对象
isinstance(iter([]), Iterator) # True
isinstance(iter('abc'), Iterator) # True
函数式编程
高阶函数
- map/reduce
map 接收两个参数,一个是函数,一个是
Iterable
,新结果作为Iterator
返回
def f(x):
return x * x
r = map(f,[1,2,3]) # <map object at 0x000000D84BDFFF28>
list(r) # [1,4,9] 计算 Iterator,获得完整的 list
reduce 接收两个参数,一个是函数,一个是
Iterable
,高阶函数的参数为计算结果和下一个元素
from functools import reduce
def add(x, y):
return x + y
r = reduce(add, [1, 2, 3]) # 6
### lambda函数
r = reduce(lambda x, y : x + y,[1,2,3]) # 6
- filter
filter 接收一个函数,一个
Iterable
,返回Iterator
def is_odd(n):
return n % 2 == 1
r = filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])
list(r) # [1, 5, 9, 15]
####返回所有素数
## 算法 埃氏筛法
def origin(): # 初始序列
n = 2
while True:
yield n
n = n + 1
def not_divisible(n):
return lambda x: x % n != 0 # 表示不能整除
def primes(): # 素数序列
arr = origin()
while True:
n = next(arr) # 返回序列的第一个数
yield n
arr = filter(not_divisible(n),arr) # 筛除部分非素数
- sorted
sorted 接收一个
Iterable
,接收一个key
函数,返回一个list
a = [36, 5, -12, 9, -21]
sorted(a) # [-21, -12, 5, 9, 36]
print(a) # [36, 5, -12, 9, -21] 不会改变原列表
####添加 key函数
sorted(a, key=abs) # [5, 9, -12, -21, 36]
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)
# ['about', 'bob', 'Credit', 'Zoo']
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
# ['Zoo', 'Credit', 'bob', 'about'] 反向
####自定义 key函数
def by_name(t):
return t[0].lower()
sorted([('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)],key=by_name)
# [('Adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88)]
### 特别注意
sorted("bacdge") # ['a', 'b', 'c', 'd', 'e', 'g']
返回函数(闭包)
即函数作为返回值,也可以称为函数生成器
### python的作用域貌似有点严格
def createCounter():
n = 0
def counter():
nonlocal n # nonlocal 关键字 用来声明变量需要向上一层寻找
n = n + 1
return n
return counter
counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5
### 引用类型不需要 nonlocal关键字
def createCounter():
arr = [0]
def counter():
arr[0] = arr[0] + 1
return arr[0]
return counter
匿名函数(lambda)
没有 return,不能遍历,不能使用 if:
else:
分支
add = lambda x,y: x + y # 带参数
add = lambda x,y: x + y if y >= 0 else x # 三元判断符
def add(x, y):
return lambda: x + y # 无参数
装饰器
增强某函数的功能,但又不希望修改原函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
### 定义一个函数做装饰器 接收一个函数 并返回一个函数
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__) # 打印函数名称
return func(*args, **kw)
return wrapper
# '@'关键字 在函数定义处设置装饰器
@log
def now():
print('today')
now()
# call now():
# today
@log
放在函数定义处等价于 now = log(now)
装饰器可传入参数 (等于多包了一层函数)
#### 装饰器传入参数
def log(text):
def decorator(func):
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
@log('execute')
def now():
print('today')
now()
# execute now()
# today
### 等价于 now = log('execute')(now)
最后的问题
now.__name__
为wrapper
#### 解决最终问题
### functools.wraps
import functools
def log(func):
@functools.wraps(func) ### 关键句 用装饰器包装 wrapper 函数
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
偏函数(Partial function)
提前给定参数的函数生成器
int('10') # 10
int('10',base=2) # 2
### 偏函数 2进制转10进制
import functools
int2 = functools.partial(int,base=2) # 原函数 和 给定参数
int2('10') # 2
小结
偏函数可以固定参数,用来简化函数调用,在原函数分支较多,或者参数过多的情况下,可以用偏函数优化。