Danh sách mặc định Python là gì?

Hôm nay, tôi muốn chia sẻ một lời khuyên cứu mạng nhanh chóng về một lỗi phổ biến mà các nhà phát triển Python vẫn có xu hướng mắc phải

TL;DR

Không sử dụng các đối số mặc định có thể thay đổi trong Python, trừ khi bạn có lý do THỰC SỰ chính đáng để làm như vậy

Tại sao?

Thay vào đó, hãy đặt mặc định là None và gán giá trị có thể thay đổi bên trong hàm

Giờ kể chuyện

Tôi đã gặp lỗi này một vài lần trong hành trình phát triển ban đầu của mình

  • Khi tôi mới bắt đầu thực hiện các dự án thực sự với Python [chắc 5-6 năm trước], tôi nhớ mình đã vấp phải một lỗi rất lạ. Một danh sách sẽ lớn hơn dự kiến ​​khi một chức năng được gọi nhiều lần, điều này sẽ gây ra các lỗi lạ
  • Khi còn học đại học, chúng tôi được giao một dự án phát triển thuật toán và người hướng dẫn đã gửi cho chúng tôi một chương trình để kiểm tra mã của chúng tôi. Tại một thời điểm, tôi hoàn toàn tin rằng mã của mình là chính xác, nhưng các bài kiểm tra vẫn thất bại

Trong trường hợp đầu tiên, tôi, một nhà phát triển trẻ đang học cách gỡ lỗi, đã rất tức giận vì anh ấy không biết tại sao danh sách đó lại ngày càng nhiều và anh ấy đã dành hàng giờ để cố gắng khắc phục sự cố này.

Trong trường hợp thứ hai, các sinh viên khác cũng gặp phải sự cố và người hướng dẫn cũng không biết gì, vì vậy thời gian của mọi người đã bị lãng phí

Trong cả hai trường hợp, thời gian và công sức có thể đã được tiết kiệm nếu chúng ta biết về sai lầm phổ biến này

Chúng ta đã làm gì sai?

Hóa ra là trong cả hai trường hợp, một danh sách trống đã được sử dụng làm đối số mặc định cho một hàm. Ừ, chỉ vậy thôi. Cái gì đó như

def compute_patterns[inputs=[]]:
    inputs.append["some stuff"]
    patterns = ["a list based on"] + inputs
    return patterns

Hãy tự mình thử. nếu bạn chạy chức năng này nhiều lần, bạn sẽ nhận được các kết quả khác nhau

>>> compute_patterns[]
['a list based on', 'some stuff']  # Expected
>>> compute_patterns[]
['a list based on', 'some stuff', 'some stuff']  # Woops!

Mặc dù trông không có vẻ gì nhiều, nhưng inputs=[] chính là cậu bé nghịch ngợm đã gây ra mớ hỗn độn này

Vấn đề

Trong Python, khi chuyển một giá trị có thể thay đổi làm đối số mặc định trong hàm, đối số mặc định sẽ bị thay đổi bất cứ khi nào giá trị đó bị thay đổi

Ở đây, "giá trị có thể thay đổi" đề cập đến bất kỳ thứ gì như danh sách, từ điển hoặc thậm chí là thể hiện của lớp

Điều gì đã xảy ra, chính xác?

Không dễ hiểu tại sao thực tế trên có thể là một vấn đề

Đây là những gì xảy ra chi tiết bằng cách sử dụng một ví dụ khác

def append[element, seq=[]]:
    seq.append[element]
    return seq

>>> append[1]  # seq is assigned to []
[1]  # This returns a reference the *same* list as the default for `seq`
>>> append[2]  # => `seq` is now given [1] as a default!
[1, 2]  # WTFs and headaches start here…

Như bạn có thể thấy, Python "giữ lại" giá trị mặc định và liên kết nó với hàm theo một cách nào đó. Vì nó bị biến đổi bên trong hàm, nên nó cũng được biến đổi như một mặc định. Cuối cùng, chúng tôi sử dụng một giá trị mặc định khác nhau mỗi khi hàm được gọi — duh

Giải pháp

Câu chuyện dài, giải pháp rất đơn giản

Sử dụng None làm giá trị mặc định và gán giá trị có thể thay đổi bên trong hàm

Vì vậy, thay vào đó, hãy làm điều này

# 👇
def append[element, seq=None]:
    if seq is None:  # 👍
        seq = []
    seq.append[element]
    return seq

>>> append[1]  # `seq` is assigned to []
[1]
>>> append[2]  # `seq` is assigned to [] again!
[2]  # Yay!

Đây thực sự là một mẫu rất phổ biến trong Python;

Nó phổ biến đến mức có một Đề xuất cải tiến Python [PEP] hiện đang được thực hiện [PEP 505 - Toán tử không nhận biết], trong số những thứ khác, cho phép đơn giản hóa mã ở trên và chỉ cần viết

def append[element, seq=None]:
    seq ??= []  # ✨
    seq.append[element]
    return seq

PEP vẫn là một bản nháp, nhưng tôi chỉ muốn đề cập đến nó vì tôi thực sự hy vọng các toán tử không nhận biết sẽ sớm trở thành một thứ trong Python. 🔥

bài học kinh nghiệm

của bạn đi. Hy vọng rằng bạn sẽ không bao giờ thấy mình sử dụng các giá trị mặc định có thể thay đổi trong mã Python nữa [trừ khi bạn muốn làm phiền mọi người]

Mặc định trong Python là gì?

Trong Python, tham số mặc định được xác định với giá trị dự phòng làm đối số mặc định . Các tham số như vậy là tùy chọn trong khi gọi hàm. Nếu không có đối số nào được cung cấp, thì giá trị mặc định sẽ được sử dụng và nếu có đối số được cung cấp, nó sẽ ghi đè lên giá trị mặc định.

Chức năng mặc định là gì?

Đối số mặc định trong C++ . a value provided in a function declaration that is automatically assigned by the compiler if the calling function doesn't provide a value for the argument.

Giá trị chỉ mục mặc định trong danh sách là gì?

Mặc định là 0. Một chỉ mục chỉ định nơi dừng tìm kiếm

Tại sao bạn không nên biến các đối số mặc định thành một danh sách trống?

Tại sao bạn không nên biến các đối số mặc định thành một danh sách trống? . d] là một ý tưởng tồi vì mặc định [] sẽ tích lũy dữ liệu và mặc định [] sẽ thay đổi với các lần gọi tiếp theo .

Chủ Đề