Django-Vue 实战开发 第1章 Python 知识点速查

python 是一种解释型语言, 无需编译就可以利用解释器执行. 支持函数式编程和面向对象编程, 拥有动态类型系统和垃圾回收功能. 相比于java, python 以文件而不是类为基本单位, 一个python 文件里, 可以直接定义函数, 或者多个类, 或者直接的代码行, 运行python 文件会执行没有被函数或者类包裹的代码行, 相当于省略了java 里的main 函数

python 复制代码
# start.py
print('hello world')

数据类型

💡python 拥有动态类型, 因此定义变量时直接a = 1 这样赋值就好了, 解释器会自动确认a的类型, 另外a 的是数据类型不是固定的, 可以继续给a 赋值其他类型的值(有点过于灵活了)

数字|Number

python 中统一使用int 表示整数, 用float 表示小数, 它们在64位系统中占用8个字节(对应java 语言的long 和double)

python 复制代码
2 / 4
# >>0.5
2 // 4 #整除
# >>0
17 % 3 #取余
# >>2
2 ** 5 #乘方
# >>32

bool 类型只有两个取值: True 和False, 因为是int 的子类, 它可以直接当作数字参与运算, True 被视为1, False 被视为0

python 复制代码
True == 1
# >>True
True + 1
# >>2

bool 类型经常和逻辑运算符一起使用, 比如and, or 和not

python 复制代码
a = 2 < 3
# >>True
b = 2 == 3
# >>False
a and b
# >>False
not a
# >>False

另外, python 中所有非0 的数字和非空的字符串, 列表, 元组等数据都被视为True, 0, 空字符串, 空列表, 空元组等被视为False

字符串|String

python 中字符串是用单引号或者双引号包裹的任意文本, 同时支持用反斜杠符号转义

python 复制代码
# 字符串里包含"或者'时, 要使用\转义
a = "i\'m ok!"
# '''...''' 可以表示多行文本
print('''line1
line2
line3''')

如果希望字符串不进行任何转义原样输出, 可以使用r'字符串' 声明字符串

python 复制代码
# 从左到右, 第一个反斜杠是为了帮第二个反斜杠转义(因为\是特殊符号), 代表原样输出一个\, 第三个反斜杠与t组合输出一个制表符
print('制表符\\\t\\')
#>>>制表符\    \
#加r以后将原样输出
print(r'\\\t\\')
#>>>\\\t\\

字符串可以像数组一样截取, 格式是:变量[包含上标:不包含下标], 0表示第一个元素, 1表示第二个元素, 以此类推;-1 表示最后一个元素, -2表示倒数第2个元素, 以此类推

python 复制代码
str = 'hello'
# 输出第一个字符h
sub_str = str[0]
# 输出从第一个字符开始后面的所有字符hello
sub_str = str[0:]
# 输出从第一个字符到第二个字符py
sub_str = str[0:2]
# 输出从第一个字符到倒数第二个字符hell
sub_str = str[0:-1]
# 输出从倒数第四到倒数第一之间的字符ell
sub_str = str[-4:-2]

字符串可以使用* 表示复制当前字符串, 用+ 连接两个字符串

python 复制代码
str = 'hello'
# 两个str, hellohello
sub_str = str * 2
# helloworld
sub_str = str + 'world'

字符串支持使用%占位符的方式进行格式化, 支持%d(整数),%f(小数),%s(字符串), %x(十六进制整数), 如果不确定就用%s即可

  • % 方式
python 复制代码
'name:%s age:%d' % ('ted', 10)
  • 使用format()函数
python 复制代码
'name:%s age:%d'.format('ted', 10)
  • 使用f'字符串, 格式是:f"字符串{要填入的参数:格式化参数}" 或者省略格式化参数: f"字符串{要填入的参数:格式化参数}". 下述代码中, 定义了两个占位符, 第一个直接传入了变量r, 第二个传入了变量s, 并对s进行了格式化--保留了2位小数
python 复制代码
   r = 2.5
   s = 3.14 * r ** 2
   print(f'The area of the circle with radius {r} is {s:.2f}')

💡 如果要输出%本身, 需要用%%的方式转义

python 复制代码
str = 'age:%d name:%s'
str %

数组|tuple

tuple 是不可变的有序列表, 一旦初始化就不能修改, 使用() 声明.

💡 tuple 中只有一个元素时要加上逗号, 防止歧义

python 复制代码
classmates = ('a', 'b', 'c')
# 只有一个元素时要加上逗号, 防止歧义
names = (1, )
# 访问元素a
classmates[0]
# 倒序访问c
classmates[-1]
# 将classmates 中第0, 1, 2个元素非别赋值给a, b, c
a, b, c = classmates

列表|list

列表是可变的集合, 可以随时添加和删除其中的元素, 使用[] 声明

python 复制代码
# 声明
classmates = ['a', 'b', 'c']
# 获取长度
len(classmates)
# 访问第0个元素
classmates[0]
# 获取值为'x' 的元素索引, 找不到就报错
a = classmates.index('x')
# 同上, 只是限制了查找范围
a = classmates.index('x', 1, 5)
# 在指定位置插入元素
classmates.insert(1, 'd')
# 在列表末尾插入元素
classmates.append('d')
# 删除并返回最后一个元素
a = classsmates.pop()
# 删除并返回指定index 的元素
a = classmates.pop(1)
# 删除第一个值为x 的元素, 未找到时会报异常
classmates.remove('e')
# 修改第1个元素
classsmates[1] = 'e'

list 支持嵌套, 类似二维数组

python 复制代码
s = ['python', 'java', ['asp', 'jsp']]
# 访问元素
s[1]
s[2][1]

字典|dict

字典用于存储键值对, 无序集合, 使用{} 声明

python 复制代码
d = {'k1': 'v1', 'k2': 'v2'}
# 可以直接获取值和赋值
d['k1']
d['k2'] = 'vv2'
# 也可以使用get() 获取, 并提供默认值
d.get('k3', 'v3')
# 用pop() 删除元素
d.pop('k3')
# 用in 判断是否包含key
'k5' in d

💡建议使用get() 方法获取值, 因为如果dict 不存在'k1, d['k1']会报错

集合|set

set 可以看作是只有key 的dict, 它同样是无序不可重复的, 通过set() 声明, set() 函数可以接收iterable 参数, 比如list, string

python 复制代码
# 接收list参数
s = set([1, 2, 3])
# 接收字符串
s = set('a1b2c3')
s.remove(1)
s.add(2)

set 可以做数学意义上的交集, 并集等操作

python 复制代码
s1 = set([1, 2, 3])
s2 = set([2, 3, 4])
# 交集, 输出{2, 3}
s1 & s2
# 并集, 输出{1, 2, 3, 4}
s1 | s2

流程控制

条件判断|if

相比Java, Python 的各种结构体都不需要{}, 依靠缩进来确定结构

python 复制代码
age = 20
if age >= 18:
	print('adult')
elif age >= 6:
	print('teenager')
else:
	print('kid')

模式匹配|match case

如果if 条件较多, 可以使用match 语句改写

python 复制代码
score = 'B'
match score:
	case 'A':
		print('A')
	case 'B'
		print('B')
	# 默认
	case _:
		print('C')

case 后面还可以匹配多个值, 或者加条件判断

python 复制代码
age = 15
match age:
	# 创建一个变量x
	case x if x < 10:
		print(f'< 10 years old: {x}')
	case 11 | 12 | 13:
		print('11 ~ 13 years old')

match 语句可以匹配列表

python 复制代码
args = ['gcc', 'hello.c', 'world.c']
match args:
	case ['gcc']
		print('missing params')
	case ['gcc', file1, *files]:
		print('gcc ' + file1 + ','.join(files))

args 元素与['gcc'] 相同时, 会进入第一个case . 第二个case , 要求第一个字符串必须是'gcc', 第二个字符串会赋值给file1, 其余字符串赋值给files, files是一个可变参数

循环|for|while

Python 支持for...in循环 和while 循环

python 复制代码
friends = ['dog', 'cat']
for i in friends:
	print(i)

i = 0
while i < len(friends):
	print(friends[i])

和java 一样, python 也指出breakcontinue, 其中break 用来结束当前循环, continue 用来跳过一轮循环, 继续执行下一轮循环

函数

函数定义

python 中使用def 关键字指定函数, 因为参数无法指定类型, 可能需要在函数内部增加入参校验; 另外, 返回值可以有多个, python 会自动将多个返回值转化成一个tuple

python 复制代码
def test(x, y):
	nx = x + y
	ny = x - y
	return nx, ny

nx, ny = test(1, 1)

默认参数

python 的函数入参可以设置默认值, 作为可选参数, 没有默认值的作为必选参数, 不能省略

python 的参数可以按声明顺序依次填入, 也可以通过指定参数名乱序传入

python 复制代码
def test(x, y, z=1)
	return x, y, z

test(1, 2)
test(1, 2, z=3)

python 的默认参数作用域是函数, 也就是说函数定义出来以后, 默认值就被初始化了, 所有调用该函数的代码, 共用一个参数, 因此默认参数必须使用不可变类型: string, tuple 等

python 复制代码
def print_list(x, l = []):
	l.add(x)
	print(l)

print_list(1)
# >>> [1]
print_list(2)
# >>> [1, 2]

可变参数

python 函数支持设置数量可变的参数, 使用*标记, 函数会将可变参数视为tuple

python 复制代码
def add(*args):
	ret = 0
	for i in args:
		ret += i
	return ret

add(1, 2, 3)
# 加星号表示当前数组作为可变参数传入
add(*[1, 2, 3])

关键字参数

关键字参数与可变参数类似, python 会在函数内部转变成dict

python 复制代码
def add(x, y, **kw):
    print(x, y, kw)

add(1, 2, z=3)
# >>> 1, 2, {'z': 3}
# 加两个星号python 会自动将当前dict 转换成键值对
add(1, 2, **{'z': 3})

如果想要限制key, 可以这样写:

python 复制代码
# 星号后面代表关键字参数的key
def add(a, b, *, c, d)
	print(a, b, c, d)

add(1, 2, c=3, d=4)

高阶函数之函数参数

python 支持将函数赋值给一个变量, 同时这个变量可以作为参数传递给另一个函数

python 复制代码
def add(x, y, f):
		return f(x) + f(y)

# 定义变量z 指向函数abs
z = abs
# 可以通过z 实现abs的功能
print(z(-10))
# >>> 10
# 调用高阶函数add
ret = add(1, -1, z)
print(ret)
# >>> 2

python 内置了很多这样的高级函数, 例如map, reduce, filter....

map

map() 是python 的内建函数, 用来指向映射功能, 它接收两个参数, 一个是函数,一个是Iterable, map 通过遍历Iterable 参数, 依次执行传入的函数, 将该Iterable 参数映射成Iterator 返回.
💡 传入的是itreable, 返回的是iterator

python 复制代码
def f(x):
		return x * x

ret = map(f, [1, 2, 3, 4, 5])
list(r)
>>> [1, 4, 9, 16, 25]

reduce

reduce() 将一个函数作用在一个序列上, 并将函数运行结果继续和序列的下一个元素做累积计算. reduce(f, [x1, x2, x3]) = f(f(f(x1, x2), x3), x4)

python 复制代码
from functools import reduce
def fn(x, y):
		return x * 10 + y

reduce(fn, [1, 3, 5, 7, 9])

# >>> 13579

filter

filter() 用于过滤序列

python 复制代码
def is_odd(n):
		return n % 2 == 1

ret = filter(is_odd, [1, 2, 3])
list(ret)
>>> [1, 3]

sorted

sorted() 用于排序, 接收一个序列, 一个排序函数key, 一个是否反转reverse

python 复制代码
sorted([1, 7, -5, 3])
# >>> [-5, 1, 3, 7]
sorted([1, 7, -5, 3], key=abs)
# >>> [1, 3, 5, 73751]
sorted([1, 7, -5, 3], key=abs, reverse=True)
# >>> [7, 5, 3, 1]

高阶函数之返回函数

除了将函数作为变量, 还可以在函数内部定义函数, 并将它作为返回值.这种程序结构被称为闭包

python 复制代码
def lazy_sum(*args):
		def sum():
			ax = 0
			for n in args:
					ax = ax + n
			return ax
		return sum

# 调用lazy_sum 会返回一个函数
f = lazy_sum(1, 2, 3)
# >>> <function lazy_sum.<locals>.sum at 0x101c6ed90>
# 调用f 才会返回计算结果
ret = f()
# >>> 25

💡 返回的函数并没有被立刻执行, 被调用后才会真正执行. 因此返回函数应该避免使用后续会发生变化的变量

python 复制代码
# 函数count 内循环创建函数f, 输出i 的vi
def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i
        fs.append(f)
    return fs

f1, f2, f3 = count()

# 调用f1, f2, f3, 并没有返回1, 2, 3, 而是都返回了3
# 这是因为f 函数并没有立刻执行, 而是在调用时才会执行, 此时i 的值已经是3了
f1()
# >>> 3
f2()
# >>> 3
f3()
# >>> 3

💡 内层函数只能读取外层函数的变量, 不能直接修改. 如果要修改, 必须先用nonlocal 声明

python 复制代码
# 函数count 内循环创建函数f, 输出i 的vi
def count():
    fs = []
		x = 1
    for i in range(1, 4):
        def f():
						# nonlocal i
						x = x + i
            return x
        fs.append(f)
    return fs

f1, f2, f3 = count()

f1()
# >>> 报错
# 解释器会把x 当作f() 的局部变量, 它并没有被初始化, 必须使用nonlocal x
# 告诉解释器x 是外层函数的变量

匿名函数

匿名函数使用关键字lambda, 只能有一个表达式, 代表返回值

python 复制代码
lambda x : x * x
# 等价于
def f(x):
		return x * x

装饰器

装饰器(decorator)可以在代码运行期间动态增加功能. 本质上, 装饰器是一个返回函数的高阶函数, 使用@ 符号来标识要增强的函数

python 复制代码
# 定义装饰器
def log(func):
	def wrapper(*args, **kw):
		print('call %s():' % func.__name__)
		return func(*args, **kw)
	return wrapper

# 使用装饰器
@log
def now():
	print('222')

now()
# >>> call now(): 
# >>> 222

调用now() 函数, 不仅会运行now() 函数本身, 还会在运行之前执行log() 函数. 把@log 放到now() 函数的定义处, 相当于执行了now = log(now), 此时now 变量指向了新的函数, 于是调用now() 将执行新的逻辑

如果想让decorator 接入参数, 需要编写一个返回decorator 的高阶函数.

python 复制代码
def log(text):
	def decorator(func):
		@functools.wraps(func)
		def wrapper(*args, **kw):
			print('%s %s()' % (text, func.__name__))
			return func(*args, **kw)
		return wrapper
	return decorator

@log('execute')
def now():
	print('2023-10-11')

now()
# >>> execute now(): 2023-10-11

这段代码首先执行log('execute'), 返回decorator 函数, 再调用返回的函数, 参数是now 函数, 返回值是wrapper 函数. 因为最后返回的是wrapper 函数, 这导致now.name 会返回'wrapper', 可以用functools.wraps 来处理

面向对象

python 使用class 关键字声明类,创建实例使用类名() 💡类中定义的函数, 第一个参数必须是self, 代表当前实例

python 复制代码
class Cat(object):
	def miaomiao(self):
		print('miaomiao')

cat = Cat()
cat.miaomiao()

封装

python 中, 类的构造函数使用__init__ 声明. python作为动态语言, 也可以直接给一个实例变量增加属性

python 复制代码
class Cat:
	# 类属性, 所有实例共用
	class_name = 'cat'
	def __init__(self, name):
		self.name = name
		
	def print_name(self):
		print(self.name)

cat = Cat("mimi")
# 手动绑定age 属性
cat.age = 1

如果想声明私有属性, 可以在属性名称前面加上两个下划线

python 复制代码
class Cat:
	def __init__(self, name):
		self.__name = name

	def set_name(self, name):
		self.__name = name

	def get_name(self):
		return self.__name

继承

类名后面的括号用来注明它的父类, 默认继承object类, 可以省略. 另外, python 支持多重继承

python 复制代码
class Animal:
	def eat(self):
		print('Animal is eating')

class Pet:
	def play(self):
		print('Pet is playing')

class Cat(Animal, Pet):
	pass

cat = Cat()
cat.eat()
cat.play()

多态

基于继承, 可以将一个类重写为多个子类, 子类的数据类型可以被看作父类, 但是他们有不同的表达

python 复制代码
def test(animal):
	animal.eat()

cat = new Cat()
test(cat)

python 的多态更加自由, 入参没有限制类型, 只要它有eat() 方法就行

并发编程

协程

协程是一种特殊的函数, 可以在内部中断, 然后在再次被调用时, 从上次中断的地方继续执行 python 的协程基于generator 实现, 通过yield (暂停并返回)来标记中断点, 从而创建一个协程

python 复制代码
def consume():
	ret = 'start'
	while True:
		#程序在此处阻塞, 直接返回ret, 下次调用才会执行param = ret
		param = yield ret
		if not param:
			return
		print('CONSUMER consuming %s ' % param)
		ret = 'end'

def produce(c):
	# 启动并调用generator
	c.send(None)
	param = 0
	while param < 3:
		param += 1
		print('PRODUCER producing %s ' % n)
		# 调用generator
		ret = c.send(param)
		print('PRODUCER consumer return %s' % ret)
	# 关闭generator
	c.close()

c = consume()
produce(c)

>>> PRODUCER producing 1
>>> CONSUMER consuming 1
>>> PRODUCER consumer return end
>>> PRODUCER producing 2
>>> CONSUMER consuming 2
>>> PRODUCER consumer return end
>>> PRODUCER producing 3
>>> CONSUMER consuming 3
>>> PRODUCER consumer return end
>>> ...

上述代码的执行流程如下:

  1. 创建生成器c, 然后调用produce 方法, 并传入参数c
  2. 启动生成器c, 并返回ret, consume 函数进入暂停
  3. produce 函数进入while 循环, param 被赋值为1, 打印param, 然后将其发送给consume
  4. consume 接收到param, 然后执行打印, ret 被赋值为end, 再次进入循环, 返回ret, 然后进入暂停
  5. produce函数执行第二个打印, 然后进入第二轮循环
  6. ...

asyncio

python 提供了asyncio 来实现异步IO. 通过创建一个消息循环EventLoop, 将需要执行的协程放入其中, 来实现异步IO 它有两种写法, 具体如下:

python 复制代码
import asyncio
@asyncio.coroutine
def hello():
	print("hello")
	# 模拟耗时操作
	r = yield from asyncio.sleep(1)
	print("world")

async def test():
	print("hello")
	r = await asyncio.sleep(1)
	print("world")


loop = asyncio.get_event_loop()
# loop.run_until_complete(hello())
loop.run_until_complete(asyncio.wait([hello(), test()]))
loop.close()
	

第一种写法里使用@asyncio.coroutine 声明协程, 然后使用yield from 来调用另一个协程并获取返回值

高级特性

切片

切片操作符可以很方便地获取序列型对象(如string, list, tuple) 的部分元素, 语法是: 起始包含:截止不包含:step , 每个参数都可以省略, 如果参数过大或过小, python会自动调整

python 复制代码
s = [0, 1, 2, 3, 4, 5]
# 从index 1到index5(不包含), 每2个元素截取一次
s1 = s[0:5:2]
# >>[0, 2, 3]
# step 为负数时, 逆向索引
s2 = s[0:5:-2]
# >>[4, 2, 0]

迭代

python 中可迭代对象(Iterable 子类)都可以通过for ... in 实现迭代

python 复制代码
# 迭代字典key
for key in dicts:
# 迭代字典value
for value in dicts.values():
# 迭代字典key 和value
for key, value in dicts.items():
# 迭代list, 并获取下标, 可以用enumerate 函数
for index, value in enumerate([1, 2, 3])

列表生成式

列表生成式可以创建基于特定规则的列表, 格式为: [表达式 遍历 筛选条件]

python 复制代码
[x * 2 for x in range(1, 11) if x % 2 == 0]
# >>[4, 8, 12, 16, 20]
# 可以两层嵌套循环
[m + n for m in 'ABC' for n in 'XYZ']
# >>['AX', 'AY', 'AZ'...]

生成器-generator

生成器用于创建生成规则, 注意是列表生成规则而不是列表, 格式是: (表达式 遍历 筛选条件) , 语法上与列表生成式类似, 方括号变成了小括号. 通过next() 函数打印下一个元素, 也可以使用for 循环遍历

python 复制代码
g = (x * 2 for x in range(1, 11) if x % 2 == 0)
next(g)
# >>4
for n in g:
    print(n)
# >>4, 8, 12, 16, 20

还可以通过yield 关键字创建generator 函数, 调用generator 函数将获得一个generator, 每次调用next() 或者遍历, 会返回yield 处的值

python 复制代码
def fib(max):
	n = 0
	while n < max:
		yield n
			n += 1
	return 'done'

f = fib(3)
for n in f:
	print(n)

# >>0 1 2

想要获取generator 函数的值, 需要遍历到最后一个值, 捕获StopIteration 错误

python 复制代码
g = fib(6)
while True:
	try:
		x = next(g)
	except StopIteration as e:
		print(e.value)
# >>done
相关推荐
失败尽常态5231 小时前
用Python实现Excel数据同步到飞书文档
python·excel·飞书
2501_904447741 小时前
OPPO发布新型折叠屏手机 起售价8999
python·智能手机·django·virtualenv·pygame
青龙小码农1 小时前
yum报错:bash: /usr/bin/yum: /usr/bin/python: 坏的解释器:没有那个文件或目录
开发语言·python·bash·liunx
大数据追光猿1 小时前
Python应用算法之贪心算法理解和实践
大数据·开发语言·人工智能·python·深度学习·算法·贪心算法
Leuanghing2 小时前
【Leetcode】11. 盛最多水的容器
python·算法·leetcode
xinxiyinhe3 小时前
如何设置Cursor中.cursorrules文件
人工智能·python
诸神缄默不语3 小时前
如何用Python 3自动打开exe程序
python·os·subprocess·python 3
橘子师兄4 小时前
分页功能组件开发
数据库·python·django
Logintern094 小时前
使用VS Code进行Python编程的一些快捷方式
开发语言·python
Multiple-ji4 小时前
想学python进来看看把
开发语言·python