10 Advanced Tips to Improve Your Python Code

Python’s simplicity allows developers to write functional programs quickly, but advanced techniques can make your code even more efficient, maintainable, and elegant. These advanced tips and examples will take your Python skills to the next level.


1. Leverage Generators for Memory Efficiency

When working with large datasets, use generators instead of lists to save memory:

<span># List consumes memory upfront </span><span>numbers</span> <span>=</span> <span>[</span><span>i</span><span>**</span><span>2</span> <span>for</span> <span>i</span> <span>in</span> <span>range</span><span>(</span><span>1_000_000</span><span>)]</span>
<span># Generator evaluates lazily </span><span>numbers</span> <span>=</span> <span>(</span><span>i</span><span>**</span><span>2</span> <span>for</span> <span>i</span> <span>in</span> <span>range</span><span>(</span><span>1_000_000</span><span>))</span>
<span># Iterate over the generator </span><span>for</span> <span>num</span> <span>in</span> <span>numbers</span><span>:</span>
<span>print</span><span>(</span><span>num</span><span>)</span> <span># Processes one item at a time </span>
<span># List consumes memory upfront </span><span>numbers</span> <span>=</span> <span>[</span><span>i</span><span>**</span><span>2</span> <span>for</span> <span>i</span> <span>in</span> <span>range</span><span>(</span><span>1_000_000</span><span>)]</span>

<span># Generator evaluates lazily </span><span>numbers</span> <span>=</span> <span>(</span><span>i</span><span>**</span><span>2</span> <span>for</span> <span>i</span> <span>in</span> <span>range</span><span>(</span><span>1_000_000</span><span>))</span>

<span># Iterate over the generator </span><span>for</span> <span>num</span> <span>in</span> <span>numbers</span><span>:</span>
    <span>print</span><span>(</span><span>num</span><span>)</span>  <span># Processes one item at a time </span>
# List consumes memory upfront numbers = [i**2 for i in range(1_000_000)] # Generator evaluates lazily numbers = (i**2 for i in range(1_000_000)) # Iterate over the generator for num in numbers: print(num) # Processes one item at a time

Enter fullscreen mode Exit fullscreen mode

Why: Generators create items on-the-fly, avoiding the need to store the entire sequence in memory.


2. Use dataclasses for Simplified Classes

For classes that primarily store data, dataclasses reduce boilerplate code:

<span>from</span> <span>dataclasses</span> <span>import</span> <span>dataclass</span>
<span>@dataclass</span>
<span>class</span> <span>Employee</span><span>:</span>
<span>name</span><span>:</span> <span>str</span>
<span>age</span><span>:</span> <span>int</span>
<span>position</span><span>:</span> <span>str</span>
<span># Instead of defining __init__, __repr__, etc. </span><span>emp</span> <span>=</span> <span>Employee</span><span>(</span><span>name</span><span>=</span><span>"</span><span>Alice</span><span>"</span><span>,</span> <span>age</span><span>=</span><span>30</span><span>,</span> <span>position</span><span>=</span><span>"</span><span>Engineer</span><span>"</span><span>)</span>
<span>print</span><span>(</span><span>emp</span><span>)</span> <span># Employee(name='Alice', age=30, position='Engineer') </span>
<span>from</span> <span>dataclasses</span> <span>import</span> <span>dataclass</span>

<span>@dataclass</span>
<span>class</span> <span>Employee</span><span>:</span>
    <span>name</span><span>:</span> <span>str</span>
    <span>age</span><span>:</span> <span>int</span>
    <span>position</span><span>:</span> <span>str</span>

<span># Instead of defining __init__, __repr__, etc. </span><span>emp</span> <span>=</span> <span>Employee</span><span>(</span><span>name</span><span>=</span><span>"</span><span>Alice</span><span>"</span><span>,</span> <span>age</span><span>=</span><span>30</span><span>,</span> <span>position</span><span>=</span><span>"</span><span>Engineer</span><span>"</span><span>)</span>
<span>print</span><span>(</span><span>emp</span><span>)</span>  <span># Employee(name='Alice', age=30, position='Engineer') </span>
from dataclasses import dataclass @dataclass class Employee: name: str age: int position: str # Instead of defining __init__, __repr__, etc. emp = Employee(name="Alice", age=30, position="Engineer") print(emp) # Employee(name='Alice', age=30, position='Engineer')

Enter fullscreen mode Exit fullscreen mode

Why: dataclasses handle __init__ , __repr__, and other methods automatically.


3. Master Context Managers (with Statement)

Custom context managers simplify resource management:

<span>from</span> <span>contextlib</span> <span>import</span> <span>contextmanager</span>
<span>@contextmanager</span>
<span>def</span> <span>open_file</span><span>(</span><span>file_name</span><span>,</span> <span>mode</span><span>):</span>
<span>file</span> <span>=</span> <span>open</span><span>(</span><span>file_name</span><span>,</span> <span>mode</span><span>)</span>
<span>try</span><span>:</span>
<span>yield</span> <span>file</span>
<span>finally</span><span>:</span>
<span>file</span><span>.</span><span>close</span><span>()</span>
<span># Usage </span><span>with</span> <span>open_file</span><span>(</span><span>"</span><span>example.txt</span><span>"</span><span>,</span> <span>"</span><span>w</span><span>"</span><span>)</span> <span>as</span> <span>f</span><span>:</span>
<span>f</span><span>.</span><span>write</span><span>(</span><span>"</span><span>Hello, world!</span><span>"</span><span>)</span>
<span>from</span> <span>contextlib</span> <span>import</span> <span>contextmanager</span>

<span>@contextmanager</span>
<span>def</span> <span>open_file</span><span>(</span><span>file_name</span><span>,</span> <span>mode</span><span>):</span>
    <span>file</span> <span>=</span> <span>open</span><span>(</span><span>file_name</span><span>,</span> <span>mode</span><span>)</span>
    <span>try</span><span>:</span>
        <span>yield</span> <span>file</span>
    <span>finally</span><span>:</span>
        <span>file</span><span>.</span><span>close</span><span>()</span>

<span># Usage </span><span>with</span> <span>open_file</span><span>(</span><span>"</span><span>example.txt</span><span>"</span><span>,</span> <span>"</span><span>w</span><span>"</span><span>)</span> <span>as</span> <span>f</span><span>:</span>
    <span>f</span><span>.</span><span>write</span><span>(</span><span>"</span><span>Hello, world!</span><span>"</span><span>)</span>
from contextlib import contextmanager @contextmanager def open_file(file_name, mode): file = open(file_name, mode) try: yield file finally: file.close() # Usage with open_file("example.txt", "w") as f: f.write("Hello, world!")

Enter fullscreen mode Exit fullscreen mode

Why: Context managers ensure proper cleanup (e.g., closing files) even if an exception occurs.


4. Take Advantage of Function Annotations
Annotations improve clarity and enable static analysis:

<span>def</span> <span>calculate_area</span><span>(</span><span>length</span><span>:</span> <span>float</span><span>,</span> <span>width</span><span>:</span> <span>float</span><span>)</span> <span>-></span> <span>float</span><span>:</span>
<span>return</span> <span>length</span> <span>*</span> <span>width</span>
<span># IDEs and tools like MyPy can validate these annotations </span><span>area</span> <span>=</span> <span>calculate_area</span><span>(</span><span>5.0</span><span>,</span> <span>3.2</span><span>)</span>
<span>def</span> <span>calculate_area</span><span>(</span><span>length</span><span>:</span> <span>float</span><span>,</span> <span>width</span><span>:</span> <span>float</span><span>)</span> <span>-></span> <span>float</span><span>:</span>
    <span>return</span> <span>length</span> <span>*</span> <span>width</span>

<span># IDEs and tools like MyPy can validate these annotations </span><span>area</span> <span>=</span> <span>calculate_area</span><span>(</span><span>5.0</span><span>,</span> <span>3.2</span><span>)</span>
def calculate_area(length: float, width: float) -> float: return length * width # IDEs and tools like MyPy can validate these annotations area = calculate_area(5.0, 3.2)

Enter fullscreen mode Exit fullscreen mode

Why: Annotations make code self-documenting and help catch type errors during development.


5. Apply Decorators for Code Reuse

Decorators extend or modify functionality without changing the original function:

<span>def</span> <span>log_execution</span><span>(</span><span>func</span><span>):</span>
<span>def</span> <span>wrapper</span><span>(</span><span>*</span><span>args</span><span>,</span> <span>**</span><span>kwargs</span><span>):</span>
<span>print</span><span>(</span><span>f</span><span>"</span><span>Executing </span><span>{</span><span>func</span><span>.</span><span>__name__</span><span>}</span><span> with </span><span>{</span><span>args</span><span>}</span><span>, </span><span>{</span><span>kwargs</span><span>}</span><span>"</span><span>)</span>
<span>return</span> <span>func</span><span>(</span><span>*</span><span>args</span><span>,</span> <span>**</span><span>kwargs</span><span>)</span>
<span>return</span> <span>wrapper</span>
<span>@log_execution</span>
<span>def</span> <span>add</span><span>(</span><span>a</span><span>,</span> <span>b</span><span>):</span>
<span>return</span> <span>a</span> <span>+</span> <span>b</span>
<span>result</span> <span>=</span> <span>add</span><span>(</span><span>3</span><span>,</span> <span>5</span><span>)</span>
<span># Output: Executing add with (3, 5), {} </span>
<span>def</span> <span>log_execution</span><span>(</span><span>func</span><span>):</span>
    <span>def</span> <span>wrapper</span><span>(</span><span>*</span><span>args</span><span>,</span> <span>**</span><span>kwargs</span><span>):</span>
        <span>print</span><span>(</span><span>f</span><span>"</span><span>Executing </span><span>{</span><span>func</span><span>.</span><span>__name__</span><span>}</span><span> with </span><span>{</span><span>args</span><span>}</span><span>, </span><span>{</span><span>kwargs</span><span>}</span><span>"</span><span>)</span>
        <span>return</span> <span>func</span><span>(</span><span>*</span><span>args</span><span>,</span> <span>**</span><span>kwargs</span><span>)</span>
    <span>return</span> <span>wrapper</span>

<span>@log_execution</span>
<span>def</span> <span>add</span><span>(</span><span>a</span><span>,</span> <span>b</span><span>):</span>
    <span>return</span> <span>a</span> <span>+</span> <span>b</span>

<span>result</span> <span>=</span> <span>add</span><span>(</span><span>3</span><span>,</span> <span>5</span><span>)</span>
<span># Output: Executing add with (3, 5), {} </span>
def log_execution(func): def wrapper(*args, **kwargs): print(f"Executing {func.__name__} with {args}, {kwargs}") return func(*args, **kwargs) return wrapper @log_execution def add(a, b): return a + b result = add(3, 5) # Output: Executing add with (3, 5), {}

Enter fullscreen mode Exit fullscreen mode

Why: Decorators reduce duplication for tasks like logging, authentication, or timing functions.


6. Use functools for Higher-Order Functionality

The functools module simplifies complex function behaviors:

<span>from</span> <span>functools</span> <span>import</span> <span>lru_cache</span>
<span>@lru_cache</span><span>(</span><span>maxsize</span><span>=</span><span>100</span><span>)</span>
<span>def</span> <span>fibonacci</span><span>(</span><span>n</span><span>):</span>
<span>if</span> <span>n</span> <span><</span> <span>2</span><span>:</span>
<span>return</span> <span>n</span>
<span>return</span> <span>fibonacci</span><span>(</span><span>n</span> <span>-</span> <span>1</span><span>)</span> <span>+</span> <span>fibonacci</span><span>(</span><span>n</span> <span>-</span> <span>2</span><span>)</span>
<span>print</span><span>(</span><span>fibonacci</span><span>(</span><span>50</span><span>))</span> <span># Efficient due to caching </span>
<span>from</span> <span>functools</span> <span>import</span> <span>lru_cache</span>

<span>@lru_cache</span><span>(</span><span>maxsize</span><span>=</span><span>100</span><span>)</span>
<span>def</span> <span>fibonacci</span><span>(</span><span>n</span><span>):</span>
    <span>if</span> <span>n</span> <span><</span> <span>2</span><span>:</span>
        <span>return</span> <span>n</span>
    <span>return</span> <span>fibonacci</span><span>(</span><span>n</span> <span>-</span> <span>1</span><span>)</span> <span>+</span> <span>fibonacci</span><span>(</span><span>n</span> <span>-</span> <span>2</span><span>)</span>

<span>print</span><span>(</span><span>fibonacci</span><span>(</span><span>50</span><span>))</span>  <span># Efficient due to caching </span>
from functools import lru_cache @lru_cache(maxsize=100) def fibonacci(n): if n < 2: return n return fibonacci(n - 1) + fibonacci(n - 2) print(fibonacci(50)) # Efficient due to caching

Enter fullscreen mode Exit fullscreen mode

Why: Functions like lru_cache optimize performance by memoizing results of expensive function calls.


7. Understand the Power of collections

The collections module offers advanced data structures:

<span>from</span> <span>collections</span> <span>import</span> <span>defaultdict</span><span>,</span> <span>Counter</span>
<span># defaultdict with default value </span><span>word_count</span> <span>=</span> <span>defaultdict</span><span>(</span><span>int</span><span>)</span>
<span>for</span> <span>word</span> <span>in</span> <span>[</span><span>"</span><span>apple</span><span>"</span><span>,</span> <span>"</span><span>banana</span><span>"</span><span>,</span> <span>"</span><span>apple</span><span>"</span><span>]:</span>
<span>word_count</span><span>[</span><span>word</span><span>]</span> <span>+=</span> <span>1</span>
<span>print</span><span>(</span><span>word_count</span><span>)</span> <span># {'apple': 2, 'banana': 1} </span>
<span># Counter for frequency counting </span><span>freq</span> <span>=</span> <span>Counter</span><span>([</span><span>"</span><span>apple</span><span>"</span><span>,</span> <span>"</span><span>banana</span><span>"</span><span>,</span> <span>"</span><span>apple</span><span>"</span><span>])</span>
<span>print</span><span>(</span><span>freq</span><span>.</span><span>most_common</span><span>(</span><span>1</span><span>))</span> <span># [('apple', 2)] </span>
<span>from</span> <span>collections</span> <span>import</span> <span>defaultdict</span><span>,</span> <span>Counter</span>

<span># defaultdict with default value </span><span>word_count</span> <span>=</span> <span>defaultdict</span><span>(</span><span>int</span><span>)</span>
<span>for</span> <span>word</span> <span>in</span> <span>[</span><span>"</span><span>apple</span><span>"</span><span>,</span> <span>"</span><span>banana</span><span>"</span><span>,</span> <span>"</span><span>apple</span><span>"</span><span>]:</span>
    <span>word_count</span><span>[</span><span>word</span><span>]</span> <span>+=</span> <span>1</span>
<span>print</span><span>(</span><span>word_count</span><span>)</span>  <span># {'apple': 2, 'banana': 1} </span>
<span># Counter for frequency counting </span><span>freq</span> <span>=</span> <span>Counter</span><span>([</span><span>"</span><span>apple</span><span>"</span><span>,</span> <span>"</span><span>banana</span><span>"</span><span>,</span> <span>"</span><span>apple</span><span>"</span><span>])</span>
<span>print</span><span>(</span><span>freq</span><span>.</span><span>most_common</span><span>(</span><span>1</span><span>))</span>  <span># [('apple', 2)] </span>
from collections import defaultdict, Counter # defaultdict with default value word_count = defaultdict(int) for word in ["apple", "banana", "apple"]: word_count[word] += 1 print(word_count) # {'apple': 2, 'banana': 1} # Counter for frequency counting freq = Counter(["apple", "banana", "apple"]) print(freq.most_common(1)) # [('apple', 2)]

Enter fullscreen mode Exit fullscreen mode

Why: defaultdict and Counter simplify tasks like counting occurrences.


8. Parallelize with concurrent.futures

For CPU-bound or IO-bound tasks, parallel execution speeds up processing:

<span>from</span> <span>concurrent.futures</span> <span>import</span> <span>ThreadPoolExecutor</span>
<span>def</span> <span>square</span><span>(</span><span>n</span><span>):</span>
<span>return</span> <span>n</span> <span>*</span> <span>n</span>
<span>with</span> <span>ThreadPoolExecutor</span><span>(</span><span>max_workers</span><span>=</span><span>4</span><span>)</span> <span>as</span> <span>executor</span><span>:</span>
<span>results</span> <span>=</span> <span>executor</span><span>.</span><span>map</span><span>(</span><span>square</span><span>,</span> <span>range</span><span>(</span><span>10</span><span>))</span>
<span>print</span><span>(</span><span>list</span><span>(</span><span>results</span><span>))</span> <span># [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] </span>
<span>from</span> <span>concurrent.futures</span> <span>import</span> <span>ThreadPoolExecutor</span>

<span>def</span> <span>square</span><span>(</span><span>n</span><span>):</span>
    <span>return</span> <span>n</span> <span>*</span> <span>n</span>

<span>with</span> <span>ThreadPoolExecutor</span><span>(</span><span>max_workers</span><span>=</span><span>4</span><span>)</span> <span>as</span> <span>executor</span><span>:</span>
    <span>results</span> <span>=</span> <span>executor</span><span>.</span><span>map</span><span>(</span><span>square</span><span>,</span> <span>range</span><span>(</span><span>10</span><span>))</span>

<span>print</span><span>(</span><span>list</span><span>(</span><span>results</span><span>))</span>  <span># [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] </span>
from concurrent.futures import ThreadPoolExecutor def square(n): return n * n with ThreadPoolExecutor(max_workers=4) as executor: results = executor.map(square, range(10)) print(list(results)) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Enter fullscreen mode Exit fullscreen mode

Why: concurrent.futures makes multi-threading and multi-processing easier.


9. Use pathlib for File Operations
The pathlib module provides an intuitive and powerful way to work with file paths:

<span>from</span> <span>pathlib</span> <span>import</span> <span>Path</span>
<span>path</span> <span>=</span> <span>Path</span><span>(</span><span>"</span><span>example.txt</span><span>"</span><span>)</span>
<span># Write to a file </span><span>path</span><span>.</span><span>write_text</span><span>(</span><span>"</span><span>Hello, pathlib!</span><span>"</span><span>)</span>
<span># Read from a file </span><span>content</span> <span>=</span> <span>path</span><span>.</span><span>read_text</span><span>()</span>
<span>print</span><span>(</span><span>content</span><span>)</span>
<span># Check if a file exists </span><span>if</span> <span>path</span><span>.</span><span>exists</span><span>():</span>
<span>print</span><span>(</span><span>"</span><span>File exists</span><span>"</span><span>)</span>
<span>from</span> <span>pathlib</span> <span>import</span> <span>Path</span>

<span>path</span> <span>=</span> <span>Path</span><span>(</span><span>"</span><span>example.txt</span><span>"</span><span>)</span>

<span># Write to a file </span><span>path</span><span>.</span><span>write_text</span><span>(</span><span>"</span><span>Hello, pathlib!</span><span>"</span><span>)</span>

<span># Read from a file </span><span>content</span> <span>=</span> <span>path</span><span>.</span><span>read_text</span><span>()</span>
<span>print</span><span>(</span><span>content</span><span>)</span>

<span># Check if a file exists </span><span>if</span> <span>path</span><span>.</span><span>exists</span><span>():</span>
    <span>print</span><span>(</span><span>"</span><span>File exists</span><span>"</span><span>)</span>
from pathlib import Path path = Path("example.txt") # Write to a file path.write_text("Hello, pathlib!") # Read from a file content = path.read_text() print(content) # Check if a file exists if path.exists(): print("File exists")

Enter fullscreen mode Exit fullscreen mode

Why: pathlib is more readable and versatile compared to os and os.path.


10. Write Unit Tests with Mocking

Test complex systems by mocking dependencies:

<span>from</span> <span>unittest.mock</span> <span>import</span> <span>patch</span>
<span>def</span> <span>fetch_data</span><span>():</span>
<span># Simulating an API call </span> <span>return</span> <span>{</span><span>"</span><span>key</span><span>"</span><span>:</span> <span>"</span><span>value</span><span>"</span><span>}</span>
<span>@patch</span><span>(</span><span>'</span><span>__main__.fetch_data</span><span>'</span><span>,</span> <span>return_value</span><span>=</span><span>{</span><span>"</span><span>key</span><span>"</span><span>:</span> <span>"</span><span>mocked_value</span><span>"</span><span>})</span>
<span>def</span> <span>test_fetch_data</span><span>(</span><span>mock_fetch</span><span>):</span>
<span>data</span> <span>=</span> <span>fetch_data</span><span>()</span>
<span>assert</span> <span>data</span><span>[</span><span>"</span><span>key</span><span>"</span><span>]</span> <span>==</span> <span>"</span><span>mocked_value</span><span>"</span>
<span>test_fetch_data</span><span>()</span>
<span>from</span> <span>unittest.mock</span> <span>import</span> <span>patch</span>

<span>def</span> <span>fetch_data</span><span>():</span>
    <span># Simulating an API call </span>    <span>return</span> <span>{</span><span>"</span><span>key</span><span>"</span><span>:</span> <span>"</span><span>value</span><span>"</span><span>}</span>

<span>@patch</span><span>(</span><span>'</span><span>__main__.fetch_data</span><span>'</span><span>,</span> <span>return_value</span><span>=</span><span>{</span><span>"</span><span>key</span><span>"</span><span>:</span> <span>"</span><span>mocked_value</span><span>"</span><span>})</span>
<span>def</span> <span>test_fetch_data</span><span>(</span><span>mock_fetch</span><span>):</span>
    <span>data</span> <span>=</span> <span>fetch_data</span><span>()</span>
    <span>assert</span> <span>data</span><span>[</span><span>"</span><span>key</span><span>"</span><span>]</span> <span>==</span> <span>"</span><span>mocked_value</span><span>"</span>

<span>test_fetch_data</span><span>()</span>
from unittest.mock import patch def fetch_data(): # Simulating an API call return {"key": "value"} @patch('__main__.fetch_data', return_value={"key": "mocked_value"}) def test_fetch_data(mock_fetch): data = fetch_data() assert data["key"] == "mocked_value" test_fetch_data()

Enter fullscreen mode Exit fullscreen mode

Why: Mocking isolates the code under test, ensuring external dependencies don’t interfere with your tests.


Conclusion

Mastering these advanced techniques will elevate your Python coding skills. Incorporate them into your workflow to write code that’s not only functional but also efficient, maintainable, and Pythonic. Happy coding!

原文链接:10 Advanced Tips to Improve Your Python Code

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享
No one can change another. But one can be the reason for another to change.
没人能改变另一个人,但是某个人能成为一个人改变的原因
评论 抢沙发

请登录后发表评论

    暂无评论内容