Python超能力:高级技巧让你的代码飞起来
文章一览
- 前言
- 一、with
- 1.1 基本用法
- 1.2 示例
- 自定义上下文管理器
- 二、条件表达式
- 三、列表式推导式
- 与 zip 结合
- 四、map() 函数(内置函数)
- map用于数据清洗
- 1. 数据清洗:字母大小写规范
- 2. filter() 函数
- 五、匿名函数 lambda
- 5.1 lambda的参数(argument_list)和表达式
- 5.2 lambda 函数与其它函数搭配使用
- 5.3 匿名函数的优势
前言
在当今这个技术日新月异的时代,Python已经成为全球开发者的首选语言之一,它以其简洁、高效和强大的功能闻名于世。然而,Python的真正魅力远不止于此——它隐藏着许多高级技巧,这些技巧能够极大地提升你的编程能力,让你的代码更加优雅、高效和强大。这些高级技巧是Python高手的秘密武器,它们能够解决复杂的问题,优化性能,甚至改变你对编程的看法。
现在,让我们一起揭开Python高级技巧的神秘面纱,探索那些让代码更智能、更灵活的高级特性。无论你是Python新手还是老手,这些高级技巧都将为你打开新世界的大门,让你的编程之路更加宽广。
准备好了吗?让我们一起踏上这段激动人心的Python高级技巧之旅,解锁编程的新高度,成为真正的Python大师!
一、with
在Python中,with
语句是一种上下文管理协议,用于包装代码执行前后的初始化与清理工作。它使得代码更加简洁,易于阅读,并且能够自动管理资源,比如文件操作、线程锁的获取与释放等。with
语句通过__enter__()
和__exit__()
这两个方法来实现资源的封装管理。
1.1 基本用法
with expression as variable:# 在这个代码块中,可以使用variable# 执行一些操作# ...
# 当离开这个代码块时,会自动执行一些清理工作
这里的expression
必须是一个上下文管理器(context manager)对象,它必须实现__enter__()
和__exit__()
方法。__enter__()
方法在进入代码块之前被调用,其返回值(如果有的话)会被赋值给as
子句中的variable
。__exit__()
方法在代码块执行完毕后被调用,无论是正常结束还是由于异常而结束。
1.2 示例
例1:文件操作
使用with
语句进行文件操作是一个很好的例子,因为它可以自动管理文件的打开和关闭:
with open('example.txt', 'r') as file:content = file.read()print(content)
# 文件在这里自动关闭
在这个例子中,open()
函数返回一个文件对象,这个对象是一个上下文管理器。当进入with
语句的代码块时,__enter__()
方法被调用,返回的文件对象被赋值给file
变量。当离开代码块时,__exit__()
方法被调用,文件被自动关闭。
自定义上下文管理器
也可以通过定义一个类,并实现__enter__()
和__exit__()
方法来创建自己的上下文管理器:
class MyContextManager:def __enter__(self):print("Entering")return self # 可以返回任何对象,或者Nonedef __exit__(self, exc_type, exc_val, exc_tb):print("Exiting")# 如果需要,可以在这里处理异常# 如果处理了异常,应该返回True# 否则,返回False(或者省略return,默认为False)return Falsewith MyContextManager() as cm:print("Inside the context manager")
# 输出:
# Entering
# Inside the context manager
# Exiting
在这个例子中,MyContextManager
类定义了一个简单的上下文管理器,它在进入和离开with
语句的代码块时分别打印消息。注意,__exit__()
方法接收三个参数,分别用于异常处理:exc_type
是异常类型,exc_val
是异常值,exc_tb
是异常跟踪信息(traceback)。如果__exit__()
方法返回True
,则异常会被忽略(即被处理)。如果返回False
(或没有返回值,默认为False
),则异常会被正常抛出。
二、条件表达式
if x > 0:y = x*2
else:y = x# 使用条件表达式
y = x*2 if x > 0 else x
简单的条件表达式可以直接写到一行上,而且不用冒号了“:”
三、列表式推导式
列表推导式 是Python基础,也是最受欢迎的 Python 特性之一
>>> a = []
>>> for i in range(0,10):
>>> a.append(i)
>>> print (a)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 使用列表推导式
>>> a = [i for i in range(0,10)]
>>> print (a)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
本质上可以把列表推导式理解成一种集合了 变换 和 筛选 功能的 函数,通过这个函数把一个列表转换成另一个列表
注意:是另一个新列表,原列表保持不变
形式1:[表达式 for 变量 in 列表(或range)]
形式2:[表达式 for 变量 in 列表 if 条件]
格式 1:[expression for item in iterable]
lis = []
for i in range(100):lis.append(i)
print (lis)
# 使用列表推导式
lis = [i for i in range(100)]
print (lis)
格式 2:[expression for item in iterable if 条件]
lis = []
for i in range(100):if i % 2 == 0:lis.append(i)
print (lis)
# 使用列表推导式
lis = [i for i in range(100) if i % 2 == 0]
print (lis)
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [x ** 3 for x in a if x % 2 == 0]
print ('a :',a)
print ('b :',b)
从结果上可以看出:如果有筛选条件是先筛选再变换,即先筛掉不满足条件的元素,再进行变换运算。
也可以同时加多个筛选条件,如对大于 5 的且是偶数的元素进行立方运算
>>> a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> b = [x ** 3 for x in a if x % 2 == 0 and x > 5]
>>> print (b)
[216, 512, 1000]
如对大于 5 的或者是偶数的元素进行立方运算
>>> a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> b = [x ** 3 for x in a if (x % 2 == 0 or x > 5)]
>>> print (b)
[8, 64, 216, 343, 512, 729, 1000]
与 zip 结合
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个列表组,然后返回由这些列表组组成的列表
将 a,b 两个列表中相对应的值组合起来,形成一个新列表。例如包含x 坐标的列表与 y 坐标的列表形成相对应的点坐标 [x, y] 列表
>>> a = [1, 2, 3, 4, 5]
>>> b = [6, 7, 8, 9, 10]
>>> c = [[x, y] for x, y in zip(a, b)]
>>> print(c)
[[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]
四、map() 函数(内置函数)
map(function, iterable,…)
参数function传的是一个函数名,可以是python内置的,也可以是自定义的
参数iterable传的是一个可以迭代的对象,如 列表,元组,字符串
map() 接收一个函数 function 和一个 iterable ,并通过把函数 f 依次作用在 iterable 的每个元素上,得到一个新的 iterable 并返回
给定一列数据,使该列数据中每个元素乘 2
lis = [16,15,13,11,18,17,12,14]
print (lis)
i = 0
for j in lis:lis[i] = j*2i = i + 1
print (lis)
用 map() 函数如何做呢?
def f(x):return x*2
lis = [16,15,13,11,18,17,12,14]
lis1 = map(f, lis)
print (lis1)
注意:map 函数返回时返回的是一个地址
如果要输出值,必须在外层加上list()
def f(x):return x*2
lis = [16,15,13,11,18,17,12,14]
lis1 = map(f, lis)
print (list(lis1))
获取两个列表对应位置上的最小值
>>> l1 = [1,3,7,10]
>>> l2 = [2,4,6,9]
>>> mins = map (min,l1,l2)
>>> print(list(mins))
[1, 3, 6, 9]
获取多输入整数或浮点数
m,n = map(int,input().split(','))
lis = [*map(int, input().split(','))]
lis = [*map(float,input().split(','))]
map用于数据清洗
什么是数据清洗?
一般拿到初始数据后是不能直接用到模型的。比如字符串有些是大写,有些是小写,有些是首字母大写,现在需要处理成统一的格式(首字母大写),这个过程就是数据清洗。
1. 数据清洗:字母大小写规范
'adam', 'LISA', 'barT', 'PYTHON'
>>> def format_name(s):
>>> s=s[0].upper()+s[1:].lower()
>>> return s
>>> s = ['adam', 'LISA', 'barT', 'PYTHON']
>>> s = map(format_name, s)
>>> print (list(s))
['Adam', 'Lisa', 'Bart', 'Python']
2. filter() 函数
filter() 函数是 Python 中常用的内置函数,它主要用来根据特定条件过滤迭代器中不符合条件的元素,需要用list函数进行转换,才能得到符合的条件元素组成的新列表
filter(function, iterable,…)
lis = [4,9,3,14,7,10,6,1]
def odd(x):if x % 2 == 1:return x
newlis = list(filter(odd,lis))
print(newlis)
五、匿名函数 lambda
lambda 函数,或称为匿名函数,是一个没有函数名的简单函数。语法如下:
lambda arguments: expression
lambda 关键字可以用来创建一个 lambda 函数,紧跟其后的是参数列表和用冒号分割开的单个表达式
参数(arguments) 和 表达式(expression)由用户自定义
5.1 lambda的参数(argument_list)和表达式
lambda arguments: expression
匿名函数的 arguments 和普通函数参数一样,可以有非常多的形式
- expression中出现的参数需要在 argument 中有定义,并且表达式只能是单行的
lambda 函数输入是传入到 argument的值,输出是根据 expression 计算得到的值
例如,lambda x: 2 * x 是将任何输入的数乘 2,而 lambda x, y: x+y 是计算两个数字的和。语法十分直截了当
y = lambda x: 2 * x
print(y(6))
def f(x,y):return x+y
f (10,20)# lambda 表达式
f = lambda x,y: x+y
print (f(10,20))
简单说,lambda 函数用于定义简单的、能够在一行内表示的函数。特别提醒:
- 只能写一个表达式,表达式的结果就是返回值
- 不用 return 语句
与其他的使用常规 def 关键字创建的函数不同,lambda 函数没有名字
5.2 lambda 函数与其它函数搭配使用
lambda 函数经常和高阶函数一起使用,比如 map 或 filter
l1 = [1,3,5,7,9]
l2 = [2,4,6,8,10]
result = map (lambda x,y: x * 2 + y, l1,l2)
print (list (result))
>>> m = lambda *args : sum(args)
>>> print (m(3,4,5,6))
18
>>> lis = [-10, 28, 9, -5, 30, 5]
>>> new_lis = list(filter(lambda x:x>0, lis))
>>> print(new_lis)
[28, 9, 30, 5]
5.3 匿名函数的优势
为什么经常把 for 循环和序列(可迭代)类型数据联合使用?
因为数据在容器里存放,要处理数据就需要对容器里的数据进行遍历
用 for 循环遍历十次百次千次,如果遍历百万千万次呢?for 循环效率低!能不用 for 循环就不用 。可以用匿名函数 lambda,简单的函数操作,返回值是 func 类型,在数据分析和清洗中结合 map() 大量会用到匿名函数。
另外,有些函数如果只是临时一用,而且它的业务逻辑也很简单时,就没必要非给它取个名字不可!