【Python】高级语法:推导式、迭代器、生成器、装饰器、上下文管理器

原文作者:我辈李想
版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。



一、推导式

语法格式为:

new_set = {expression for item in iterable if condition}

其中,
new_set 是新生成的集合;
expression 是一个表达式,用于计算集合中元素的值;
item 是集合的元素;
iterable 是一个可迭代对象,如列表、元组、字符串等;
if 语句是可选的,用于筛选元素。

1.列表推导式

列表推导式是 Python 中常用的一种快速创建列表的方式。它可以通过一行代码来生成一个新的列表,而不需要繁琐的循环和条件语句。
下面是一个简单的示例,演示了如何使用列表推导式生成一个1到10的平方数列表:

squares = [x**2 for x in range(1, 11)]
print(type(squares))
print(squares)

输出结果

<class 'list'>
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

列表推导式也可以使用条件语句来过滤元素。下面是一个示例,演示了如何使用列表推导式生成1到10的平方数列表,但只包括偶数:

squares = [x**2 for x in range(1, 11) if x % 2 == 0]
print(type(squares))
print(squares)

输出结果

<class 'list'>
[4, 16, 36, 64, 100]

在上面的示例中,列表推导式使用for循环语句遍历1到10的整数,但只包括偶数,并使用x**2计算每个偶数的平方,然后将结果添加到新的列表中。

列表推导式的优点是可读性高,能够快速创建列表。但是,当可读性受到影响或数据处理较复杂时,建议使用传统的循环和条件语句

2.集合推导式

Python 集合推导式是用来生成集合的一种快捷方式,它类似于列表推导式。

new_set = {x**2 for x in range(1,6)}
print(type(new_set))
print(new_set)

输出结果

<class 'set'>
{1, 4, 9, 16, 25}

上面的例子是生成由 1 到 5 的平方组成的集合。

3.字典推导式

字典推导式的语法与列表推导式和集合推导式类似,但是需要使用花括号 {},可以加入条件表达式等来筛选元素,实现更加复杂的生成。

my_dict = {i: i ** 2 for i in range(1, 6)}
print(type(my_dict))
print(my_dict)

输出结果

<class 'dict'>
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

在上面的例子中,我们使用了一个字典生成器,将 1 到 5 的整数作为字典的键,并将其平方作为值。

二、迭代器

在Python中,迭代器(Iterator)和可迭代对象(Iterable)是两个重要的概念。

可迭代对象是指实现了 iter 或者 getitem 方法的对象,例如列表、元组、集合、字典、字符串等。这些对象可以通过 for 循环进行迭代,或者使用 iter() 函数将其转换为迭代器。

迭代器是指实现了 iternext 方法的对象。__iter__方法返回迭代器对象本身,__next__方法返回数据集合中的下一个元素,如果没有下一个值,就抛出 StopIteration 异常。迭代器只能向前遍历一次,无法回到前面的位置。

示例:迭代对象转迭代器

my_list = [1, 2, 3]
iterator = iter(my_list)
print('my_list',type(my_list))
print('iterator',type(iterator))

输出结果

my_list <class 'list'>
iterator <class 'list_iterator'>

需要注意的是,虽然可迭代对象可以使用 iter() 函数转换为迭代器,但是迭代器本身也是可迭代对象。也就是说,迭代器可以在 for 循环中直接使用。

my_list = [1, 2, 3]
iterator = iter(my_list)
for item in iterator:
    print(item)

迭代器是一个可以遍历数据集合的对象,它的作用是提供一种统一的访问数据集合的方法,而不必关注数据的底层实现方式。

示例:创建一个迭代器

class MyIterator:
    def __iter__(self):
        self.a = 1
        return self

    def __next__(self):
        x = self.a
        self.a += 1
        return x

my_iter = MyIterator()
my_iter_iter = iter(my_iter)
print(type(my_iter_iter))

print(next(my_iter_iter))
print(next(my_iter_iter))
print(next(my_iter_iter))

输出

<class '__main__.MyIterator'>
1
2
3

三、生成器

生成器是一种特殊的迭代器,它可以动态地生成数据而不是从一个固定的数据集合中返回数据。Python中的生成器是通过yield关键字来实现的。当函数中包含yield时,该函数就成为生成器函数,并返回一个生成器对象。

1.yield 生成器

示例1:

def num_generator(n):
    for i in range(1, n+1):
        yield i

# 使用生成器函数生成1到10的数字序列
print(type(num_generator(10)))
for num in num_generator(10):
    print(num)

输出

<class 'generator'>
1
2
3
4
5
6
7
8
9
10

其中,生成器函数num_generator()使用yield语句生成数字序列,并在每次调用时返回一个值。使用for循环迭代生成器对象,每次迭代从生成器函数中获取一个值并打印。

2.元组生成器

示例2:

tuple_generator = (i for i in range(10))
result_tuple = tuple(tuple_generator)
print(type(tuple_generator))
print(type(result_tuple))
print(result_tuple)

输出结果

<class 'generator'>
<class 'tuple'>
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

在这个例子中,我们使用了生成器表达式 (i for i in range(10)) 来生成一个可迭代对象,然后使用 tuple() 函数将其转换为元组。

3.生成器中重要方法

next、send、throw是生成器中的3个重要方法,其中next和send可用于遍历生成器,throw用于抛出异常。

其中next函数使用时,当已经遍历到生成器的结尾,会抛一个异常StopIteration
其中send函数使用时,生成器的第一个值必须使用send(None)
其中throw效果等同于raise

生成器的优点是节省内存,因为它不会一次性生成所有值,而是逐个生成并在使用后释放内存。另外,生成器可以通过迭代器协议与其他Python对象进行交互,包括列表、字典等等。

四、装饰器

1.函数装饰器

Python装饰器是一种高级语法,它可以在不修改原函数代码的情况下,增加或改变原函数的功能。装饰器本质上是一个函数,它可以接收一个函数作为参数,并返回一个新的函数。

@decorator
def function():
    pass

其中 decorator 是一个装饰器函数,用于增强 function 函数的功能。装饰器函数的定义如下:

def decorator(func):
    def wrapper(*args, **kwargs):
        # 在这里增加或改变 func 函数的功能
        print(f'calling {func.__name__}()')
        return func(*args, **kwargs)
    return wrapper

装饰器函数 decorator 接收一个函数 func,并返回一个新的函数 wrapper。wrapper 函数可以在调用原函数之前或之后执行一些操作,然后调用原函数并返回其结果。

计时器示例:

import datetime

def timer(func):
    def wrapper(*args, **kwargs):
        start_time = datetime.datetime.now()
        result = func(*args, **kwargs)
        end_time = datetime.datetime.now()
        print('{0} run time is {1}'.format(func.__name__, (end_time - start_time).total_seconds()))
        return result
    return wrapper

@timer
def my_function():
    time.sleep(2)
    print("Function complete.")

my_function()

其中 timer函数是装饰器函数,它接受一个函数作为参数,返回一个新函数wrapper。wrapper函数用于记录被装饰函数执行的时间,并在执行完毕后输出时间。最后,将my_function函数使用@timer装饰器修饰,从而实现函数计时的功能。
在这里插入图片描述

2.可传参函数装饰器

装饰器函数也是函数,既然是函数,那么就可以进行参数传递,咱们怎么写一个带参数的装饰器呢

import datetime

def time_msg(msg=None):
    def timer(func):
        def wrapper(*args, **kwargs):
            start_time = datetime.datetime.now()
            result = func(*args, **kwargs)
            end_time = datetime.datetime.now()
            print('{0}:{1} run time is {2}'.format(msg,func.__name__, (end_time - start_time).total_seconds()))
            return result
        return wrapper
    return timer

@time_msg(msg="baiyu")
def my_function():
    time.sleep(2)
    print("Function complete.")

my_function()

在这里插入图片描述

3.类装饰器

在python中,可以用类来实现装饰器的功能,称之为类装饰器。类装饰器的实现是调用了类里面的__call__函数。类装饰器的写法比我们装饰器函数的写法更加简单。

import datetime

class MyDecorator:
    def __init__(self, func):
        self.func = func
        print("执行类的__init__方法")
 
    def __call__(self, *args, **kwargs):
        print('进入__call__函数')
        start_time = datetime.datetime.now()
        result = self.func(*args, **kwargs)
        end_time = datetime.datetime.now()
        print('{0}:{1} run time is {2}'.format('',self.func.__name__, (end_time - start_time).total_seconds()))
        result.atrr = '自定义附加参数'  # 类调用时可
        return result 

@MyDecorator
def my_function():
    time.sleep(2)
    print("Function complete.")

@MyDecorator
class MyClass:
    print("MyClass.")

# my_function()

obj = MyClass()
print(obj.attr) # '附加参数'

在这里插入图片描述
在这里插入图片描述

4.可传参的类装饰器

import datetime

class MyDecorator(object):
    def __init__(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2
 
    def __call__(self,func):
        print('进入__call__函数')
        def wrapped(*args, **kwargs):
            print("Decorator arguments:", self.arg1, self.arg2)
            start_time = datetime.datetime.now()
            result = func(*args, **kwargs)
            end_time = datetime.datetime.now()
            print('{0}:{1} run time is {2}'.format('',func.__name__, (end_time - start_time).total_seconds()))
            result.attr = '自定义附加参数'  # 类调用时可用
            return result 
        return wrapped

@MyDecorator('参1','参2')
class MyClass:
    print("MyClass.")

obj = MyClass()
print(obj.attr) # '附加参数'

在这里插入图片描述

五、上下文管理器

上下文管理器的作用是:在代码块执行前完成一些准备工作,在代码块执行后完成一些清理工作。使用上下文管理器可以简化代码、提高可读性,同时也能确保资源在使用完后得到正确的释放。在Python中,上下文管理器通常使用with语句来使用。

1.类对象

类对象只要实现了 enter() 和 exit() 方法可以作为上下文管理器使用。

class MyContextManager:
    def __enter__(self):
        # 准备工作
        print("entering context")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        # 清理工作
        print("exiting context")
        if exc_type is not None:
            print(f"exception {exc_type}: {exc_val}")
        return False  # 如果返回 True,则会吃掉异常,不会抛出

# 使用 with 语句调用上下文管理器
with MyContextManager() as manager:
    print("inside context")

2.函数对象

函数对象实现了try+yield+finally可以作为上下文管理器使用。

from contextlib import contextmanager       # 导入上下文管理器


@contextmanager             # 用上下文管理器装饰函数
def test():
    print("__enter__")      # yield 之前的代码相当于 __enter__
    yield "Hello"           # yield 指定的对象即为执行 with 语句赋值给 as 右边变量的对象
    print("__exit__")       # yield 之后的代码相当于 __exit__


with test() as v:
    print(v)                # v 的值为 "Hello"
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
# 设置数据库连接信息
DATABASE_URL = "postgresql://username:password@localhost/database"
 
# 创建数据库引擎
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
# 初始化数据库会话
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()
with get_db() as db:
    configs = db.query(Config).all()
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我辈李想

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值