Sử dụng Python Timeit để tính thời gian cho mã của bạn

Spread the love

Trong hướng dẫn này, bạn sẽ học cách sử dụng hàm timeit từ mô-đun timeit của Python. Bạn sẽ học cách tính thời gian cho các biểu thức và hàm đơn giản trong Python.

Đặt thời gian cho mã của bạn có thể giúp bạn ước tính thời gian thực thi của một đoạn mã, đồng thời xác định các phần mã cần được tối ưu hóa.

Chúng ta sẽ bắt đầu bằng cách tìm hiểu cú pháp của hàm timeit trong Python. Và sau đó, chúng ta sẽ viết mã ví dụ để hiểu cách sử dụng nó để tính thời gian cho các khối mã và chức năng trong mô-đun Python của bạn. Hãy bắt đầu nào.

Cách sử dụng hàm timeit trong Python

Mô-đun timeit là một phần của thư viện chuẩn Python và bạn có thể nhập nó:

import timeit

Cú pháp sử dụng hàm timeit từ mô-đun timeit như sau:

timeit.timeit(stmt, setup, number)

Nơi đây:

  • stmt là đoạn mã cần đo thời gian thực thi. Bạn có thể chỉ định nó dưới dạng một chuỗi Python đơn giản hoặc một chuỗi nhiều dòng hoặc chuyển vào tên có thể gọi được.
  • Như tên gợi ý, thiết lập biểu thị đoạn mã chỉ cần chạy một lần, thường là điều kiện tiên quyết để stmt chạy. Ví dụ: giả sử bạn đang tính toán thời gian thực hiện để tạo một mảng NumPy. Trong trường hợp này, nhập numpy là mã thiết lập và việc tạo thực tế là câu lệnh được tính thời gian.
  • Số tham số biểu thị số lần stmt được chạy. Giá trị mặc định của số là 1 triệu (1000000), nhưng bạn cũng có thể đặt tham số này thành bất kỳ giá trị nào khác mà bạn chọn.

Bây giờ chúng ta đã học cú pháp để sử dụng hàm timeit(), hãy bắt đầu mã hóa một số ví dụ.

Thời gian biểu thức Python đơn giản

Trong phần này, chúng ta sẽ thử đo thời gian thực hiện của các biểu thức Python đơn giản bằng cách sử dụng timeit.

Bắt đầu REPL Python và chạy các ví dụ mã sau. Ở đây, chúng tôi đang tính toán thời gian thực hiện của các phép toán lũy thừa và chia sàn cho 10000 và 100000 lần chạy.

Lưu ý rằng chúng tôi chuyển vào câu lệnh để được tính thời gian dưới dạng chuỗi Python và sử dụng dấu chấm phẩy để phân tách các biểu thức khác nhau trong câu lệnh.

>>> import timeit
>>> timeit.timeit('3**4;3//4',number=10000)
0.0004020999999738706

>>> timeit.timeit('3**4;3//4',number=100000)
0.0013780000000451764

Chạy Python timeit tại Dòng lệnh

Bạn cũng có thể sử dụng timeit tại dòng lệnh. Đây là dòng lệnh tương đương với lệnh gọi hàm timeit:

$ python-m timeit -n [number] -s [setup] [stmt]
  • python -m timeit thể hiện rằng chúng tôi chạy timeit làm mô-đun chính.
  • n là một tùy chọn dòng lệnh biểu thị số lần mã sẽ chạy. Điều này tương đương với đối số số trong lệnh gọi hàm timeit().
  • Bạn có thể sử dụng tùy chọn -s để xác định mã thiết lập.
  Cách cắt ảnh

Ở đây, chúng tôi viết lại ví dụ trước bằng cách sử dụng dòng lệnh tương đương:

$ python -m timeit -n 100000 '3**4;3//4'
100000 loops, best of 5: 35.8 nsec per loop

Trong ví dụ này, chúng tôi tính toán thời gian thực hiện của hàm len() tích hợp sẵn. Việc khởi tạo chuỗi là mã thiết lập được chuyển vào bằng cách sử dụng tùy chọn s.

$ python -m timeit -n 100000 -s "string_1 = 'coding'" 'len(string_1)'
100000 loops, best of 5: 239 nsec per loop

Ở đầu ra, lưu ý rằng chúng tôi nhận được thời gian thực hiện tốt nhất trong 5 lần chạy. Điều đó có nghĩa là gì? Khi bạn chạy timeit tại dòng lệnh, tùy chọn lặp lại r được đặt thành giá trị mặc định là 5. Điều này có nghĩa là việc thực thi stmt cho số lần đã chỉ định được lặp lại năm lần và thời gian thực hiện tốt nhất được trả về.

Phân tích các phương pháp đảo ngược chuỗi bằng cách sử dụng timeit

Khi làm việc với chuỗi Python, bạn có thể muốn đảo ngược chúng. Hai cách tiếp cận phổ biến nhất để đảo ngược chuỗi như sau:

  • Sử dụng cắt chuỗi
  • Sử dụng hàm Reverse() và phương thức Join()

Đảo ngược chuỗi Python bằng cách cắt chuỗi

Hãy tìm hiểu cách hoạt động của thao tác cắt chuỗi và cách bạn có thể sử dụng nó để đảo ngược chuỗi Python. Sử dụng cú pháp some-string[start:stop] trả về một lát của chuỗi bắt đầu từ điểm bắt đầu của chỉ mục và kéo dài đến điểm dừng của chỉ mục-1. Hãy lấy một ví dụ.

Hãy xem xét chuỗi sau ‘Python’. Chuỗi có độ dài 6 và danh sách các chỉ số là 0, 1, 2 cho đến 5.

>>> string_1 = 'Python'

Khi bạn chỉ định cả giá trị bắt đầu và kết thúc, bạn sẽ nhận được một lát chuỗi kéo dài từ điểm bắt đầu đến điểm dừng-1. Do đó, chuỗi_1[1:4] trả về ‘yth’.

>>> string_1 = 'Python'
>>> string_1[1:4]
'yth'

Khi bạn không chỉ định giá trị bắt đầu, giá trị bắt đầu mặc định bằng 0 được sử dụng và lát cắt bắt đầu ở chỉ số 0 và kéo dài đến điểm dừng – 1.

  Cách xem ứng dụng có chạy trên máy Mac M1 với Apple Silicon hay không

Ở đây, giá trị dừng là 3, vì vậy lát cắt bắt đầu ở chỉ số 0 và đi lên chỉ số 2.

>>> string_1[:3]
'Pyt'

Khi bạn không bao gồm chỉ mục dừng, bạn sẽ thấy rằng lát cắt bắt đầu từ chỉ mục bắt đầu (1) và kéo dài đến cuối chuỗi.

>>> string_1[1:]
'ython'

Bỏ qua cả giá trị bắt đầu và kết thúc trả về một lát của toàn bộ chuỗi.

>>> string_1[::]
'Python'

Hãy tạo một lát cắt với giá trị bước. Đặt các giá trị bắt đầu, dừng và bước tương ứng thành 1, 5 và 2. Chúng tôi nhận được một phần của chuỗi bắt đầu từ 1 kéo dài đến 4 (không bao gồm điểm kết thúc 5) chứa mọi ký tự thứ hai.

>>> string_1[1:5:2]
'yh'

Khi bạn sử dụng một bước phủ định, bạn có thể nhận được một lát cắt bắt đầu từ cuối chuỗi. Với bước được đặt thành -2, chuỗi_1[5:2:-2] đưa ra lát cắt sau:

>>> string_1[5:2:-2]
'nh'

Vì vậy, để có được một bản sao đảo ngược của chuỗi, chúng tôi bỏ qua các giá trị bắt đầu và kết thúc và đặt bước thành -1, như được hiển thị:

>>> string_1[::-1]
'nohtyP'

Tóm lại: chuỗi[::-1] trả về một bản sao đảo ngược của chuỗi.

Đảo ngược chuỗi bằng các hàm và phương thức chuỗi tích hợp

Hàm Reverse() tích hợp sẵn trong Python sẽ trả về một trình vòng lặp đảo ngược trên các phần tử của chuỗi.

>>> string_1 = 'Python'
>>> reversed(string_1)
<reversed object at 0x00BEAF70>

Vì vậy, bạn có thể lặp qua trình vòng lặp ngược bằng vòng lặp for:

for char in reversed(string_1):
    print(char)

Và truy cập các phần tử của chuỗi theo thứ tự ngược lại.

# Output
n
o
h
t
y
P

Tiếp theo, bạn có thể gọi phương thức join() trên trình vòng lặp ngược với cú pháp: .join(reversed(some-string)).

Đoạn mã dưới đây hiển thị một vài ví dụ trong đó dấu phân cách lần lượt là dấu gạch nối và khoảng trắng.

>>> '-'.join(reversed(string1))
'n-o-h-t-y-P'
>>> ' '.join(reversed(string1))
'n o h t y P'

Ở đây, chúng tôi không muốn bất kỳ dấu phân cách nào; vì vậy, hãy đặt dấu phân cách thành một chuỗi trống để nhận bản sao đảo ngược của chuỗi:

>>> ''.join(reversed(string1))
'nohtyP'

Sử dụng ”.join(reversed(some-string)) trả về một bản sao đã đảo ngược của chuỗi.

So sánh thời gian thực hiện Sử dụng timeit

Cho đến nay, chúng ta đã học được hai cách để đảo ngược chuỗi Python. Nhưng cái nào trong số chúng nhanh hơn? Hãy cùng tìm hiểu.

Trong một ví dụ trước khi chúng ta tính thời gian cho các biểu thức Python đơn giản, chúng ta không có bất kỳ mã thiết lập nào. Ở đây, chúng tôi đang đảo ngược chuỗi Python. Mặc dù hoạt động đảo ngược chuỗi chạy với số lần được chỉ định bởi số, nhưng mã thiết lập là phần khởi tạo của chuỗi sẽ chỉ chạy một lần.

>>> import timeit
>>> timeit.timeit(stmt="string_1[::-1]", setup = "string_1 = 'Python'", number = 100000)
0.04951830000001678
>>> timeit.timeit(stmt = "''.join(reversed(string_1))", setup = "string_1 = 'Python'", number = 100000)
0.12858760000000302

Đối với cùng một số lần chạy để đảo ngược chuỗi đã cho, phương pháp cắt chuỗi sẽ nhanh hơn so với sử dụng phương thức join() và hàm Reverse().

  Đặt mục tiêu từ tối thiểu khi bạn viết truyện ngắn hoặc tiểu thuyết

Định thời gian Các hàm Python Sử dụng timeit

Trong phần này, chúng ta hãy tìm hiểu cách tính thời gian cho các hàm Python với hàm timeit. Đưa ra một danh sách các chuỗi, hàm sau hasDigit trả về danh sách các chuỗi có ít nhất một chữ số.

def hasDigit(somelist):
     str_with_digit = []
     for string in somelist:
         check_char = [char.isdigit() for char in string]
         if any(check_char):
            str_with_digit.append(string)
     return str_with_digit

Bây giờ chúng tôi muốn đo thời gian thực hiện của hàm Python hasDigit() này bằng cách sử dụng timeit.

Trước tiên hãy xác định câu lệnh được tính thời gian (stmt). Đó là lệnh gọi hàm hasDigit() với một danh sách các chuỗi làm đối số. Tiếp theo, hãy xác định mã thiết lập. Bạn có thể đoán mã thiết lập phải là gì không?

Để lệnh gọi hàm chạy thành công, mã thiết lập phải bao gồm các phần sau:

  • Định nghĩa hàm hasDigit()
  • Việc khởi tạo danh sách đối số của chuỗi

Hãy xác định mã thiết lập trong chuỗi thiết lập, như hình bên dưới:

setup = """
def hasDigit(somelist):
    str_with_digit = []
    for string in somelist:
      check_char = [char.isdigit() for char in string]
      if any(check_char):
        str_with_digit.append(string)
    return str_with_digit
thislist=['puffin3','7frost','blue']
     """

Tiếp theo, chúng ta có thể sử dụng hàm timeit và lấy thời gian thực hiện hàm hasDigit() cho 100000 lần chạy.

import timeit
timeit.timeit('hasDigit(thislist)',setup=setup,number=100000)
# Output
0.2810094920000097

Phần kết luận

Bạn đã học cách sử dụng hàm timeit của Python để tính thời gian cho các biểu thức, hàm và các hàm có thể gọi khác. Điều này có thể giúp bạn đánh giá chuẩn mã của mình, so sánh thời gian thực hiện của các triển khai khác nhau của cùng một chức năng, v.v.

Hãy xem lại những gì chúng ta đã học được trong hướng dẫn này. Bạn có thể sử dụng hàm timeit() với cú pháp timeit.timeit(stmt=…,setup=…,number=…). Ngoài ra, bạn có thể chạy timeit tại dòng lệnh để tính thời gian cho các đoạn mã ngắn.

Bước tiếp theo, bạn có thể khám phá cách sử dụng các gói cấu hình Python khác như line-profiler và memprofiler để cấu hình mã của bạn theo thời gian và bộ nhớ tương ứng.

Tiếp theo, hãy tìm hiểu cách tính chênh lệch múi giờ trong Python.

x