Viết vòng lặp tốt hơn

Viết mã Python hiệu quả

Logan Thomas

Scientific Software Technical Trainer, Enthought

Lưu ý bài học

  • Một số vòng lặp sau có thể loại bỏ bằng kỹ thuật đã học trước đó.

  • Ví dụ trong bài chỉ dùng cho mục đích minh họa.

alt=”Biển cảnh báo với chữ Cảnh báo: chỉ dùng để minh họa”

Viết mã Python hiệu quả

Viết vòng lặp tốt hơn

  • Hiểu từng lần lặp làm gì
  • Đưa phép tính chỉ thực hiện một lần ra ngoài (phía trên) vòng lặp
  • Dùng chuyển đổi tổng thể bên ngoài (phía dưới) vòng lặp
  • Việc nào làm một lần thì để ngoài vòng lặp
Viết mã Python hiệu quả

Đưa phép tính lên trước vòng lặp

import numpy as np

names = ['Absol', 'Aron', 'Jynx', 'Natu', 'Onix']
attacks = np.array([130, 70, 50, 50, 45])

for pokemon,attack in zip(names, attacks):
total_attack_avg = attacks.mean()
if attack > total_attack_avg: print( "{}'s attack: {} > average: {}!" .format(pokemon, attack, total_attack_avg) )
Absol's attack: 130 > average: 69.0!
Aron's attack: 70 > average: 69.0!
Viết mã Python hiệu quả
import numpy as np

names = ['Absol', 'Aron', 'Jynx', 'Natu', 'Onix']
attacks = np.array([130, 70, 50, 50, 45])

# Tính trung bình tổng một lần (ngoài vòng lặp) total_attack_avg = attacks.mean()
for pokemon,attack in zip(names, attacks): if attack > total_attack_avg: print( "{}'s attack: {} > average: {}!" .format(pokemon, attack, total_attack_avg) )
Absol's attack: 130 > average: 69.0!
Aron's attack: 70 > average: 69.0!
Viết mã Python hiệu quả

Đưa phép tính lên trước vòng lặp

%%timeit
for pokemon,attack in zip(names, attacks):

    total_attack_avg = attacks.mean()

    if attack > total_attack_avg:
        print(
            "{}'s attack: {} > average: {}!"
            .format(pokemon, attack, total_attack_avg)
        )
74.9 µs ± 3.42 µs mỗi vòng lặp (trung bình ± độ lệch chuẩn của 7 lần chạy, 10000 vòng lặp mỗi lần)
Viết mã Python hiệu quả

Đưa phép tính lên trước vòng lặp

%%timeit
# Tính trung bình tổng một lần (ngoài vòng lặp)
total_attack_avg = attacks.mean()

for pokemon,attack in zip(names, attacks):

    if attack > total_attack_avg:
        print(
            "{}'s attack: {} > average: {}!"
            .format(pokemon, attack, total_attack_avg)
        )
37.5 µs ± 281 ns mỗi vòng lặp (trung bình ± độ lệch chuẩn của 7 lần chạy, 10000 vòng lặp mỗi lần)
Viết mã Python hiệu quả

Dùng chuyển đổi tổng thể

names = ['Pikachu', 'Squirtle', 'Articuno', ...]
legend_status = [False, False, True, ...]
generations = [1, 1, 1, ...]

poke_data = [] for poke_tuple in zip(names, legend_status, generations):
poke_list = list(poke_tuple)
poke_data.append(poke_list)
print(poke_data)
[['Pikachu', False, 1], ['Squirtle', False, 1], ['Articuno', True, 1], ...]
Viết mã Python hiệu quả

Dùng chuyển đổi tổng thể

names = ['Pikachu', 'Squirtle', 'Articuno', ...]
legend_status = [False, False, True, ...]
generations = [1, 1, 1, ...]

poke_data_tuples = [] for poke_tuple in zip(names, legend_status, generations): poke_data_tuples.append(poke_tuple)
poke_data = [*map(list, poke_data_tuples)]
print(poke_data)
[['Pikachu', False, 1], ['Squirtle', False, 1], ['Articuno', True, 1], ...]
Viết mã Python hiệu quả
%%timeit
poke_data = []
for poke_tuple in zip(names, legend_status, generations):
    poke_list = list(poke_tuple)
    poke_data.append(poke_list)
261 µs ± 23.2 µs mỗi vòng lặp (trung bình ± độ lệch chuẩn của 7 lần chạy, 1000 vòng lặp mỗi lần)
%%timeit
poke_data_tuples = []
for poke_tuple in zip(names, legend_status, generations):
    poke_data_tuples.append(poke_tuple)

poke_data = [*map(list, poke_data_tuples)]
224 µs ± 1.67 µs mỗi vòng lặp (trung bình ± độ lệch chuẩn của 7 lần chạy, 1000 vòng lặp mỗi lần)
Viết mã Python hiệu quả

Đến lúc thực hành!

Viết mã Python hiệu quả

Preparing Video For Download...