Python

官方文档

https://docs.python.org/zh-tw/3.7/library/functions.html#abs

语法

print

print-explain

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'忽略错误的字节

在操作字符串时,我们经常遇到strbytes的互相转换。为了避免乱码问题,应当始终坚持使用UTF-8编码对strbytes进行转换。

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对象,但listdictstr虽然是Iterable,却不是Iterator

Iterable变成Iterator

listdictstrIterable变成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()函数接收两个参数,一个是函数,一个是Iterablemap将传入的函数依次作用到序列的每个元素,并把结果作为新的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