Điều đặc biệt đối với các tham số mặc định đó là khi sử dụng các giá trị có thể thay đổi được như là list và dictionary thì giá trị này sẽ bị thay đổi trong lần gọi tiếp theo của hàm, mặc dù không hề truyền giá trị cho nó.
Giá trị tham số mặc định - giá trị có thay đổi
Ví dụ
Khi sử dụng tham số mặc định với giá trị có thể thay đổi.
def test(data = []): data.append(1) return data print("1:", test()) print("2:", test()) print("3:", test())
Kết quả:
1: [1] 2: [1, 1] 3: [1, 1, 1]
Giải thích ví dụ
Mỗi hàm trong Python được lưu trong các ô nhớ, kiểm tra địa chỉ hàm test()
thì thấy địa chỉ này không thay đổi qua mỗi lần gọi hàm test()
.
Để có thể kiểm tra các địa chỉ ô nhớ của hàm, sử dụng hàm id(object)
được cung cấp bởi Python để lấy giá trị địa chỉ.
print(id(test()) print(id(test()) print(id(test())
Kết quả
12511268 12511268 12511268
Theo như kết quả thì giá trị các ô nhớ này không hề thay đổi, tức là giá trị mặc định trong hàm cũng sẽ không thay đổi và qua mỗi lần gọi hàm, khi data.append(1)
thì giá trị mặc định data
trong hàm sẽ được cập nhật (bị thay đổi).
Do đó, nên sử dụng các giá trị không thể thay đổi cho tham số mặc định nhằm tránh trường hợp giá trị mặc định này bị thay đổi.
Giá trị tham số mặc định - giá trị không thay đổi
Áp dụng cho ví dụ
Đối với hàm test()
ở ví dụ trên, cho giá trị tham số mặc định data
là một giá trị không thay đổi.
def test(data = None): if data != None: data.append(1) return data
Cách khác:
obj = object() def test(data = obj): if data is obj: data = [] data.append(1) return data