Python
Python
沐飞官方文档
https://docs.python.org/zh-tw/3.7/library/functions.html#abs
语法
input
s = input('birth: ')
birth = int(s) #str转化为int
if birth < 2000:
print('00前')
else:
print('00后')
注释
#这是注释符
代码块 :
当语句以冒号:
结尾时,缩进的语句视为代码块
坚持使用4个空格的缩进
a = 100
if a>90:
print("大于")
else:
print("小于")
数据类型
整型
可以使用_
对比较长的数进行分割,效果一样
100000000 100_000_000
#十六进制
0xa1b2c3d4 0xa1b2_c3d4
浮点数
科学计数法:把10用e代替 1.23x109就是1.23e9
,或者12.3e8
整数运算永远是精确的(除法也是精确的),而浮点数运算则可能会有四舍五入的误差。
字符串
转义字符
print("I\'m ok")
#或者使用 r‘’
print(r'I'm Ok)
Python还允许用
r''
表示''
内部的字符串默认不转义
换行
除了“\n” Python允许用
'''...'''
的格式表示多行内容
print('''line1
... line2
... line3''')
布尔值
Ture False
and or not
>>> True and True
True
>>> True or True
True
>>> not True
False
空值
空值是Python里一个特殊的值,用None
表示。None
不能理解为0
,因为0
是有意义的,而None
是一个特殊的空值。
变量
a = 1
t_007 = 't_007'
Answer = True
常量
PI = 3.14
除法
/
除法计算结果是浮点数整数的地板除
//
永远是整数
乘法
r**2 #表示r的2次方
字符串
单个字符的编码,Python提供了ord()
函数获取字符的整数表示,chr()
函数把编码转换为对应的字符:
>>> ord('A')
65
>>> ord('中')
20013
>>> chr(66)
'B'
>>> chr(25991)
'文'
由于Python的字符串类型是str
,在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输,或者保存到磁盘上,就需要把str
变为以字节为单位的bytes
。
Python对bytes
类型的数据用带b
前缀的单引号或双引号表示:
x = b'ABC'
要注意区分
'ABC'
和b'ABC'
,前者是str
,后者虽然内容显示得和前者一样,但bytes
的每个字符都只占用一个字节。
>>> 'ABC'.encode('ascii')
b'ABC'
>>> '中文'.encode('utf-8')
b'\xe4\xb8\xad\xe6\x96\x87'
>>> '中文'.encode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
encode()
可以将unicode
编码为指定的byte
如果要在网络上传输,或者保存到磁盘上
decode()
可以将byte
转化为unicode
网络或磁盘上读取了字节流
转化过程
byte
只有一小部分无效字节,可以传入*errors*='ignore'
忽略错误的字节
在操作字符串时,我们经常遇到
str
和bytes
的互相转换。为了避免乱码问题,应当始终坚持使用UTF-8编码对str
和bytes
进行转换。
print(b'\xe4\xb8\xad'.decode('utf-8',errors='ignore'))
获取长度
len()#计算str有多少个字符,会先转化为Unicode码
>>> len(b'ABC')
3
>>> len(b'\xe4\xb8\xad\xe6\x96\x87')
6
>>> len('中文'.encode('utf-8'))
6
声明utf-8编码
在.py文件开头写上
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
申明了UTF-8编码并不意味着你的
.py
文件就是UTF-8编码的,必须并且要确保文本编辑器正在使用UTF-8 without BOM
编码
整理sort(),替换repalce(‘A’,’a’)
对于不可变对象如str,b = a.replace(‘A’,’a’),a不会改变,而是创建一个新的对象,被b指向
格式化
print('hello,%s'%('me')) #类比C/C++
占位符 | 替换内容 |
---|---|
%d | 整数 |
%f | 浮点数 |
%s | 字符串 |
%x | 十六进制整数 |
小数整数位数,补0
print('%2d-%02d'%(3,1))
print('%.2f' % 3.1415926)
字符串里有%
用%%
转义
format()
print('hello,{0},成绩提升了 {1:.1f}'.format('小明',17.2))
它会用传入的参数依次替换字符串内的占位符{0}
、{1}
……,
f-string
>>> r = 2.5
>>> s = 3.14 * r ** 2
>>> print(f'The area of a circle with radius {r} is {s:.2f}')
The area of a circle with radius 2.5 is 19.62
list数组[]
特点:可变的有序列表
每个数据类型可以不同
a[0] a[1] a[2] 第一个,第二个,第三个数据
a[-1] a[-2] a[-3] 倒一个,倒二个,倒三个数据
a.append() 结尾添加元素
a.insert(1,’jack’) 把元素插入到序列位置1,之前的后移
a.pop() 删除末尾元素 a.pop(i)删除序列位置为i的元素
>>> s = ['python', 'java', ['asp', 'php'], 'scheme']
>>> len(s)
4
#list里可以再放list 访问'php'时使用s[2][1]
tuple指向不变的数组()
classmates这个tuple不能变了,它也没有append(),insert()这样的方法。
其他获取元素的方法和list是一样的,
提高代码安全性
classmates = ('Michael', 'Bob', 'Tracy')
>>> t = (1,)
>>> t
(1,)
#如果写成t=(1)看成赋值1,而不是tuple,
“可变的”tuple
>>> t = ('a', 'b', ['A', 'B'])
>>> t[2][0] = 'X'
>>> t[2][1] = 'Y'
>>> t
('a', 'b', ['X', 'Y'])
变的是tuple里的list
条件判断
age = 3
if age >= 18:
print('adult')
elif age >= 6:
print('teenager')
else:
print('kid')
注意缩进和冒号
循环
for-in
类比C\C++的for(auto e:name)
names = ['Michael', 'Bob', 'Tracy']
for name in names:
print(name)
range(5)生成序列0~4
list(range(5))
sum = 0
for x in range(101):
sum = sum + x
print(sum)
while
sum = 0
n = 99
while n > 0:
sum = sum + n
n = n - 2
print(sum)
break contiune
与C\C++相同
dict字典{} key-value
查询速度快,通过key计算位置的算法称为哈希算法(Hash)
dict的key必须是不可变对象(list无法用作key)
两种存入方式
>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
>>> d['Michael']
95
>>> d['Jack'] = 90
>>> d['Jack']
90
>>> d['Jack'] = 88
>>> d['Jack']
88
判断Key是否存在
一是通过in
判断key是否存在:
>>> 'Thomas' in d
False
二是通过dict提供的get()
方法,如果key不存在,可以返回None
,或者自己指定的value:
>>> d.get('Thomas')
>>> d.get('Thomas', -1) #若为找到则返回自定义的值-1
-1
删除key
d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
print(d)
d.pop('Tracy')
print(d)
set
set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。
#要创建一个set,需要提供一个list作为输入集合:
s = set([1, 1, 2, 2, 3, 3])
print(s)#输出结果为{1, 2, 3} 重复的被过滤掉
添加元素add()
s.add(4)#添加重复的没有效果
删除元素remove()
s.remove(4)
数学意义
无序和无重复元素的集合,因此,两个set可以做数学意义上的交集
、并集
等操作
>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s1 & s2
{2, 3}
>>> s1 | s2
{1, 2, 3, 4}
函数
函数定义
def my_abs(x):
if x>0:
return x
else:
return -x
空函数
def nop():
pass #占位符
参数检查
1.参数个数不对时
TypeError
: my_abs() takes 1 positional argument but 2 were given
2.数据类型检查可以用内置函数isinstance()
实现
def my_abs(x):
if not isinstance(x, (int, float)): #如果不是int 和 float类型
raise TypeError('bad operand type')#抛出错误
if x >= 0:
return x
else:
return -x
返回多个值
import 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)
返回值其实是一个tuple
import math
def quadratic(a, b, c):
x1 = (-b+math.sqrt(b**2-4*a*c))/2/a
x2 = (-b-math.sqrt(b**2-4*a*c))/2/a
return x1,x2
print('quadratic(2, 3, 1) =', quadratic(2, 3, 1))
print('quadratic(1, 3, -4) =', quadratic(1, 3, -4))
if quadratic(2, 3, 1) != (-0.5, -1.0):
print('测试失败')
elif quadratic(1, 3, -4) != (1.0, -4.0):
print('测试失败')
else:
print('测试成功')
默认参数
def enroll(name, gender, age=6, city='Beijing'):
print('name:', name)
print('gender:', gender)
print('age:', age)
print('city:', city)
除了按顺序填入参数,也可以不按顺序填入参数只要把参数名写出来enroll('Adam', 'M', city='Tianjin')
默认参数的误用
默认参数必须指向不变对象
def add_end(L=[]):
L.append('END')
return L
#改为
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
可变参数
def calc(*numbers):#*numbers表示定义可变参数
sum = 0
for n in numbers:
sum = sum + n * n
return sum
nums =(1,2,3)
print(calc(*nums))#*nums表示把nums这个list的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。
关键字参数
关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict
。
#声明格式
def person(name, age, **kw):#**kw为关键字参数
print('name:', name, 'age:', age, 'other:', kw)
#直接填入
>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
#声明dict再传入
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, city=extra['city'], job=extra['job'])
>>> 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
。
命名关键字参数
检查关键字参数是否存在
def person(name, age, **kw):
if 'city' in kw:
# 有city参数
pass
if 'job' in kw:
# 有job参数
pass
print('name:', name, 'age:', age, 'other:', kw)
命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错:
def person(name,age,*,city,birth):
print('name',name,'age:',age,'city:',city,'birth',birth)
d = {'city':10,'birth':101010}
person('a',11,**d)
和关键字参数
**kw
不同,命名关键字参数需要一个特殊分隔符*
,*
后面的参数被视为命名关键字参数。
如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*
了:
def person(name, age, *args, city='Beijing', job):
print(name, age, args, city, job)
>>> person('Jack', 24, job='Engineer')
组合参数
参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
def f2(a, b, c=0, *, d, **kw):
print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
递归函数
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
高级特性
切片
L[起始位置:终止位置:步程] #0可以忽略
L[0:3]
L[:3]
L[-2:]
L[:10:2]前是个数,每隔2个取一个
'ABCDEF'[:3] ==>'ABC'
迭代(遍历)
for in可以遍历list,tuple,和dict,字符串等可迭代对象
dict默认遍历前面的数
如果要迭代value,可以用for value in d.values()
,如果要同时迭代key和value,可以用for k, v in d.items()
判断一个对象是可迭代对象
方法是通过
collections.abc
模块的Iterable
类型判断
>>> from collections.abc import Iterable
>>> isinstance('abc', Iterable) # str是否可迭代
True
>>> isinstance([1,2,3], Iterable) # list是否可迭代
True
>>> isinstance(123, Iterable) # 整数是否可迭代
False
for in 使用两个变量
enumerate
函数可以把一个list
变成索引-元素对,这样就可以在for
循环中同时迭代索引和元素本身:
>>> 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
列表生成式
print([x*x for x in range(1,11)])
#==>>[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
print([x*x for x in range(1,11) if x%2==0])
print([m+n for m in 'ABC' for n in 'XYZ'])
#==>>['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ'] 全排列
print([x if x%2==0 else -x for x in range(1,11)])
#前面必须是if else 后面不能有else
L = ['Hello', 'World', 'IBM', 'Apple']
print([s.lower() for s in L])
前面的if是表达式,它必须根据x
计算出一个确切结果
后面的if是筛选条件
生成器
一边循环一边计算的机制,称为生成器:generator。,保存的是表达式
1.只要把一个列表生成式的[]
改成()
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>
读取值
next(g)
>>> g = (x * x for x in range(10))
>>> for n in g:
... print(n)
斐波拉契数列用列表
def lib(max):
n,a,b = 0,0,1
while n<max:
print(b)
a,b = b,a+b
n = n+1
return 'done'
a, b = b, a + b
相当于
t = (b, a + b) # t是一个tuple
a = t[0]
b = t[1]
将函数改为generator
添加yield
def odd():
print('step 1')
yield 1
print('step 2')
yield(3)
print('step 3')
yield(5)
执行顺序
与普通函数不一样,在每次调用next()
的时候执行,遇到yield
语句返回,再次执行时从上次返回的yield
语句处继续执行。
注意
o = odd()
next(o)
next(o)
next(o)
#才会按顺序执行
next(odd())
next(odd())
next(odd())
#每次会生成一个独立的generator,都是第一个值
使用捕获异常来捕获generator的return的返回值
g = fib(6)
while True:
try:
x = next(g)
print('g:', x)
except StopIteration as e:
print('Generator return value:', e.value)
break
生成杨辉三角
def triangles():
L=[1]
while True:
yield L
X=[0] +L
Y = L+ [0]
L = [X[i]+Y[i] for i in range(len(X))]
迭代器
可以被next()
函数调用并不断返回下一个值的对象称为迭代器:Iterator
。
可以使用isinstance()
判断一个对象是否是Iterator
对象
生成器都是
Iterator
对象,但list
、dict
、str
虽然是Iterable
,却不是Iterator
。
将Iterable
变成Iterator
把list
、dict
、str
等Iterable
变成Iterator
可以使用iter()
函数:
isinstance(iter([]), Iterator)
高阶函数
把函数作为参数传入,这样的函数称为高阶函数
f = abs()
f(-1) #其实就是abs(-1),因为f指向了函数abs
#将函数作为参数传入
def add(x, y, f):
return f(x) + f(y)
map()
map()
函数接收两个参数,一个是函数,一个是Iterable
,map
将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator
返回。
>>> def f(x):
... return x * x
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
可以使用list()
将惰性序列r
的所有结果计算出来
reduce()
reduce
把一个函数作用在一个序列[x1, x2, x3, ...]
上,这个函数必须接收两个参数
reduce
把结果继续把序列的下一个元素做为形参,然后调用函数
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
from functools import reduce
def add(x, y): #使用sum()可以达到一样的效果
return x+y
t = reduce(add, [1, 3, 5, 7, 9])
print(t)
def fn(x, y):
return x*10 + y
m = reduce(fn, [1, 3, 5, 7, 9])
print(m)
结合使用
reduce(fn,map(char2num,'123123'))
#调用顺序,‘1’使用char2num转换,
#然后‘2’使用char2num转换,
#调用reduce,fn作用于‘1’和‘2’,
#然后‘3’使用char2num转换,
#之后fn作用于‘3’,
#然后‘4’使用char2num转换,
#之后fn作用于‘4’
#python