ทำไมคุณต้อง“ ตัวเอง” ใน Python เพื่ออ้างถึงตัวแปรอินสแตนซ์?


13

ฉันเขียนโปรแกรมเป็นภาษาต่างๆเช่น Java, Ruby, Haskell และ Python ฉันต้องสลับไปมาระหว่างหลายภาษาต่อวันเนื่องจากโครงการที่ฉันทำงานอยู่ ตอนนี้ปัญหาคือฉันมักจะลืมที่จะเขียนselfเป็นพารามิเตอร์แรกในนิยามฟังก์ชั่นใน Python เดียวกันกับวิธีการโทรบนวัตถุเดียวกัน

ที่กล่าวว่าฉันค่อนข้างประหลาดใจกับวิธีการของ Python นี้ โดยทั่วไปเราต้องพิมพ์ให้มากขึ้นเพื่อทำสิ่งต่าง ๆ ในภาษาอย่าง Java และ Ruby สิ่งต่าง ๆ ทำได้ง่ายโดยอ้างอิงตัวแปรในวัตถุปัจจุบันโดยอัตโนมัติ

คำถามของฉันคือเหตุใดจึงselfจำเป็น มันเป็นตัวเลือกสไตล์อย่างหมดจดหรือมีสาเหตุที่ Python ไม่สามารถให้คุณละเว้นselfวิธีที่ Java และ C ++ ปล่อยให้คุณละเว้นได้this?



1
@gnat ตอนนี้เป็นเพียงข้อดีและเป็นคำถามที่ดีอย่างจริงจังซึ่งกำลังไล่ฉันตั้งแต่สองสามวันโปรดอย่าฆ่ามันด้วยการลงคะแนน
vivek

2
คำถามนี้ได้รับมากกว่าอย่างทั่วถึงครอบคลุมโดยstackoverflow.com/questions/2709821/...
David Arno

ความเข้าใจของฉันคือว่ามันขึ้นอยู่กับรูปแบบ C ของการส่งตัวชี้ไปยัง struct เป็นอาร์กิวเมนต์แรก
Dannnno

เขียน@staticmethodก่อนการประกาศเมธอด, ระงับข้อผิดพลาด (สำหรับข้อมูลและยังไม่แนะนำ)
Yash

คำตอบ:


23

1) เหตุใดจึงselfจำเป็นต้องใช้เป็นพารามิเตอร์ที่ชัดเจนในลายเซ็นวิธีการ

เพราะวิธีการที่มีฟังก์ชั่นและเป็นเพียงน้ำตาลประโยคสำหรับfoo.bar(baz) bar(foo, baz)ชั้นเรียนเป็นเพียงพจนานุกรมที่มีค่าบางส่วนเป็นฟังก์ชั่น (ตัวสร้างเป็นเพียงฟังก์ชันซึ่งเป็นสาเหตุที่ Python ไม่ต้องการnew) คุณสามารถพูดได้ว่า Python ทำให้มันชัดเจนว่าวัตถุนั้นถูกสร้างจากส่วนประกอบที่ง่ายกว่า นี่เป็นไปตาม "ชัดเจนดีกว่าโดยนัย" - ปรัชญา

ในทางตรงกันข้ามในวัตถุ Java เป็นเวทย์มนตร์และไม่สามารถลดลงเพื่อส่วนประกอบที่ง่ายขึ้นในภาษา ใน Java (อย่างน้อยก็จนกว่า Java 8) ฟังก์ชั่นมักจะเป็นวิธีการที่เป็นเจ้าของวัตถุและความเป็นเจ้าของนี้ไม่สามารถเปลี่ยนแปลงได้เนื่องจากลักษณะคงที่ของภาษา ดังนั้นจึงไม่มีความเคลือบแคลงเกี่ยวกับสิ่งที่thisอ้างถึงดังนั้นจึงเหมาะสมที่จะนิยามไว้โดยปริยาย

JavaScript เป็นตัวอย่างของภาษาที่มีนัยโดยนัยthisเช่น Java แต่ฟังก์ชันที่สามารถมีอยู่แยกต่างหากจากวัตถุเช่นใน Python นำไปสู่การนี้เพื่อเป็นจำนวนมากของความสับสนเกี่ยวกับสิ่งที่thisหมายถึงเมื่อฟังก์ชั่นจะถูกส่งผ่านไปรอบ ๆ และที่เรียกว่าในบริบทที่แตกต่างกัน หลายคนคิดว่าสัญชาตญาณthisต้องอ้างถึงคุณสมบัติที่แท้จริงของฟังก์ชั่นในขณะที่มันถูกกำหนดอย่างแท้จริงโดยวิธีการที่เรียกว่าฟังก์ชั่น ฉันเชื่อว่าการมีthisพารามิเตอร์ที่ชัดเจนเหมือนใน Python จะทำให้เกิดความสับสนน้อยลง

ประโยชน์อื่น ๆ ของselfพารามิเตอร์ - ชัดเจน:

  • มัณฑนากรเป็นเพียงฟังก์ชั่นที่หุ้มฟังก์ชั่นอื่น ๆ เนื่องจากเมธอดเป็นเพียงฟังก์ชั่นมัณฑนากรจึงทำงานได้ดีในวิธีการ หากมีบางชนิดของตัวเองโดยนัยนักตกแต่งจะไม่ทำงานอย่างโปร่งใสในวิธีการ

  • วิธีการในชั้นเรียนและวิธีการคงที่ไม่ได้ใช้พารามิเตอร์เช่น Classmethods ใช้คลาสเป็นอาร์กิวเมนต์แรก (โดยทั่วไปเรียกว่าcls) ชัดเจนselfหรือclsพารามิเตอร์ทำให้ชัดเจนมากขึ้นสิ่งที่เกิดขึ้นและสิ่งที่คุณสามารถเข้าถึงได้ในวิธีการ

2) ทำไมตัวแปรอินสแตนซ์จึงต้องผ่านการรับรองด้วย "เสมอself.?

ใน Java คุณไม่จำเป็นต้องนำหน้าตัวแปรสมาชิกด้วย " this." แต่ใน Python " self." จำเป็นต้องมีเสมอ เหตุผลคือ Python ไม่มีไวยากรณ์ที่ชัดเจนสำหรับการประกาศตัวแปรดังนั้นจึงไม่มีวิธีที่จะบอกได้ว่าx = 7ควรจะประกาศตัวแปรท้องถิ่นใหม่หรือกำหนดให้กับตัวแปรสมาชิก การระบุself.แก้ความกำกวมนี้


การอ้างอิงตัวแปรสมาชิกโดยนัย (โดยไม่มีself.เช่น Java) นั้นไม่เข้ากับพื้นฐานของกฎการกำหนดขอบเขตและเมื่อคุณจำเป็นต้องมีความชัดเจนในที่นั้น
Jan Hudec

@ JanHudec: ดีจุด ฉันได้เพิ่มไปยังคำตอบ
JacquesB

6

มีเหตุผลที่ค่อนข้างง่ายที่ AFAIK ไม่ได้สัมผัสในการทำซ้ำข้ามไซต์หรือที่นี่: Python เริ่มต้นเป็นภาษาขั้นตอน มันขึ้นอยู่กับ ABC เป็นภาษาขั้นตอน

เพิ่มการวางแนววัตถุในภายหลังและเมื่อเพิ่มเข้ามากุยโดแวนรอสซัมต้องการเพิ่มฟีเจอร์จำนวนน้อยที่สุดเท่าที่จะเป็นไปได้เพื่อให้การออกแบบของ Python ง่ายขึ้น Python มีคุณสมบัติdictและฟังก์ชั่นอยู่แล้วดังนั้นทำไมจึงเพิ่มสิ่งใหม่ ๆ ลงในภาษาเมื่อวัตถุสามารถเป็นdictสล็อตและคลาสสามารถเป็นdictฟังก์ชันได้? วิธีการสามารถตีความได้ว่าเป็นฟังก์ชั่นที่ใช้บางส่วนที่ปิดมากกว่าอาร์กิวเมนต์ที่แตกต่างเดียว และนั่นเป็นวิธีการใช้งานวิธีที่แม่นยำใน Python: ไม่ใช่ มันเป็นเพียงฟังก์ชั่นที่รับอาร์กิวเมนต์พิเศษที่แตกต่าง


ฉันเชื่อว่า Python สนับสนุน OO และมีคลาสและการสืบทอดจากเวอร์ชันที่เผยแพร่ครั้งแรก อย่างน้อยนี่คือสิ่งที่วิกิพีเดียบอกฉัน แต่กระบวนการของ Ross Rossums ในขั้นต้นการออกแบบภาษาอาจเป็นไปตามที่คุณอธิบาย
JacquesB


ขอบคุณสำหรับลิงค์นี่คือการอ่านที่น่าสนใจจริงๆ
JacquesB

2

นี่คือข้อสรุปของฉันตามคำตอบข้างต้นและอ่านการท่องเที่ยวของกุยโดในหัวข้อนี้:

ความคิดที่ยิ่งใหญ่

ฟังก์ชั่นเป็นหน่วยการสร้างที่สำคัญใน Python (หรือเราควรจะพูดเพียงอันเดียว) อันที่จริงแล้วเราเลียนแบบ OOP โดยใช้ฟังก์ชั่น

เนื่องจาก class ไม่มีอะไรนอกจากพจนานุกรมของฟังก์ชั่นดังนั้นเราสามารถแนบฟังก์ชั่นใด ๆ กับคลาสใดก็ได้ ณ รันไทม์ โดยทั่วไปจะเป็นเพราะความจำเป็นที่จะโยนนี้ฟังก์ชั่นรอบในเวลาทำงานเราสามารถทำวัตถุดิบเช่นลิงปะ นี่คือselfพารามิเตอร์ที่สนับสนุนพารามิเตอร์หลากหลาย


1
สนับสนุนคำถามที่ตอบเองเมื่อคำตอบของคุณคือคำตอบที่มีคุณภาพสูง เมื่อฉันเปรียบเทียบคำตอบของคุณที่นี่กับคำตอบอื่นฉันสงสัยว่าทำไมคุณถึงรู้สึกว่าคุณต้องการที่จะเพิ่มสิ่งนี้ คำตอบอื่น ๆ จะเจาะลึกและเพิ่มรายละเอียดมากกว่าคำตอบของคุณ

1
@ GlenH7 คำตอบสำหรับการอ้างอิงของฉันเพราะทุกครั้งที่ฉันมาไม่ได้และอ่านคำตอบของทุกคนซ้ำแล้วซ้ำอีก เกี่ยวกับคุณภาพบอกฉันว่าข้อมูลใด ๆ ที่ทำให้เข้าใจผิด ต่อไปฉันมักจะรอ 2-3 วันเพื่อยอมรับคำตอบใด ๆ
vivek

การลงคะแนนเสียงกำลังกลายเป็นสกุลเงินที่ถูกและทุกคนที่นี่ใช้มันด้วยมือทั้งสองโดยไม่ทราบความหมายของมัน คุณรู้หรือไม่ว่ามีคนมาที่นี่ดูคำตอบที่ลงคะแนนนี้จะถือว่าผิด!
vivek
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.