เอาล่ะสิ่งแรกก่อน
ไม่มีสิ่งที่เรียกว่า "การประกาศตัวแปร" หรือ "การเริ่มต้นตัวแปร" ใน Python
มีเพียงสิ่งที่เราเรียกว่า "การมอบหมาย" แต่น่าจะเรียกว่า "การตั้งชื่อ"
การมอบหมายงานหมายถึง "ชื่อนี้ทางด้านซ้ายมือตอนนี้หมายถึงผลลัพธ์ของการประเมินด้านขวามือโดยไม่คำนึงถึงสิ่งที่อ้างถึงก่อนหน้านี้ (ถ้ามี)"
foo = 'bar'
foo = 2 * 3
ด้วยเหตุนี้ชื่อของ Python (คำที่ดีกว่า "ตัวแปร" เนื้อหา) จึงไม่มีประเภทที่เกี่ยวข้อง ค่าทำ คุณสามารถใช้ชื่อเดิมซ้ำกับอะไรก็ได้โดยไม่คำนึงถึงประเภท แต่สิ่งนั้นยังคงมีพฤติกรรมที่ขึ้นอยู่กับประเภทของมัน ชื่อเป็นเพียงวิธีอ้างถึงค่า (วัตถุ) สิ่งนี้ตอบคำถามที่สองของคุณ: คุณไม่ได้สร้างตัวแปรเพื่อเก็บประเภทที่กำหนดเอง คุณไม่ได้สร้างตัวแปรเพื่อเก็บประเภทใดประเภทหนึ่ง คุณไม่ได้ "สร้าง" ตัวแปรเลย คุณตั้งชื่อให้กับวัตถุ
จุดที่สอง: งูหลามตามกฎง่ายมากเมื่อมันมาถึงการเรียนที่เป็นจริงมากขึ้นกว่าสิ่งที่สอดคล้องภาษาเช่น Java, C ++ และ C # ทำทุกอย่างที่ประกาศภายในclass
บล็อกเป็นส่วนหนึ่งของการเรียน ดังนั้นฟังก์ชัน ( def
) ที่เขียนในที่นี้คือเมธอดซึ่งเป็นส่วนหนึ่งของคลาสอ็อบเจ็กต์ (ไม่ได้จัดเก็บแบบต่ออินสแตนซ์) เช่นเดียวกับใน Java, C ++ และ C #; แต่ชื่ออื่น ๆก็เป็นส่วนหนึ่งของชั้นเรียนเช่นกัน อีกครั้งชื่อเป็นเพียงชื่อและไม่มีประเภทที่เกี่ยวข้องและฟังก์ชันก็เป็นวัตถุเช่นกันใน Python ดังนั้น:
class Example:
data = 42
def method(self): pass
คลาสเป็นวัตถุเช่นกันใน Python
ตอนนี้เราได้สร้างอ็อบเจกต์ชื่อExample
ซึ่งแสดงถึงคลาสของทุกสิ่งที่เป็นExample
s อ็อบเจ็กต์นี้มีแอ็ตทริบิวต์ที่ผู้ใช้จัดหาให้สองแอ็ตทริบิวต์ (ใน C ++ "สมาชิก" ใน C # "ฟิลด์หรือคุณสมบัติหรือเมธอด" ใน Java "ฟิลด์หรือเมธอด") หนึ่งในนั้นคือการตั้งชื่อและเก็บค่าจำนวนเต็มdata
42
อีกตัวตั้งชื่อmethod
และเก็บอ็อบเจ็กต์ฟังก์ชัน (มีคุณสมบัติอื่น ๆ อีกมากมายที่ Python เพิ่มโดยอัตโนมัติ)
แอตทริบิวต์เหล่านี้ยังคงไม่ได้เป็นส่วนหนึ่งของวัตถุจริงๆ โดยพื้นฐานแล้วออบเจ็กต์เป็นเพียงกลุ่มของชื่ออื่น ๆ (ชื่อแอตทริบิวต์) จนกว่าคุณจะเข้าใจสิ่งที่ไม่สามารถแบ่งออกได้อีก ดังนั้นค่าสามารถใช้ร่วมกันระหว่างอินสแตนซ์ต่างๆของคลาสหรือแม้กระทั่งระหว่างอ็อบเจ็กต์ของคลาสต่างๆหากคุณตั้งใจตั้งค่านั้น
มาสร้างอินสแตนซ์:
x = Example()
ตอนนี้เรามีออบเจ็กต์แยกต่างหากชื่อx
ซึ่งเป็นตัวอย่างของExample
. data
และmethod
ไม่ได้เป็นส่วนหนึ่งของวัตถุ แต่เรายังคงสามารถมองพวกเขาผ่านทางx
มายากลเพราะบางอย่างที่หลามไม่อยู่เบื้องหลัง method
โดยเฉพาะอย่างยิ่งเมื่อเราค้นหาเราจะได้ "วิธีการผูก" แทน (เมื่อเราเรียกมันจะx
ถูกส่งผ่านโดยอัตโนมัติเป็นself
พารามิเตอร์ซึ่งไม่สามารถเกิดขึ้นได้หากเราค้นหาExample.method
โดยตรง)
จะเกิดอะไรขึ้นเมื่อเราพยายามใช้x.data
?
เมื่อเราตรวจสอบมันจะมองขึ้นไปในวัตถุก่อน หากไม่พบในวัตถุ Python จะดูในคลาส
อย่างไรก็ตามเมื่อเรากำหนดให้ x.data
Python จะสร้างแอตทริบิวต์บนวัตถุ จะไม่แทนที่แอตทริบิวต์ของคลาส
สิ่งนี้ช่วยให้เราทำการเริ่มต้นอ็อบเจ็กต์ Python จะเรียก__init__
เมธอดของคลาสโดยอัตโนมัติในอินสแตนซ์ใหม่เมื่อสร้างขึ้นหากมี ในวิธีนี้เราสามารถกำหนดให้กับแอตทริบิวต์เพื่อกำหนดค่าเริ่มต้นสำหรับแอตทริบิวต์นั้นในแต่ละวัตถุ:
class Example:
name = "Ignored"
def __init__(self, name):
self.name = name
ตอนนี้เราต้องระบุname
เมื่อเราสร้างและแต่ละกรณีมีของตัวเองExample
name
Python จะละเว้นแอตทริบิวต์คลาสExample.name
เมื่อใดก็ตามที่เราค้นหา.name
อินสแตนซ์เนื่องจากจะพบแอตทริบิวต์ของอินสแตนซ์ก่อน
ข้อแม้สุดท้าย: การดัดแปลง (การกลายพันธุ์) และการมอบหมายงานเป็นสิ่งที่แตกต่างกัน!
ใน Python สตริงไม่เปลี่ยนรูป ไม่สามารถแก้ไขได้ เมื่อคุณทำ:
a = 'hi '
b = a
a += 'mom'
คุณไม่ได้เปลี่ยนสตริง 'hi' ดั้งเดิม เป็นไปไม่ได้ใน Python แต่คุณสร้างสตริงใหม่'hi mom'
และทำให้a
หยุดเป็นชื่อสำหรับ'hi '
และเริ่มเป็นชื่อ'hi mom'
แทน เราb
ตั้งชื่อให้'hi '
เช่นกันและหลังจากใช้a
ชื่อซ้ำแล้วb
ก็ยังคงเป็นชื่อ'hi '
เพราะ'hi '
ยังคงมีอยู่และไม่มีการเปลี่ยนแปลง
แต่รายการสามารถเปลี่ยนแปลงได้:
a = [1, 2, 3]
b = a
a += [4]
ตอนนี้b
คือ [1, 2, 3, 4] เช่นกันเพราะเราb
ตั้งชื่อให้กับสิ่งเดียวกันที่a
ตั้งชื่อแล้วเราก็เปลี่ยนสิ่งนั้น เราไม่ได้สร้างรายการใหม่a
เพื่อตั้งชื่อเนื่องจาก Python ปฏิบัติ+=
แตกต่างกันไปสำหรับรายการ
สิ่งนี้มีความสำคัญสำหรับออบเจ็กต์เนื่องจากหากคุณมีรายการเป็นแอตทริบิวต์คลาสและใช้อินสแตนซ์เพื่อแก้ไขรายการการเปลี่ยนแปลงจะ "เห็น" ในอินสแตนซ์อื่น ๆ ทั้งหมด เนื่องจาก (ก) ข้อมูลเป็นส่วนหนึ่งของคลาสอ็อบเจ็กต์ไม่ใช่อ็อบเจ็กต์อินสแตนซ์ใด ๆ (b) เนื่องจากคุณกำลังแก้ไขรายการและไม่ได้ทำการมอบหมายอย่างง่ายคุณจึงไม่ได้สร้างแอตทริบิวต์อินสแตนซ์ใหม่โดยซ่อนแอตทริบิวต์คลาส