python常用代码-自用 三元表达式、列表生成式

python

1、三元表达式

# if else 
x = 10
y = 20
# 使用三元表达式判断 x 和 y 的大小,并赋值给 result
result = "x 大于 y" if x > y else "x 小于或等于 y"
print(result) # 输出: x 小于或等于 y

2、列表生成式

# [expression for item in iterable if condition]
# expression:要计算并添加到新列表中的表达式。
# item:从可迭代对象中获取的元素。
# iterable:一个可迭代对象,例如列表、字符串、范围等。
# condition(可选):过滤条件,只有满足条件的元素才会被包含在新列表中。
# 例子
# 创建一个包含 1 到 10 的平方的列表
squares = [x**2 for x in range(1, 11)]
print(squares) # 输出: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 创建一个包含 1 到 10 中偶数的平方的列表
even_squares = [x**2 for x in range(1, 11) if x % 2 == 0]
print(even_squares) # 输出: [4, 16, 36, 64, 100]
# 嵌套循环:创建一个包含 (i, j) 元组的列表,其中 i 是 1 到 3,j 是 1 到 2
pairs = [(i, j) for i in range(1, 4) for j in range(1, 3)]
print(pairs) # 输出: [(1, 1), (1, 2), (2, 1), (2, 2), (3, 1), (3, 2)]
# 带有多个条件的列表生成式(两个if相当于用and连接)
filtered_list = [x for x in range(20) if x % 2 == 0 if x % 3 == 0]
# 等价于下面
filtered_list = [x for x in range(20) if (x % 2 == 0 and x % 3 == 0)]
print(filtered_list) # 输出: [0, 6, 12, 18]
# 带有多个条件的列表生成式使用or连接
custom_list = [x for x in range(20) if x % 2 == 0 or if x % 5 == 0]
custom_list = [x for x in range(20) if (x % 2 == 0 or x % 5 == 0)]
print(custom_list) # 输出: [0, 2, 4, 5, 6, 8, 10, 12, 14, 15, 16, 18, 20]
# 从一个字符串中提取字母并转换为大写
text = "Hello, World!"
uppercase_letters = [char.upper() for char in text if char.isalpha()]
print(uppercase_letters) # 输出: ['H', 'E', 'L', 'L', 'O', 'W', 'O', 'R', 'L', 'D']

3、判断一个序列是不是另一个序列的子序列

def is_subsequence(a, b):
 b = iter(b)
 return all(i in b for i in a)
print(is_subsequence([1, 3], [0, 1, 2, 3])) # 输出: True
print(is_subsequence([1, 4], [0, 1, 2, 3])) # 输出: False

定义函数
def is_subsequence(a, b): 定义一个名为 is_subsequence 的函数,接受两个参数 ab
创建迭代器
b = iter(b):将 b 转换为一个迭代器。这样做的目的是为了在检查 b 中是否存在元素时,可以消耗掉 b 中的元素。换句话说,一旦某个元素在 b 中被找到,之后的查找会从该元素后面开始,而不是从头开始
检查子序列
return all(i in b for i in a)

  • 这个表达式使用生成器表达式遍历 a 中的每个元素 i
  • 对于每个元素 i,它检查是否在迭代器 b 中。
  • all() 函数会返回 True 当且仅当生成器表达式中的所有检查都返回 True。也就是说,只有当 a 中的每个元素都能在 b 中找到时,is_subsequence 才会返回 True

4、 GIL 全局解释器锁(Global Interpreter Lock,简称 GIL)

Python 的全局解释器锁(Global Interpreter Lock,简称 GIL)是一个机制,用于确保在任何时刻只有一个线程可以执行 Python 字节码。这一设计主要是为了简化 CPython 的内存管理并避免多线程环境下的数据竞争和崩溃。但使用线程时的时候仍需要自己加锁来管理内存。

GIL 工作原理

单线程运行: GIL 使得 CPython 解释器在执行字节码时只允许一个线程运行。这意味着即使在多核处理器上,Python 程序也不能利用多个 CPU 核心进行并行计算。
线程切换: 当一个线程需要执行一段时间的操作(如 I/O 操作),GIL 会被释放,允许其他线程获取 GIL 并执行。这种切换通常发生在 I/O 阻塞、时间片到期等情况下。这样,虽然 GIL 限制了 CPU 密集型操作的并行性,但对于 I/O 密集型操作,多个线程仍然可以有效共享时间。
影响:

  • 对于 CPU 密集型任务,GIL 可能导致性能瓶颈,因为多个线程无法并行运行。
  • 对于 I/O 密集型任务,如网络请求或文件读写,GIL 的影响较小,因为线程可以在等待 I/O 时让出 GIL。

注: NumPy 的许多核心功能是用 C 和 Fortran 编写的,这些底层库可以在执行计算时释放 GIL。这意味着在进行大量数值计算时,NumPy 可以利用多核 CPU 的优势,特别是在调用外部库(如 BLAS 或 LAPACK)进行矩阵运算时

5、装饰器

简单装饰器

  • 装饰器是一个接收函数作为参数并返回一个增强功能的函数(通常是一个闭包)的函数。装饰器的目的是在不修改原始函数代码的前提下添加额外的功能
  • 一个典型的装饰器定义没有外层函数包裹,直接接收一个函数并返回一个函数
# 外层函数(Decorator Function):这个函数接受被装饰的函数作为参数
def decorator(func): 
	# 内层函数(Wrapper Function):这个函数用于包装或增强被装饰的函数的行为。它通常会接受任意的参数,并在适当的时候调用原始函数。
 def wrapper():
 print("在函数执行前做点什么")
 # 调用原始函数
 func()	
 print("在函数执行后做点什么")
 return wrapper
@decorator
def say_hello():
 print("Hello!")
say_hello()

装饰器工厂

  • 装饰器工厂是一个返回装饰器的函数。这种结构让你可以在创建装饰器时传递参数,从而控制装饰器的行为。
  • 装饰器工厂通常由两层或更多层函数组成:最外层函数接收装饰器的配置参数,内层函数则是实际的装饰器,它接收一个函数并返回一个增强版的函数。
# 简单装饰器本身不支持在装饰器应用时直接传递参数来控制其行为
def decorator_with_args(prefix):
 def decorator(func):
 def wrapper(*args, **kwargs):
 print(prefix, "在函数执行前做点什么")
 result = func(*args, **kwargs)
 print(prefix, "在函数执行后做点什么")
 return result
 return wrapper
 return decorator
@decorator_with_args("LOG:")
def say_hello():
 print("Hello!")
say_hello()

类装饰器

类装饰器是使用类来实现装饰器的功能。类装饰器利用了类的 __call__ 方法,这使得类的实例可以被当作函数调用,使用类装饰器的优势在于它能够利用面向对象编程的特性,如继承、封装等,来构建更复杂的装饰器逻辑。

普通的装饰器用类方法实现

class CountCalls:
 def __init__(self, func):
 self.func = func
 def __call__(self, *args, **kwargs):
 print("在函数执行前做点什么")
 result = self.func(*args, **kwargs)
 print("在函数执行后做点什么")
 return result
@CountCalls
def say_hello():
 print("Hello!")
say_hello()

装饰器工厂用类装饰器实现

from functools import wraps
class CountCalls:
 def __init__(self, prefix):
 self.prefix = prefix
 def __call__(self, func):
 	# 将一些重要的元数据从原始函数(即被装饰的函数 func)复制到包装函数(即装饰器内部定义的函数 wrapper)。这些元数据包括函数的名称 __name__、文档字符串 __doc__、以及其他由用户定义的属性。
 @wraps(func)	
 def wrapper(*args, **kwargs):
 print(self.prefix, "在函数执行前做点什么")
 result = func(*args, **kwargs)
 print(self.prefix, "在函数执行后做点什么")
 return result
 return wrapper
@CountCalls(prefix='LOG:')
def say_hello():
 print("Hello!")
say_hello()

当函数执行失败时按照传入参数重试

import logging
import time
from functools import wraps
from time import sleep
class Retry:
 """
 类装饰器,当函数执行抛出异常时,按照max_retries和wait_time重试
 """
 def __init__(self, max_retries=3, wait_time=2):
 self.max_retries = max_retries
 self.wait_time = wait_time
 def __call__(self, func):
 @wraps(func)
 def wrapper(*args, **kwargs):
 attempts = 0
 while attempts < self.max_retries:
 try:
 return func(*args, **kwargs)
 except Exception as e:
 attempts += 1
 logging.error(f"Error occurred: {e}. Retrying {attempts}/{self.max_retries}...")
 time.sleep(self.wait_time) # 等待惩罚时间
 if attempts == self.max_retries:
 logging.error("Max retries reached. Giving up.")
 return wrapper
@Retry(max_retries=5, wait_time=1)
def say_hello():
 print("Hello!")
 sleep(0.2)
 raise Exception("手动抛出异常")
say_hello()
# Hello!
# ERROR:root:Error occurred: 手动抛出异常. Retrying 1/5...
# Hello!
# ERROR:root:Error occurred: 手动抛出异常. Retrying 2/5...
# Hello!
# ERROR:root:Error occurred: 手动抛出异常. Retrying 3/5...
# Hello!
# ERROR:root:Error occurred: 手动抛出异常. Retrying 4/5...
# Hello!
# ERROR:root:Error occurred: 手动抛出异常. Retrying 5/5...
# ERROR:root:Max retries reached. Giving up.
作者:吃不到的烤鱼原文地址:https://blog.csdn.net/weixin_37038498/article/details/140693143

%s 个评论

要回复文章请先登录注册