数据STUDIO

10 精彩绝伦的 Python 功能

Image

Image

如果你学习 Python 有一段时间了,你可能会遇到一些比较迷惑功能。它们看起来比较复杂,实际非常好用的技巧。

这些功能都是非常出色的工具,只要你了解它们,就能让你的代码更简洁、更高效、更优雅。

我们用简单的语言分解其中的 10 个功能。

1. 装饰器:函数的超能力

装饰器看起来像魔法。

你在函数上方添加一个 @something,突然间,函数的行为就变了。这是怎么回事呢?

装饰器可以让你在不修改代码的情况下修改或扩展函数或方法的行为。

将它们视为添加额外功能的一种方式。

示例:

def greet_decorator(func):
    def wrapper():
        print("Hello!")
        func()
        print("Goodbye!")
    return wrapper

@greet_decorator
def say_name():
    print("My name is Python.")
say_name()

当你调用 say_name() 时,它将被封装在装饰器的 wrapper 函数中。它会打印 “Hello!”,运行 say_name,然后打印 “Goodbye!”。

装饰器非常适合日志记录、身份验证或测量执行时间。

2. 生成器 懒惰而高效的迭代器

生成器使用 yield 而不是 return,而且它们不会同时运行。有什么意义?

生成器只在需要时才一次生成一个项目。

这对于处理大型数据集或无限序列非常有用,而且不会占用内存。

def count_up_to(n):
    count = 1
    while count <= n:
        yield count
        count += 1
for number in count_up_to(5):
    print(number)

count_up_to并不是创建一个完整的数字列表,而是即时生成数字。

这就像一个神奇的水龙头,能根据你的要求倒出数字。

3. 上下文管理器和 with 语句:像专家一样处理资源

with语句似乎是一种打开文件的花哨方法。

为什么不直接使用 open() 就可以了呢?

上下文管理器会自动处理设置和清理工作,防止资源泄漏,比如忘记关闭文件。

with open("example.txt", "r") as file:
    content = file.read()
    print(content)

文件被打开、读取,然后在退出 with 块时自动关闭。

不再调用file.close(),不再意外锁定文件。

你甚至可以使用 contextlib 或在类中定义 __enter__ 和 __exit__ 方法来创建自己的上下文管理器。

方便管理数据库连接或网络资源。

4. 推导式

列表推导式和它们的同类(dict、set 和生成器理解)看起来像难以理解的速记。

但综合法能让你简洁地创建集合,通常能取代多行代码。

squares = [x**2 for x in range(10) if x % 2 == 0]
print(squares)  # Output: [0, 4, 16, 36, 64]

这个单行本为 0 到 9 之间的偶数建立了一个正方形列表。

一旦你掌握了它们的窍门,你就会想,如果没有它们,你是怎么生活的。

5. 海象运算符(:=):表达式中的赋值

它在代码中看起来就像一个侧向的笑脸。它到底在做什么?

作为表达式的一部分,海象运算符可以为变量赋值。

这可以让你的代码更简短、更易读。

numbers = [10, 20, 30, 40]
if (n := len(numbers)) > 3:
    print(f"Too many numbers ({n})!")

len(numbers)结果将赋值给 n,并在条件中使用。无需计算两次。

6. 类型提示:让代码更易于阅读和调试

Python 是一种动态类型语言,那么我们为什么要添加类型呢?

类型提示提高了代码的可读性,并能及早发现错误。它们不会在运行时强制执行,但可以帮助列式器和集成开发环境等工具。

def greet(name: str) -> str:
    return f"Hello, {name}!"
print(greet("Python"))

类型提示告诉你 name 应该是字符串,函数返回字符串。

这就像是为未来的你(或你的队友)提供了一个指南。

7. Metaclasses元类 控制类的行为

元类就像是 “类中之类”。

元类可以让你控制类的创建方式。它们对于执行规则或注入行为非常有用。

class Meta(type):
    def __new__(cls, name, bases, dct):
        if 'required_attribute' not in dct:
            raise TypeError("Missing required_attribute")
        return super().__new__(cls, name, bases, dct)
class MyClass(metaclass=Meta):
    required_attribute = True

元类在创建 MyClass 时会检查 required_attribute 是否存在。如果不存在,就会引发错误。

这就像是类的质量控制。

8. @staticmethod 和 @classmethod 装饰器:灵活的类方法

既然普通方法也能正常工作,我们为什么还需要它们呢?

这些装饰器提供了定义方法的不同方法,这些方法不需要访问实例属性(@staticmethod),也不需要使用类本身(@classmethod)。

class MyClass:
    @staticmethod
    def static_method():
        return "I don’t need an instance!"
@classmethod
    def class_method(cls):
        return f"I work with {cls}!"
print(MyClass.static_method())
print(MyClass.class_method())

static_method 不关心类或实例,而 class_method 可以访问它所属的类。

这对实用函数或替代构造函数很有用。

9. __slots__:在类中节省内存

__slots__ 看起来限制了灵活性,这与 Python 的动态特性背道而驰。

通过定义 __slots__,你可以告诉 Python 为属性分配固定数量的内存,从而在大型应用程序中节省内存。

class MyClass:
    __slots__ = ['name', 'age']
def __init__(self, name, age):
        self.name = name
        self.age = age

MyClass 的实例只能有 name 和 age 属性,而且占用内存更少。

非常适合有许多对象的情况。

10. Descriptors描述符 可重复使用的属性逻辑

它们涉及的方法如 __get__、__set__ 和 __delete__,让人感觉晦涩难懂。

但描述符可以让你重复使用管理属性的逻辑。可以把它们看作高级属性装饰器。

class Descriptor:
    def __get__(self, instance, owner):
        return instance._value

def __set__(self, instance, value):
        instance._value = value * 2
class MyClass:
    attr = Descriptor()
    def __init__(self, value):
        self._value = value
obj = MyClass(10)
obj.attr = 20
print(obj.attr)  # Output: 40

描述符在赋值前会将数值加倍,这样就不必在多个地方重复这一逻辑。

🏴‍☠️宝藏级🏴‍☠️ 原创公众号『数据STUDIO』内容超级硬核。公众号以Python为核心语言,垂直于数据科学领域,包括可戳👉Python|MySQL|数据分析|数据可视化|机器学习与数据挖掘|爬虫 等,从入门到进阶!

长按👇关注- 数据STUDIO -设为星标,干货速递ImageImage