laitimes

15 high-level features in Python that are not well known

author:Senior Internet Architect

Python, with its clear and concise syntax and powerful library support, has become a language that beginners and experts alike will love. But hidden beneath its approachable exterior lies a host of advanced features waiting to be discovered by explorers. This article will take you through 15 unknown advanced features of Python that can make your code more efficient and elegant.

Feature 1: Generator expressions

Generator expressions are memory-friendly versions of list derivations. It is especially useful when dealing with large amounts of data because it delays calculations and produces only one result at a time. For example, gen = (x**2 for x in range(10)), which does not calculate all square values at once, but is generated on demand at each iteration.

Hands-on tip: Use generator expressions to reduce your memory footprint, especially when working with large files or datasets in loops.

Feature 2: Enhanced assignment of list parsing

In case you didn't notice, list parsing not only creates new lists, but also combines with existing lists to make in-place changes. For example, [x*2 for x in lst] += [10], here a temporary list consisting of twice the lst elements is created, and then the number 10 is added to the end of the lst, which implements a one-time expansion and modification of the list.

Note: This is a concise way to write, but you need to be careful when working with large lists to avoid unnecessary memory overhead.

Next, we'll take a deep dive into the advanced features of dictionaries and collections, and how you can use them to make your code more efficient.

Feature 3: Dictionary derivation and merging

字典推导式是快速构建新字典的神器。 比如,{k: v*2 for k, v in my_dict.items()}将每个值翻倍。 而Python 3.5+引入了字典合并的新语法,{**d1, **d2},直接合并两个字典,解决了传统.update()的繁琐。

Practical cases:

d1 = {'a': 1, 'b': 2}
d2 = {'b': 3, 'c': 4}
merged = {**d1, **d2}  # 结果: {'a': 1, 'b': 3, 'c': 4}           

This trick is especially useful when configuring merge or handling nested dictionaries returned by the API.

Feature 4: Efficient collection operations

Set provides unique mathematical set operations, such as intersection (&), union (|), difference (-), symmetric difference (^). The symmetric_difference() method is to find elements that are unique to two sets and is great for deduplicating and merging two lists.

set1 = {1, 2, 3}
set2 = {2, 3, 4}
unique_elements = set1.symmetric_difference(set2)  # 结果: {1, 4}           

Because of its underlying C implementation, collection operations are generally faster than equivalent list operations, and are suitable for deduplication and comparison operations of large data volumes.

Next, dive into the world of functions and explore the advanced uses of decorators, partial functions, and closures, which are the essence of Python programming.

Feature 5: Deep understanding of decorators

Decorators are an advanced feature in Python that changes the behavior of a function or class. Extend the functionality of the original function by defining a function that accepts a function as a parameter and returns a new function. For example, a simple log decorator:

def log_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

@log_decorator
def greet(name):
    print(f"Hello, {name}")

greet("World")  # 输出: Calling greet Hello, World           

The power of decorators lies in their flexibility and their ability to add functionality without modifying the original function code.

Feature 6: Application of partial functions

functools.partial allows you to "freeze" some function parameters and create new ones. This is useful for fixing certain parameter values, simplifying the interface, or adapting to a specific scenario.

from functools import partial

def power(base, exponent):
    return base ** exponent

square = partial(power, exponent=2)
print(square(5))  # 结果: 25           

With partial functions, we can easily create functions for specific purposes, improving the reusability and readability of our code.

Feature 7: The internal mechanism of closures

A closure is an inner function that has access to the scope variables of an external function. It saves the state of the outer scope, even if the external function has already been executed. Closures are commonly used to create functions with state.

def counter():
    count = 0
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

my_counter = counter()
print(my_counter())  # 输出: 1
print(my_counter())  # 输出: 2           

Closures are useful when implementing caching, singleton patterns, and encapsulating local state.

The above features reveal the flexibility and power of Python functions, and in the next section we will explore the mysteries of iterators, generators, and context managers to further deepen your advanced Python skills.

Feature 8: Generation of infinite sequences

Python's itertools module provides a number of powerful iterative tools, such as count(), which can generate infinite counting sequences. This is especially useful for simulating loops or generating continuous sequences of numbers.

from itertools import count

for i in count(start=1):
    if i > 10:
        break
    print(i)           

This code prints numbers from 1 to 10 and shows how to control the use of an infinite sequence.

Feature 9: Customization of the iterator protocol

Any object that implements the __iter__() and __next__() methods is an iterator. Custom iteration logic allows your class to support iteration, for example:

class CountDown:
    def __init__(self, start):
        self.current = start

    def __iter__(self):
        return self

    def __next__(self):
        if self.current <= 0:
            raise StopIteration
        self.current -= 1
        return self.current + 1

for num in CountDown(5):
    print(num)           

This code defines a countdown iterator and shows the basic implementation of the iterator.

Feature 10: Pause and resume of generator yield

Generators are special iterators that use the yield keyword to pause the execution of a function and save the current state. When next() is called again, the function picks up where it left off.

def simple_generator():
    yield 1
    yield 2
    yield 3

gen = simple_generator()
print(next(gen))  # 输出: 1
print(next(gen))  # 输出: 2           

The generator is particularly useful when working with large data streams because it generates data on demand, saving memory.

Trait 11: 自定义with语句

The Context Manager allows code blocks to automatically manage resources, such as file operations, by defining __enter__() and __exit__() methods. Here's an example of a simple file manipulation context manager:

class ManagedFile:
    def __init__(self, name):
        self.name = name

    def __enter__(self):
        self.file = open(self.name, 'r')
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()

with ManagedFile('example.txt') as f:
    content = f.read()           

With the with statement, you can ensure that the file is properly closed after use, without having to manually call close().

With the above, we explored advanced applications of iterators, generators, and context managers in Python that greatly improve the elegance and efficiency of your code. Next, we'll demystify metaprogramming, learn about the mysteries of dynamic class creation and descriptors, and how to further improve your programming skills with advanced modules.

Feature 12: Dynamic creation of classes

Python's type() function is not only used for type queries, but can also be used to dynamically create classes. This is useful when you need to define a class based on runtime conditions.

def make_class(name, bases, dict):
    return type(name, bases, dict)

MyClass = make_class('MyClass', (object,), {'x': 5})
instance = MyClass()
print(instance.x)  # 输出: 5           

Creating classes on the fly allows your code to be more flexible and adapt to complex design patterns.

Feature 13: Descriptor comprehension

A descriptor is a class that implements a particular protocol and controls property access by overriding the __get__(), __set__(), and __delete__() methods. They are the basis for implementing private properties, property validation, and proxy patterns.

class DescriptorExample:
    def __init__(self):
        self._value = None

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

    def __set__(self, instance, value):
        if not isinstance(value, int):
            raise ValueError("Value must be an integer")
        self._value = value

class MyClass:
    attr = DescriptorExample()

obj = MyClass()
obj.attr = 10  # 正确
obj.attr = "not a number"  # ValueError           

Descriptors provide fine-grained property access control and are an advanced feature in the Python object model.

Trait 14: os.path的高级路径处理

The os.path module provides a variety of path operation functions, such as join() and splitext(). where normpath() can standardize the path and eliminate the redundant . 、.. and slashes.

import os.path
path = "/path/to/../file.txt"
normalized_path = os.path.normpath(path)
print(normalized_path)  # 输出: /path/file.txt           

This is useful for handling user input or file paths across platforms.

Feature 15: Advanced date operations for the datetime module

The TimeDelta class of the DateTime module allows the addition and subtraction of dates and times, while Dateutil.relativeDelta provides more complex date interval calculations.

from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta

now = datetime.now()
tomorrow = now + timedelta(days=1)
next_month = now + relativedelta(months=1)
print(tomorrow)
print(next_month)           

These tools are essential for time-related applications and can easily handle complex date calculations.

So far, we've explored the useful features of metaprogramming, advanced modules, and how they can be used to enhance the functionality and robustness of your program. Finally, let's focus on advanced exception handling techniques and performance-optimized strategies, which are key to writing high-quality Python code.

By mastering these advanced features, your Python programming skills will reach a new level, not only making your code more concise and efficient, but also being able to solve more complex problems. As you continue to practice and explore, you will find that the world of Python is far deeper and more exciting than when you first saw it.

Author: Hands-on PythonAI Programming

Link: https://mp.weixin.qq.com/s/4tsZUH0yZrzR8JrgHGSpUQ