Vượt qua giá trị Python

Điều quan trọng là phải hiểu cơ chế truyền tham số trong Python, cơ chế này thường cho phép chúng ta mắc ít lỗi hơn và nâng cao hiệu quả khi viết mã

Truyền theo giá trị so với Truyền theo tham chiếu

Nếu bạn có nền tảng ngôn ngữ lập trình khác, chẳng hạn như C/C++, thì dễ hiểu rằng có hai kiểu truyền tham số phổ biến. pass-by-value và pass-by-reference

  • giá trị vượt qua. Sao chép giá trị của tham số và chuyển nó vào biến mới trong hàm
  • chuyển qua tham chiếu. Truyền tham chiếu của tham số cho biến mới, để biến ban đầu và biến mới sẽ trỏ đến cùng một địa chỉ bộ nhớ

Vậy làm cách nào để truyền tham số hoạt động trong Python?

Trước khi trả lời câu hỏi này, trước tiên chúng ta hãy hiểu các nguyên tắc cơ bản của các biến và phép gán trong Python

Các biến và bài tập trong Python

Hãy bắt đầu bằng cách xem ví dụ mã Python sau

a = 1
b = a
a = a + 1

Ở đây, trước tiên,

l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
8 được gán cho
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
9, nghĩa là,
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
9 trỏ tới đối tượng
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
8, như thể hiện trong sơ đồ sau

Khi đó,

l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
0 có nghĩa là, hãy để biến
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
1 đồng thời trỏ đến đối tượng
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
8 cùng một lúc. Lưu ý ở đây rằng các đối tượng trong Python có thể được trỏ tới hoặc tham chiếu bởi nhiều biến. Bây giờ lưu đồ trông như thế này

Cuối cùng, câu lệnh

l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
3. Cần lưu ý rằng các kiểu dữ liệu Python, chẳng hạn như số nguyên [int], chuỗi [string], v.v. , là bất biến. Vì vậy,
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
3, không tăng giá trị của
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
9 lên 1, nhưng có nghĩa là một đối tượng mới có giá trị của
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
6 được tạo và
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
9 trỏ tới nó. Nhưng
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
1 vẫn không thay đổi và vẫn trỏ đến đối tượng
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
8

Tại thời điểm này, bạn có thể thấy rằng một phép gán đơn giản

l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
0 không có nghĩa là một đối tượng mới được tạo lại, mà là cùng một đối tượng được trỏ hoặc tham chiếu bởi nhiều biến

Đồng thời, trỏ đến cùng một đối tượng không có nghĩa là hai biến bị ràng buộc với nhau. Nếu bạn gán lại một trong các biến, nó sẽ không ảnh hưởng đến giá trị của các biến khác

Bây giờ chúng ta hãy xem một ví dụ về danh sách

l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]

Lúc đầu, chúng tôi để danh sách

l = [1, 2, 3]
del l
1 và
l = [1, 2, 3]
del l
2 trỏ đến đối tượng [1, 2, 3] cùng một lúc

Vì danh sách có thể thay đổi, nên

l = [1, 2, 3]
del l
3 không tạo danh sách mới, nó chỉ chèn phần tử 4 vào cuối danh sách ban đầu, danh sách này trở thành [1, 2, 3, 4]. Do
l = [1, 2, 3]
del l
1 và
l = [1, 2, 3]
del l
2 trỏ đến danh sách này cùng một lúc nên sự thay đổi của danh sách sẽ được phản ánh đồng thời vào hai biến của
l = [1, 2, 3]
del l
1 và
l = [1, 2, 3]
del l
2, khi đó giá trị của
l = [1, 2, 3]
del l
1 và
l = [1, 2, 3]
del l
2 sẽ trở thành [1, 2,

Ngoài ra, lưu ý rằng các biến trong Python có thể bị xóa, nhưng các đối tượng không thể bị xóa. Ví dụ đoạn mã sau

l = [1, 2, 3]
del l

l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
90 xóa biến
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
91, từ nay bạn không thể truy cập vào
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
91 nhưng đối tượng [1, 2, 3] vẫn tồn tại. Khi một chương trình Python chạy, hệ thống thu gom rác của chính nó sẽ theo dõi mọi tham chiếu đối tượng. Nếu [1, 2, 3] được tham chiếu ở những nơi khác ngoài
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
91, nó sẽ không được thu thập, nếu không, nó sẽ được thu thập

Vì vậy, trong Python

  • Việc gán một biến chỉ có nghĩa là biến đó trỏ đến một đối tượng và không có nghĩa là đối tượng được sao chép vào biến;
  • Thay đổi các đối tượng có thể thay đổi [danh sách, từ điển, bộ, v.v. ] ảnh hưởng đến tất cả các biến trỏ đến đối tượng đó
  • Đối với các đối tượng không thay đổi [chuỗi, int, bộ dữ liệu, v.v. ], giá trị của tất cả các biến trỏ đến đối tượng luôn giống nhau và không thay đổi. Nhưng khi giá trị của một đối tượng bất biến được cập nhật bởi một số thao tác [+= v.v. ], một đối tượng mới được trả về
  • Các biến có thể bị xóa, nhưng các đối tượng không thể bị xóa
Truyền đối số cho các hàm Python

Hãy xem trích dẫn chính thức của Python

“Hãy nhớ rằng các đối số được truyền bằng phép gán trong Python. Vì phép gán chỉ tạo tham chiếu đến các đối tượng, nên không có bí danh giữa tên đối số trong trình gọi và callee, do đó không có tham chiếu gọi theo tham chiếu mỗi Se. ”

Truyền đối số của Python được truyền theo phép gán hoặc truyền theo tham chiếu đối tượng. Các kiểu dữ liệu trong Python đều là đối tượng nên khi truyền tham số chỉ để biến mới và biến ban đầu trỏ về cùng một đối tượng, không có chuyện truyền giá trị hay truyền tham chiếu

Ví dụ

l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
9

Tham số truyền vào đây làm cho các biến

l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
9 và
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
1 trỏ đến đối tượng
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
8 cùng một lúc. Nhưng khi chúng ta đến
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
97, hệ thống sẽ tạo một đối tượng mới với giá trị là
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
6 và để
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
1 trỏ tới nó; . Vì vậy, giá trị của a không thay đổi, nó vẫn là
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
8

Tuy nhiên, khi một đối tượng có thể thay đổi được truyền dưới dạng tham số cho hàm, việc thay đổi giá trị của đối tượng có thể thay đổi sẽ ảnh hưởng đến tất cả các biến trỏ đến nó. Ví dụ

l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
8

Ở đây,

l = [1, 2, 3]
del l
1 và
l = [1, 2, 3]
del l
2 trước tiên đều trỏ đến danh sách có giá trị [1, 2, 3]. Tuy nhiên, do danh sách có nhiều biến khi hàm
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
85 được thực thi và một phần tử mới
l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
86 được thêm vào cuối danh sách nên giá trị của các biến
l = [1, 2, 3]
del l
1 và
l = [1, 2, 3]
del l
2 cũng bị thay đổi

Tuy nhiên, ví dụ sau đây, dường như thêm một phần tử mới vào danh sách, lại mang lại kết quả khác biệt đáng kể

l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
5

Điều này là do câu lệnh

l1 = [1, 2, 3]
l2 = l1
l1.append[4]
l1
[1, 2, 3, 4]
l2
[1, 2, 3, 4]
89, có nghĩa là một danh sách mới với "phần tử 4 được thêm vào cuối" được tạo và
l = [1, 2, 3]
del l
2 trỏ đến đối tượng mới này

Phần kết luận

Không giống như các ngôn ngữ khác, việc truyền tham số trong Python không phải theo giá trị hay theo tham chiếu, mà theo phép gán hoặc tham chiếu đến các đối tượng

Cần lưu ý rằng phép gán hoặc chuyển tham chiếu của đối tượng ở đây không trỏ đến một địa chỉ bộ nhớ cụ thể mà là một đối tượng cụ thể

  • Nếu một đối tượng có thể thay đổi, khi nó thay đổi, tất cả các biến trỏ đến đối tượng này sẽ thay đổi theo
  • Nếu đối tượng là bất biến, một phép gán đơn giản chỉ có thể thay đổi giá trị của một trong các biến, khiến các biến còn lại không bị ảnh hưởng

Rõ ràng muốn thay đổi giá trị của biến thông qua hàm thường có 2 cách

  • Một là chuyển trực tiếp vào một kiểu dữ liệu biến [chẳng hạn như danh sách, từ điển, tập hợp] làm tham số và sửa đổi nó trực tiếp;
  • Hai là tạo một biến mới để lưu giá trị đã sửa đổi, sau đó trả về biến ban đầu

Trong công việc thực tế, chúng tôi thích sử dụng cái sau hơn, vì cách diễn đạt của nó rõ ràng và ít sai sót hơn

Python có cho phép chuyển theo giá trị không?

Python truyền các đối số không phải theo tham chiếu hay theo giá trị mà theo phép gán.

Vượt qua giá trị nghĩa là gì?

Theo định nghĩa, truyền theo giá trị có nghĩa là bạn đang tạo một bản sao trong bộ nhớ của giá trị của tham số thực được truyền vào, một bản sao nội dung của tham số thực. Use pass by value when when you are only "using" the parameter for some computation, not changing it for the client program.

Truyền theo giá trị với ví dụ là gì?

"Truyền theo giá trị" có nghĩa là bạn chuyển giá trị thực của biến vào hàm . Vì vậy, trong ví dụ của bạn, nó sẽ vượt qua giá trị 9. "Chuyển theo tham chiếu" có nghĩa là bạn chuyển chính biến đó vào hàm [không chỉ giá trị]. Vì vậy, trong ví dụ của bạn, nó sẽ truyền một đối tượng số nguyên có giá trị là 9.

Các đối tượng có vượt qua giá trị Python không?

Như chúng ta đã biết, trong Python, “ Tham chiếu đối tượng được truyền theo giá trị ”. Một hàm nhận một tham chiếu đến [và sẽ truy cập] cùng một đối tượng trong bộ nhớ như được sử dụng bởi người gọi.

Chủ Đề