函数进阶语法与面向过程
Python进阶语法与面向对象基础完整笔记
一、基础语法:分支判断与三元表达式
1.1 普通分支函数判断
通过自定义函数结合if判断,实现两个数值大小比对,返回最大值,是最基础的条件判断写法。
# 定义函数实现两数取最大值
def func(x, y):
if x > y:
return x
else:
return y
# 调用函数
res = func(10, 20)
print(res)
1.2 三元表达式(简洁判断语法)
三元表达式是if...else分支的极简写法,适用于简单的二选一判断,语法结构:结果1 if 条件 else 结果2。条件成立返回结果1,不成立返回结果2。
二、推导式:高效序列生成语法
推导式是Python专属的极简语法,可快速生成列表、字典、集合等序列数据,替代传统for循环拼接代码,简洁高效、执行速度更快。包含列表、生成器、字典、集合四大推导式。
2.1 列表推导式
用于快速生成、过滤、改造列表数据,支持单层循环、多层循环、条件筛选。
完整语法:
# [expression for item1 in iterable1 if condition1
# for item2 in iterable2 if condition2
# ...
# for itemN in iterableN if conditionN
# ]
等价于普通循环逻辑:
# res=[]
# for item1 in iterable1:
# if condition1:
# for item2 in iterable2:
# if condition2:
# ...
# for itemN in iterableN:
# if conditionN:
# res.append(expression)
执行逻辑:循环遍历可迭代对象,满足条件则执行表达式,将结果存入新列表。
# 原始列表数据
l = ['egon', "lili_dsb", "jack_dsb", "tom_sb", "xxx_dsb"]
# 需求1:所有元素转为大写
new_l1 = [name.upper() for name in l]
print(new_l1)
# 需求2:所有元素去掉末尾sb
new_l2 = [name.strip("sb") for name in l]
print(new_l2)
# 需求3:筛选出以sb结尾的元素
new_l3 = [name for name in l if name.endswith("sb")]
print(new_l3)
2.2 生成器表达式
语法与列表推导式几乎一致,将[]改为(),不直接生成完整列表,而是生成一个迭代器对象,惰性求值,节省内存,适合处理海量数据。
# 生成器创建
chicken = ("鸡蛋%s" % i for i in range(5))
print(chicken) # 输出生成器对象,不占用大量内存
# 逐个取值
print(next(chicken))
print(next(chicken))
print(next(chicken))
print(next(chicken))
print(next(chicken))
# 强制转换为列表(取值完毕后生成器为空)
res1 = list(chicken)
print(res1)
res2 = list(chicken)
print(res2) # 再次取值为空
文件读取场景优化:利用生成器惰性特性,避免一次性读取大文件占用内存
with open("a.txt",mode='rt',encoding='utf-8') as f:
# 方式一:一次性读取全部内容
res = f.read()
print(len(res))
# 方式二:循环逐行累加
res = 0
for line in f:
res += len(line)
print(res)
# 方式三:列表推导式,一次性生成所有数据,占用内存高
res = sum([len(line) for line in f])
print(res)
# 方式四:生成器表达式,惰性取值,内存占用极低(可省略小括号)
res = sum(len(line) for line in f)
print(res)
2.3 字典推导式
快速创建、改造字典,支持批量生成键值对、列表转字典等场景。
# 场景1:批量生成键值对
dic1 = {"k%s" %i:i for i in range(5)}
print(dic1)
# 场景2:批量初始化字典值为None
keys = ["name","age","gender"]
dic2 = {k:None for k in keys}
print(dic2)
# 场景3:二元元组列表转为字典
items = [('name',"egon"),("age",18),("gender",'male')]
dic3 = {k:v for k,v in items}
print(dic3)
2.4 集合推导式
快速生成集合,自动去重,语法结构与列表推导式一致,外层为{}。
res = {i for i in range(3)}
print(res,type(res))
三、函数递归调用
3.1 递归定义与特性
函数递归是函数嵌套调用的特殊形式:在函数调用过程中,直接或间接调用函数自身,本质是替代循环实现重复执行。
分类:
1、直接递归:函数内部直接调用自身;
2、间接递归:A函数调用B函数,B函数再次调用A函数。
想要让某段代码重复/循环执行,有两种解决方案:
1、while、for循环;
2、函数递归调用,本质就是循环。
核心规则:递归必须设置终止条件,禁止无限递归,否则会触发程序报错。Python默认递归深度限制约1000层,可手动修改。
# 直接递归(无限递归,报错示例,禁止使用)
# def f1():
# print("111")
# f1()
# f1()
# 间接递归(无限递归,报错示例,禁止使用)
# def f1():
# print(111)
# f2()
# def f2():
# print(6666)
# f1()
# f1()
# 查看/修改递归深度限制
import sys
print(sys.getrecursionlimit())
sys.setrecursionlimit(2000)
print(sys.getrecursionlimit())
3.2 规范递归:回溯与递推
需要强调的是,递归调用不应该无限制地调用下去,必须在满足某种条件下结束递归调用。
以终止节点作为分水岭,函数递归调用可以分为两个阶段:
1、回溯:层层向下递归调用,直到触发终止条件;
2、递推:触发终止条件后,层层向上返回结果,最终得到最终值。
# 基础规范递归示例
def f1(n):
# 终止条件
if n == 10:
return
print(n)
n += 1
f1(n)
f1(0)
# 经典年龄递归案例
# 逻辑:age(1)=18,age(n)=age(n-1)+10
def age(n):
if n == 1:
return 18
return age(n-1) + 10
res = age(5)
print(res)
3.3 递归实战:多层列表遍历
利用递归遍历多层嵌套列表,逐层拆解列表,打印所有非列表元素。
l = [1, 2, [3, [4, [5, ]]]]
def f1(nums_list):
print(nums_list)
for item in nums_list:
# 判断元素是否为列表,是则继续递归遍历
if type(item) is list:
f1(item)
# 非列表元素直接打印
else:
print(item)
f1(l)
四、算法基础:二分查找法
算法是高效解决问题的方法,二分法是经典的有序序列查找算法。
需求:有一个按照从小到大顺序排列的数字列表,需要从该数字列表中找到我们想要的一个数字。
4.1 普通遍历方案(低效)
逐个遍历比对,数据量大时效率极低。
nums = [-5, 3, 7, 19, 23, 45, 63, 67, 103]
find_num = 99
for num in nums:
if num == find_num:
print('find it')
break
4.2 递归二分法(高效)
核心逻辑:每次取列表中间值,对比目标数,舍弃一半无效区间,递归查找剩余区间,列表为空则判定不存在。
nums = [-5, 3, 7, 19, 23, 45, 63, 67, 103]
def search(find_num,nums_list):
print(nums_list)
# 终止条件:列表为空,查找失败
if len(nums_list) == 0:
print("not exists")
return
# 取中间索引与中间值
mid_index = len(nums_list) // 2
mid_val = nums_list[mid_index]
# 目标值大于中间值,查找右半区间
if find_num > mid_val:
search(find_num,nums_list[mid_index+1:])
# 目标值小于中间值,查找左半区间
elif find_num < mid_val:
search(find_num, nums_list[:mid_index])
# 匹配成功
else:
print('find it')
search(68,nums)
五、编程思想范式
5.1 面向过程编程思想
核心是“过程”二字,过程就是流程、就是解决问题的步骤:先干什么、再干什么、后干什么。基于该思想写程序就好比是在设计一条流水线。
优点:复杂问题流程化、进而简单化
缺点:牵一发而动全身,扩展性差
面向过程编程思想的场景分析:
1、不是所有场景都需要频繁更迭,比如编写脚本;
2、即便是一个软件要频繁更迭,也并不代表该软件的所有部分都要更迭,软件整体的框架通常不会动,所以说程序的框架整体通常都是过程式。
六、函数进阶:匿名函数与高阶函数
6.1 有名函数与匿名函数
def定义的函数都是有名字的函数,函数名对应函数的内存地址,可重复调用。
# def定义有名函数,f1指向函数内存地址
def f1(x,y,z):
print(x,y,z)
print(f1)
f1(1,2,3)
匿名函数通过lambda定义,无函数名,引用计数为0,使用一次就释放,适合临时使用一次的场景,通常与其他函数配合使用,作为其他函数的补充功能临时用一次。
语法:lambda 参数: 返回值表达式
# 匿名函数语法
lambda x,y,z: x + y + z
# 上述匿名函数的功能等同于下面的有名函数
# def func(x,y,z):
# return x + y + z
# 匿名函数调用方式1:立即调用
res1 = (lambda x,y,z: x + y + z)(1,2,3)
print(res1)
# 匿名函数调用方式2:绑定变量(不建议,违背匿名初衷)
f = lambda x,y,z: x + y + z
print(f)
res2 = f(1,2,3)
print(res2)
6.2 匿名函数配合高阶函数实战
匿名函数核心用途:配合max、min、sorted、map、filter、reduce等高阶函数,临时提供逻辑规则。
储备知识:max基础用法
res = max([11,33,22,77,66])
print(res)
# 迭代取出 比较的值
# 11 11
# 33 33
# 22 22
# 77 77
# 66 66
# 最终返回77
实现需求:找出薪资最高的那个人的人名
salaries = {
'egon': 3000,
'tom': 7000,
'lili': 10000,
'jack': 2000
}
# 直接max字典,默认比较的是key的大小
# res = max(salaries)
# print(res)
# 迭代取出 比较的值
# egon egon
# tom tom
# lili lili
# jack jack
# 最终返回tom(按字符串排序)
# 通过key参数指定比较依据,配合匿名函数
res = max(salaries,key=lambda k:salaries[k])
res = min(salaries,key=lambda k:salaries[k])
res = sorted(salaries,key=lambda k:salaries[k])
res = sorted(salaries,key=lambda k:salaries[k],reverse=True)
print(res)
6.3 三大高阶函数详解
6.3.1 map映射函数(了解)
功能:遍历可迭代对象,对每个元素执行指定逻辑,返回新迭代器,用于批量处理数据。
l = ["egon","tom","jack"]
# 生成器表达式写法
# res = (name+"_dsb" for name in l)
# print(list(res))
# map写法
res = map(lambda name:name + "_dsb",l)
print(res)
print(list(res))
6.3.2 filter过滤函数(了解)
功能:根据条件筛选可迭代对象元素,保留条件成立的元素。
l = ["egon","tom_sb","jack_sb"]
# 生成器表达式写法
# res = (name for name in l if name.endswith('sb'))
# print(list(res))
# filter写法
res = filter(lambda name:name.endswith("sb"),l)
print(res)
print(list(res))
6.3.3 reduce累积函数(了解)
功能:对可迭代对象元素进行累积运算,两两迭代计算,最终返回单个值,需手动导入functools模块。
from functools import reduce
# 数值累加,带初始值
res = reduce(lambda x,y:x+y,[1,2,3],100)
# 字符串拼接,带初始值
res = reduce(lambda x,y:x+y,["aaa","bbb","ccc"],"--->")
print(res)
七、函数注解与常用内置方法
7.1 函数参数注解
用于标注参数、返回值的数据类型,仅做提示,不强制校验,提升代码可读性。可通过__annotations__查看所有注解信息。
# 自定义描述注解
def register(name: "必须传入一个字符串类型", age: "传整型", hobbies: "传元组") -> "返回值是整型":
print(name)
print(age)
print(hobbies)
return 123
# 标准类型注解
def register(name: str, age: int, hobbies: tuple) -> int:
print(name)
print(age)
print(hobbies)
return 123
# 查看注解
print(register.__annotations__)
7.2 常用内置函数大全
需掌握的核心内置函数:
# 字符与ASCII数字互转
print(chr(65)) # 参照ASCII表把数字转换字符
print(ord("A")) # 参照ASCII表把字符转换数字
# 查看对象可调用的所有属性/方法
import time
print(dir(time)) # 查看可以.调用出的所有名字:time.名字
def f1():
print('...')
print(dir(f1))
# 整除取商和余数
res = divmod(10,3)
print(res)
# 枚举遍历,同时获取索引和值
for i,v in enumerate([111,222,333]):
print(i,v)
# 字符串转Python可执行对象
x = "[1,2,3]"
res = eval(x)
print(res,type(res))
res = eval("print('hello')")
print(res)
# 反转序列
l = [1, 22, 33, "a"]
new_l = reversed(l)
print(new_l)
print(list(new_l))
# 四舍五入
print(round(3.6))
print(round(3.4))
# 拉链配对,以最短序列为准
m = "abcdef"
n = [11,22,33]
res = zip(m,n)
print(res)
print(dict(res))
# 动态导入模块
m = __import__("time")
print(m.time())
了解类内置函数:
# 绝对值
print(abs(-1))
# 全部为真/任意为真
res = all([1, 2.3, "a", [1, 2, 3]])
res = all([1, 2.3, "", [1, 2, 3]])
print(res)
print(all([])) # 可迭代对象没有包含任何值,all的结果为True
res = any([0, None, "123", []])
print(res)
print(any([])) # 可迭代对象没有包含任何值,any的结果为False
# 进制转换
print(bin(11)) # 二进制 0b1011
print(oct(11)) # 八进制 0o13
print(hex(11)) # 十六进制 0xb
# 判断对象是否可调用
def f1():
print(111)
print(callable(f1))
# 可变集合与不可变集合
s1 = set({1,2,3})
s1.add(4)
print(s1)
s2 = frozenset({1,2,3}) # 不可变集合
# 全局与局部变量字典
x=111
y=222
print("站在全局===>",globals())
def f1():
m = 6666
n = 777
print("站在局部===>",globals())
print("站在局部===>",locals())
f1()
# 哈希运算
res = hash("1111")
print(res)
# 幂运算取余
res = pow(10,2,3) # 10 ** 2 % 3
print(res)
# 切片对象,复用切片规则
l = [11,22,33,44,55,66,77]
s = slice(1,5,2)
res = l[s]
print(res)
# 获取对象属性字典
print(vars())
八、面向对象基础预备知识
8.1 内置工厂函数
所有基础数据类型本质都是类,通过类实例化得到对象,这些类统称为工厂函数。
包含:int、float、str、list、tuple、dict、set、bool、bytes、complex
8.2 面向对象核心内置属性与方法
为后续面向对象编程的核心预备知识点,所有对象、类均可调用:
-
装饰器与属性控制:classmethod、staticmethod、property
-
属性操作:delattr(删除属性)、hasattr(判断是否有属性)、setattr(设置属性)、getattr(获取属性)
-
代码执行:exec
-
类型判断:isinstance、issubclass
-
核心基类:object(所有类的顶层父类)、super(子类调用父类方法)

浙公网安备 33010602011771号