ค่า "self" มีให้ใช้งานได้เฉพาะภายในเมธอดเมื่อฟังก์ชันถูกเรียกและระบุ
คุณไม่สามารถเข้าถึง "self" ในอาร์กิวเมนต์ที่ระบุให้เมธอด หรือภายในฟังก์ชันโดยไม่ระบุ "self" เป็นอาร์กิวเมนต์ มิฉะนั้น คุณจะเห็นข้อผิดพลาด "NameError: name 'self' is not defined"
ในคู่มือนี้ เราพูดถึงว่าข้อผิดพลาดนี้หมายถึงอะไรและทำไมมันจึงถูกยกขึ้น เราจะเดินทางผ่านชิ้นโค้ดบางชิ้นเพื่อช่วยคุณหาวิธีแก้ไขข้อผิดพลาดนี้ในโค้ดของคุณ
NameError: name 'self' is not defined
ตัวแปร "self" เก็บข้อมูลเกี่ยวกับออบเจ็กต์ภายในคลาส ค่าทั้งหมดที่ถูกกำหนดให้ออบเจ็กต์มีอยู่ในตัวแปร "self"
"self" ต้องถูกส่งผ่านเป็นอาร์กิวเมนต์หากคุณต้องการใช้มันในเมธอด ตัวแปร "self" ไม่สามารถใช้ในอาร์กิวเมนต์อื่นในเมธอดได้ เพราะมันเข้าถึงได้เฉพาะจากภายในเมธอด
คุณจะเจอข้อผิดพลาด "NameError: name 'self' is not defined" หากคุณ:
- ไม่ระบุ "self" เป็นอาร์กิวเมนต์
- ใช้ "self" เป็นอาร์กิวเมนต์ในอีกอาร์กิวเมนต์หนึ่ง
มาเดินทางผ่านแต่ละสถานการณ์ทีละอย่าง
สถานการณ์ #1: "self" ไม่ได้ถูกรายการเป็นอาร์กิวเมนต์
"self" ต้องถูกรายการเป็นอาร์กิวเมนต์เพื่อให้เข้าถึงได้ในเมธอด "self" ไม่ใช่ตัวแปรกล로บอล (global variable) มันเป็นตัวแปรโลคอล (local) ภายในคลาส
มาเขียนโปรแกรมที่เก็บข้อมูลเกี่ยวกับหนังในคลาส เราเริ่มต้นด้วยการกำหนดคลาสของเราด้วย constructor ที่เก็บค่าประมาณหนังของเรา:
class Movie: def __init__(self, name, year_released): self.name = name self.year_released = year_released
คลาสของเราสามารถจัดเก็บสองค่า: ชื่อหนังและปีที่ฉาย ต่อไป เราประกาศเมธอดที่ให้เราเปลี่ยนค่าของ "year_released":
def change_year(year_released): self.year_released = year_released print("{} was released in {}.".format(self.name, self.year_released)) เพื่อทดสอบโค้ดของเรา เราสร้างออบเจ็กต์ของคลาสของเรา ออบเจ็กต์นี้แทนหนัง Happy Gilmore ที่ฉายในปี 1996:
happy_gilmore = Movie("Happy Gilmore") happy_gilmore.change_year(1996) เราเรียกเมธอด change_year() บนออบเจ็กต์ของเรา เพื่อที่เราจะตั้งค่าปีที่หนังฉายเป็น 1996 มารันโค้ดของเราและดูว่ามันทำงานหรือไม่:
Traceback (most recent call last): File "main.py", line 11, in <module> happy_gilmore.change_year() File "main.py", line 7, in change_year self.year_released = year_released NameError: name 'self' is not defined
โค้ดของเราคืนค่าข้อผิดพลาด
ข้อผิดพลาดนี้ถูกยกขึ้นเพราะเราไม่ได้ส่ง "self" เป็นอาร์กิวเมนต์ให้เมธอดของเรา เราแก้ไขข้อผิดพลาดนี้โดยเพิ่ม "self" เป็นอาร์กิวเมนต์แรกในเมธอด change_year():
def change_year(self, year_released): self.year_released = year_released print("{} was released in {}.".format(self.name, self.year_released)) รันโค้ดของเราอีกครั้ง:
Happy Gilmore was released in 1996.
โค้ดของเรารันสำเร็จ!
สถานการณ์ #2: การใช้ "self" เป็นอาร์กิวเมนต์ในอีกอาร์กิวเมนต์หนึ่ง
"self" ถูกประเมินค่าเมื่อฟังก์ชันถูกเรียก นี่หมายความว่าคุณไม่สามารถมีอาร์กิวเมนต์ที่อ้างอิง "self" ในรายการอาร์กิวเมนต์ที่ระบุในการเรียกฟังก์ชันได้
อัปเดตเมธอด "year_released" ของเราให้ หากปีฉายที่แตกต่างไม่ได้ระบุ ข้อความจะถูกพิมพ์ไปยังคอนโซลบอกเราว่าปีของหนังไม่ได้ถูกเปลี่ยน
เราสามารถทำได้โดยการตั้งค่าอาร์กิวเมลเริ่มต้น (default argument) ในโค้ดของเรา:
def change_year(self, year_released=self.year_released): if year_released != self.year_released: self.year_released = year_released print("{} was released in {}.".format(self.name, self.year_released)) else: print("This movie has not been changed.") print(year_released) "year_released" ตอนนี้มีค่าเริ่มต้นเป็น "self.year_released" นี่หมายความว่าหากเราไม่ระบุค่าที่ปีควรเปลี่ยน ค่าเริ่มต้นจะถูกตั้ง หากเราระบุค่า ค่าที่เราระบุจะถูกใช้แทนค่าเริ่มต้น
หากค่าที่เราระบุไม่เท่ากับค่าของ "self.year_released" ค่าของ "self.year_released" จะถูกเปลี่ยน มิฉะนั้น ข้อความจะถูกพิมพ์ไปยังคอนโซลบอกผู้ใช้ว่าหนังไม่ได้ถูกเปลี่ยน
หลังจากคำสั่ง if ของเราถูกประเมินค่าแล้ว ค่าของ "year_released" จะถูกพิมพ์ไปยังคอนโซล
มารันโค้ดของเรา:
Traceback (most recent call last): File "main.py", line 1, in <module> class Movie: File "main.py", line 6, in Movie def change_year(self, year_released=self.year_released): NameError: name 'self' is not defined
โค้ดของเรายกข้อผิดพลาดขึ้น นี่เป็นเพราะเราพยายามใช้ "self" ในอีกอาร์กิวเมนต์หนึ่งในรายการอาร์กิวเมนต์ของเรา
เราสามารถแก้ไขข้อผิดพลาดนี้โดยการตั้งค่าของตัวแปร "year_released" ให้เท่ากับ "self.year_released" ภายในฟังก์ชันของเราแทนที่จะเป็นในรายการอาร์กิวเมนต์ของเรา:
def change_year(self, year_released=None): if year_released != self.year_released: self.year_released = year_released print("{} was released in {}.".format(self.name, self.year_released)) else: year_released = self.year_released print("This movie has not been changed.") print(year_released) ในโค้ดนี้ เราตั้ง "year_released" ให้เท่ากับ "self.year_released" หากเราไม่ระบุค่าสำหรับ "year_released" ในการเรียกฟังก์ชันของเรา
มาสร้างออบเจ็กต์ Movie ใหม่เพื่อทดสอบโค้ดของเรา:
happy_gilmore = Movie("Happy Gilmore", 1995) happy_gilmore.change_year(1996) เราระบุปีที่ Happy Gilmore ฉายผิดเป็น 1995 เราต้องเปลี่ยนมันโดยใช้เมธอด change_year() โค้ดของเราคืนค่า:
Happy Gilmore was released in 1996. 1996
โค้ดของเราถูก execute สำเร็จ มาทดสอบโค้ดของเราดูว่าจะเกิดอะไรขึ้น หากค่าของ "year_released" เท่ากับค่าที่เราระบุในเมธอด change_year() แล้ว:
happy_gilmore = Movie("Happy Gilmore", 1996) happy_gilmore.change_year(1996) โค้ดของเราคืนค่า:
This movie has not been changed. 1996
โค้ดของเรา execute คำสั่ง else ในโค้ดของเรา และบอกเราว่าหนังไม่ได้ถูกเปลี่ยน
สรุป
ข้อผิดพลาด "NameError: name 'self' is not defined" ถูกยกขึ้นเมื่อคุณลืมระบุ "self" เป็น positional argument หรือเมื่อคุณใช้ "self" ในอีกอาร์กิวเมนต์หนึ่งในรายการอาร์กิวเมนต์
คุณแก้ไขข้อผิดพลาดนี้โดยการแน่ใจว่าทุกเมธอดในฟังก์ชันที่ใช้ "self" รวม "self" ในรายการอาร์กิวเมนต์ของพวกมัน หากไม่ได้ ให้ตรวจสอบว่าไม่มีอาร์กิวเมนต์ในรายการอาร์กิวเมนต์ที่พึ่งพา "self" สำหรับค่าเริ่มต้นของพวกมัน
ตอนนี้คุณพร้อมที่จะแก้ไขข้อผิดพลาด Python นี้อย่างนักพัฒนามืออาชีพแล้ว!