Fundamentals 18 min read

Python Code Optimization Techniques: Principles and Practical Tips

This article presents a comprehensive guide to speeding up Python programs by applying optimization principles, avoiding global variables and attribute look‑ups, reducing unnecessary abstractions and data copies, improving loop constructs, using built‑in functions like join, leveraging short‑circuit logic, and employing tools such as numba for JIT compilation.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Python Code Optimization Techniques: Principles and Practical Tips

Python is a high‑level scripting language that often lags behind compiled languages like C/C++ in raw performance, but many inefficiencies can be mitigated with careful coding. The article first outlines three core optimization principles: avoid premature optimization, weigh the cost of speed versus readability, and focus on the true bottlenecks.

0. Code‑Optimization Principles

Before diving into concrete tricks, developers are reminded to let code work correctly first, consider trade‑offs between time and space, and target only the slow parts—typically inner loops.

1. Avoid Global Variables

# 不推荐写法。代码耗时:26.8秒
import math

size = 10000
for x in range(size):
    for y in range(size):
        z = math.sqrt(x) + math.sqrt(y)

Placing the logic inside a function reduces lookup time and yields a 15‑30% speed gain.

# 推荐写法。代码耗时:20.6秒
import math

def main():
    size = 10000
    for x in range(size):
        for y in range(size):
            z = math.sqrt(x) + math.sqrt(y)

main()

2. Reduce Attribute Access

2.1 Directly import functions to bypass module attribute look‑ups.

# 不推荐写法。代码耗时:14.5秒
import math

def computeSqrt(size: int):
    result = []
    for i in range(size):
        result.append(math.sqrt(i))
    return result

def main():
    size = 10000
    for _ in range(size):
        result = computeSqrt(size)

main()
# 第一次优化写法。代码耗时:10.9秒
from math import sqrt

def computeSqrt(size: int):
    result = []
    for i in range(size):
        result.append(sqrt(i))
    return result

def main():
    size = 10000
    for _ in range(size):
        result = computeSqrt(size)

main()

Assigning frequently used functions to local variables removes the extra dictionary lookup.

# 第二次优化写法。代码耗时:9.9秒
import math

def computeSqrt(size: int):
    result = []
    sqrt = math.sqrt
    for i in range(size):
        result.append(sqrt(i))
    return result

def main():
    size = 10000
    for _ in range(size):
        result = computeSqrt(size)

main()

Further, caching list.append yields additional gains.

# 推荐写法。代码耗时:7.9秒
import math

def computeSqrt(size: int):
    result = []
    append = result.append
    sqrt = math.sqrt
    for i in range(size):
        append(sqrt(i))
    return result

def main():
    size = 10000
    for _ in range(size):
        result = computeSqrt(size)

main()

2.2 The same idea applies to class attributes.

# 不推荐写法。代码耗时:10.4秒
import math
from typing import List

class DemoClass:
    def __init__(self, value: int):
        self._value = value
    def computeSqrt(self, size: int) -> List[float]:
        result = []
        append = result.append
        sqrt = math.sqrt
        for _ in range(size):
            append(sqrt(self._value))
        return result

def main():
    size = 10000
    for _ in range(size):
        demo_instance = DemoClass(size)
        result = demo_instance.computeSqrt(size)

main()
# 推荐写法。代码耗时:8.0秒
import math
from typing import List

class DemoClass:
    def __init__(self, value: int):
        self._value = value
    def computeSqrt(self, size: int) -> List[float]:
        result = []
        append = result.append
        sqrt = math.sqrt
        value = self._value
        for _ in range(size):
            append(sqrt(value))
        return result

def main():
    size = 10000
    for _ in range(size):
        demo_instance = DemoClass(size)
        demo_instance.computeSqrt(size)

main()

3. Avoid Unnecessary Abstraction

# 不推荐写法,代码耗时:0.55秒
class DemoClass:
    def __init__(self, value: int):
        self.value = value
    @property
    def value(self) -> int:
        return self._value
    @value.setter
    def value(self, x: int):
        self._value = x

def main():
    size = 1000000
    for i in range(size):
        demo_instance = DemoClass(size)
        value = demo_instance.value
        demo_instance.value = i

main()
# 推荐写法,代码耗时:0.33秒
class DemoClass:
    def __init__(self, value: int):
        self.value = value

def main():
    size = 1000000
    for i in range(size):
        demo_instance = DemoClass(size)
        value = demo_instance.value
        demo_instance.value = i

main()

4. Eliminate Redundant Data Copies

# 不推荐写法,代码耗时:6.5秒
def main():
    size = 10000
    for _ in range(size):
        value = range(size)
        value_list = [x for x in value]
        square_list = [x * x for x in value_list]

main()
# 推荐写法,代码耗时:4.8秒
def main():
    size = 10000
    for _ in range(size):
        value = range(size)
        square_list = [x * x for x in value]

main()

Swap without a temporary variable:

# 不推荐写法,代码耗时:0.07秒
def main():
    size = 1000000
    for _ in range(size):
        a = 3
        b = 5
        temp = a
        a = b
        b = temp

main()
# 推荐写法,代码耗时:0.06秒
def main():
    size = 1000000
    for _ in range(size):
        a = 3
        b = 5
        a, b = b, a

main()

5. Prefer str.join Over + for Concatenation

# 不推荐写法,代码耗时:2.6秒
import string
from typing import List

def concatString(string_list: List[str]) -> str:
    result = ''
    for str_i in string_list:
        result += str_i
    return result

def main():
    string_list = list(string.ascii_letters * 100)
    for _ in range(10000):
        result = concatString(string_list)

main()
# 推荐写法,代码耗时:0.3秒
import string
from typing import List

def concatString(string_list: List[str]) -> str:
    return ''.join(string_list)

def main():
    string_list = list(string.ascii_letters * 100)
    for _ in range(10000):
        result = concatString(string_list)

main()

6. Use Short‑Circuit Logic in if Statements

# 不推荐写法,代码耗时:0.05秒
from typing import List

def concatString(string_list: List[str]) -> str:
    abbreviations = {'cf.', 'e.g.', 'ex.', 'etc.', 'flg.', 'i.e.', 'Mr.', 'vs.'}
    result = ''
    for str_i in string_list:
        if str_i in abbreviations:
            result += str_i
    return result

def main():
    for _ in range(10000):
        string_list = ['Mr.', 'Hat', 'is', 'Chasing', 'the', 'black', 'cat', '.']
        result = concatString(string_list)

main()
# 推荐写法,代码耗时:0.03秒
from typing import List

def concatString(string_list: List[str]) -> str:
    abbreviations = {'cf.', 'e.g.', 'ex.', 'etc.', 'flg.', 'i.e.', 'Mr.', 'vs.'}
    result = ''
    for str_i in string_list:
        if str_i[-1] == '.' and str_i in abbreviations:
            result += str_i
    return result

def main():
    for _ in range(10000):
        string_list = ['Mr.', 'Hat', 'is', 'Chasing', 'the', 'black', 'cat', '.']
        result = concatString(string_list)

main()

7. Loop Optimizations

Replace while with for loops.

# 不推荐写法。代码耗时:6.7秒
def computeSum(size: int) -> int:
    sum_ = 0
    i = 0
    while i < size:
        sum_ += i
        i += 1
    return sum_

def main():
    size = 10000
    for _ in range(size):
        sum_ = computeSum(size)

main()
# 推荐写法。代码耗时:4.3秒
def computeSum(size: int) -> int:
    sum_ = 0
    for i in range(size):
        sum_ += i
    return sum_

def main():
    size = 10000
    for _ in range(size):
        sum_ = computeSum(size)

main()

Use built‑in functions to hide the loop.

# 推荐写法。代码耗时:1.7秒
def computeSum(size: int) -> int:
    return sum(range(size))

def main():
    size = 10000
    for _ in range(size):
        sum = computeSum(size)

main()

Cache expensive calls outside inner loops.

# 不推荐写法。代码耗时:12.8秒
import math

def main():
    size = 10000
    sqrt = math.sqrt
    for x in range(size):
        for y in range(size):
            z = sqrt(x) + sqrt(y)

main()
# 推荐写法。代码耗时:7.0秒
import math

def main():
    size = 10000
    sqrt = math.sqrt
    for x in range(size):
        sqrt_x = sqrt(x)
        for y in range(size):
            z = sqrt_x + sqrt(y)

main()

8. JIT Compilation with numba

# 推荐写法。代码耗时:0.62秒
import numba

@numba.jit
def computeSum(size: float) -> int:
    sum = 0
    for i in range(size):
        sum += i
    return sum

def main():
    size = 10000
    for _ in range(size):
        sum = computeSum(size)

main()

9. Choose Appropriate Data Structures

Built‑in containers (list, dict, set, tuple) are implemented in C and are usually faster than custom structures. For frequent insert/delete at both ends, collections.deque offers O(1) operations. For fast ordered look‑ups, bisect on a sorted list or heapq for min/max retrieval are recommended.

References:

David Beazley & Brian K. Jones, Python Cookbook, Third edition , O'Reilly Media, 2013.

张颖 & 赖勇浩, 编写高质量代码:改善Python程序的91个建议 , 机械工业出版社, 2014.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

performancePythonCode OptimizationProfiling
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.