Tại sao bạn cần phải tự. trong Python để chỉ các biến thể hiện?


13

Tôi đã lập trình thành một số ngôn ngữ như Java, Ruby, Haskell và Python. Tôi phải chuyển đổi giữa nhiều ngôn ngữ mỗi ngày do các dự án khác nhau mà tôi làm việc. Bây giờ, vấn đề là tôi thường quên viết selflà tham số đầu tiên trong các định nghĩa hàm trong Python giống với các phương thức gọi trên cùng một đối tượng.

Điều đó nói rằng, tôi khá ngạc nhiên với cách tiếp cận này của Python. Về cơ bản chúng ta phải gõ nhiều hơn để hoàn thành công việc, trong các ngôn ngữ như Java và Ruby, mọi thứ trở nên đơn giản bằng cách tự động tham chiếu các biến trong đối tượng hiện tại.

Câu hỏi của tôi là tại sao điều này là selfcần thiết? Đây hoàn toàn là một lựa chọn về phong cách, hay có lý do tại sao Python không thể cho phép bạn bỏ qua selfcách Java và C ++ cho phép bạn bỏ qua this?



1
@gnat bây giờ chỉ có ưu, và nghiêm túc đó là một câu hỏi hay đang làm phiền tôi sau vài ngày, xin đừng giết nó bằng cách bỏ phiếu.
vivek

2
Câu hỏi này đã được bao phủ kỹ lưỡng hơn bởi stackoverflow.com/questions/2709821/ cấp .
David Arno

Sự hiểu biết của tôi là nó dựa trên kiểu chữ C của việc chuyển một con trỏ đến một cấu trúc như là đối số đầu tiên.
Dannnno

Câu trả lời:


23

1) Tại sao được selfyêu cầu như một tham số rõ ràng trong chữ ký phương thức?

Bởi vì phương pháp là chức năng và foo.bar(baz)chỉ là cú pháp đường cho bar(foo, baz). Các lớp chỉ là từ điển trong đó một số giá trị là các hàm. (Trình xây dựng cũng chỉ là các hàm, đó là lý do Python không cần new) Bạn có thể nói rằng Python làm cho nó rõ ràng rằng các đối tượng được xây dựng từ các thành phần đơn giản hơn. Điều này phù hợp với triết lý "rõ ràng là tốt hơn ngầm".

Ngược lại, trong các đối tượng Java thực sự là ma thuật và không thể rút gọn thành các thành phần đơn giản hơn trong ngôn ngữ. Trong Java (ít nhất là cho đến Java 8), một hàm luôn là một phương thức thuộc sở hữu của một đối tượng và quyền sở hữu này không thể thay đổi do tính chất tĩnh của ngôn ngữ. Do đó, không có sự mơ hồ về những gì thisđề cập đến, vì vậy nó có ý nghĩa để nó được định nghĩa ngầm.

JavaScript là một ví dụ về ngôn ngữ có ẩn thisnhư Java, nhưng ở đó các hàm có thể tồn tại tách biệt với các đối tượng như trong Python. Điều này dẫn đến rất nhiều nhầm lẫn về những gì thisđề cập đến khi các chức năng được truyền qua và được gọi trong các bối cảnh khác nhau. Nhiều người nghĩ theo bản năng thisphải đề cập đến một số thuộc tính nội tại của hàm, trong khi nó thực sự được xác định hoàn toàn bằng cách gọi hàm. Tôi tin rằng việc có thismột tham số rõ ràng như trong Python sẽ làm cho điều này bớt khó hiểu hơn nhiều.

Một số lợi ích khác của tham số rõ ràng self:

  • Trang trí chỉ là chức năng bao bọc các chức năng khác. Vì các phương thức chỉ là các hàm, các trình trang trí hoạt động tốt như các phương thức. Nếu có một số loại tự ẩn, các nhà trang trí sẽ không làm việc minh bạch trên các phương pháp.

  • Classmethods và phương thức tĩnh không lấy tham số thể hiện. Classmethods lấy một lớp làm đối số đầu tiên (thường được gọi là cls). Các tham số rõ ràng selfhoặc clslàm cho nó rõ ràng hơn những gì đang diễn ra và những gì bạn có quyền truy cập trong phương thức.

2) Tại sao các biến thể hiện luôn phải đủ tiêu chuẩn với " self.?

Trong Java, bạn không cần phải thêm tiền tố vào các biến thành viên với " this.", nhưng trong Python " self." luôn được yêu cầu. Lý do là Python không có cú pháp rõ ràng để khai báo các biến, vì vậy sẽ không có cách nào để biết liệu x = 7có nên khai báo một biến cục bộ mới hay gán cho một biến thành viên hay không. Chỉ định self.giải quyết sự mơ hồ này.


Tham chiếu biến thành viên tiềm ẩn (không có self., giống như Java) về cơ bản không tương thích với các quy tắc phạm vi và khi bạn cần phải rõ ràng ở đó, việc ẩn về tham số không còn ý nghĩa gì nữa.
Jan Hudec

@JanHudec: Tốt, điểm. Tôi đã thêm nó vào câu trả lời.
JacquesB

6

Có một lý do khá đơn giản là AFAIK chưa thực sự được chạm đến trong bản sao chéo trang web, cũng không phải ở đây: Python bắt đầu như một ngôn ngữ thủ tục. Nó dựa trên ABC, cũng là một ngôn ngữ thủ tục.

Định hướng đối tượng đã được thêm vào sau đó và khi được thêm vào, Guido van Rossum muốn thêm số lượng tính năng tối thiểu có thể, để giữ cho thiết kế của Python đơn giản. Python đã có dicts và hàm, vậy tại sao lại thêm một thứ hoàn toàn mới vào ngôn ngữ, khi một đối tượng có thể chỉ đơn giản là một dictvị trí và một lớp có thể chỉ đơn giản là một dicthàm? Một phương thức có thể được hiểu là một hàm được áp dụng một phần, đóng trên một đối số phân biệt duy nhất. Và đó chính xác là cách các phương thức được triển khai trong Python: chúng không. Chúng chỉ là các hàm nhận được một đối số phân biệt.


Tôi tin rằng Python hỗ trợ OO và có các lớp và kế thừa từ phiên bản đầu tiên được phát hành. Ít nhất đây là những gì wikipedia nói với tôi. Nhưng quá trình van Rossums trong thiết kế ban đầu ngôn ngữ có thể đã được như bạn mô tả.
JacquesB


Cảm ơn bạn đã liên kết, đây là đọc thực sự thú vị.
JacquesB

2

Dưới đây là kết luận của tôi dựa trên các câu trả lời ở trên và đọc lan man của Guido về chủ đề này:

Ý tưởng lớn

Các hàm là các khối xây dựng quan trọng trong Python (hoặc chúng ta nên nói là duy nhất), trên thực tế chúng ta là loại mô phỏng OOP bằng cách sử dụng các hàm.

Do đó, một lớp không là gì ngoài một từ điển các hàm do đó, chúng ta có thể đính kèm bất kỳ hàm nào vào bất kỳ lớp nào trong thời gian chạy. Về cơ bản là do điều này cần phải ném các chức năng xung quanh trong thời gian chạy, chúng ta có thể làm những thứ như Monkey Patching . Ở đây selftham số hỗ trợ Đa hình tham số.


1
Câu hỏi tự trả lời được khuyến khích khi câu trả lời của bạn là câu trả lời chất lượng cao. Khi tôi so sánh câu trả lời của bạn ở đây với các câu trả lời khác, tôi sẽ tự hỏi tại sao bạn cảm thấy cần phải thêm câu trả lời này. Các câu trả lời khác đi sâu hơn và thêm chi tiết hơn những gì câu trả lời của bạn làm.

1
@ GlenH7 câu trả lời chỉ để tôi tham khảo vì mỗi lần tôi không thể đến và đọc lại câu trả lời của mọi người. Về chất lượng, cho tôi biết nếu có bất kỳ thông tin nào là sai lệch. Dù sao, tôi thường chờ 2-3 ngày để chấp nhận bất kỳ câu trả lời.
vivek

Bỏ phiếu đang trở thành loại tiền tệ rẻ và mọi người ở đây đang chi tiêu bằng cả hai tay mà không biết ý nghĩa của nó. Bạn có nhận ra nếu ai đó đến đây thấy câu trả lời này đã bỏ phiếu sẽ cho là sai!
vivek
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.