ประการแรกA.__dict__.__dict__
แตกต่างจากA.__dict__['__dict__']
อดีตไม่มีอยู่จริง ส่วนหลังเป็น__dict__
แอตทริบิวต์ที่อินสแตนซ์ของคลาสจะมี เป็นวัตถุอธิบายที่ส่งคืนพจนานุกรมภายในของแอตทริบิวต์สำหรับอินสแตนซ์เฉพาะ ในระยะสั้น__dict__
แอตทริบิวต์ของวัตถุไม่สามารถเก็บไว้ในวัตถุได้__dict__
ดังนั้นจึงเข้าถึงได้โดยใช้ descriptor ที่กำหนดไว้ในคลาส
เพื่อทำความเข้าใจนี้คุณจะต้องอ่านเอกสารของโปรโตคอลอธิบาย
เวอร์ชันสั้น:
- สำหรับตัวอย่างของคลาส
A
การเข้าถึงinstance.__dict__
ให้บริการโดยซึ่งเป็นเช่นเดียวกับA.__dict__['__dict__']
vars(A)['__dict__']
- สำหรับคลาส A, การเข้าถึงการ
A.__dict__
ให้บริการโดยtype.__dict__['__dict__']
(ในทางทฤษฎี) vars(type)['__dict__']
ซึ่งเป็นเช่นเดียวกับ
เวอร์ชันยาว:
ทั้งการเรียนและวัตถุให้เข้าถึงคุณลักษณะทั้งสองผ่านผู้ประกอบการแอตทริบิวต์ (ดำเนินการผ่านชั้นเรียนหรือ metaclass ฯ__getattribute__
) และ__dict__
แอตทริบิวต์ / vars(ob)
โปรโตคอลซึ่งถูกใช้โดย
สำหรับอ็อบเจ็กต์ปกติ__dict__
อ็อบเจ็กต์จะสร้างอ็อบเจ็กต์แยกต่างหากdict
ซึ่งเก็บแอ็ตทริบิวต์และ__getattribute__
ก่อนอื่นจะพยายามเข้าถึงและรับแอ็ตทริบิวต์จากที่นั่น (ก่อนที่จะพยายามค้นหาแอ็ตทริบิวต์ในคลาสโดยใช้โปรโตคอล descriptor และก่อนที่จะเรียก__getattr__
) ตัว__dict__
อธิบายในชั้นเรียนใช้การเข้าถึงพจนานุกรมนี้
x.name
เทียบเท่ากับการพยายามที่ผู้ที่อยู่ในการสั่งซื้อ: x.__dict__['name']
, type(x).name.__get__(x, type(x))
,type(x).name
x.__dict__
ทำเช่นเดียวกัน แต่ข้ามอันแรกด้วยเหตุผลที่ชัดเจน
เนื่องจากเป็นไปไม่ได้ที่__dict__
ของinstance
จะถูกเก็บไว้ใน__dict__
อินสแตนซ์จึงถูกเข้าถึงผ่านโปรโตคอล descriptor โดยตรงแทนและจะถูกเก็บไว้ในฟิลด์พิเศษในอินสแตนซ์
สถานการณ์ที่คล้ายกันนี้เป็นจริงสำหรับคลาสแม้ว่า__dict__
จะเป็นวัตถุพร็อกซีพิเศษที่แสร้งทำเป็นพจนานุกรม (แต่อาจไม่ใช่ภายใน) และไม่อนุญาตให้คุณเปลี่ยนหรือแทนที่ด้วยอันอื่น พร็อกซีนี้อนุญาตให้คุณเข้าถึงแอตทริบิวต์ของคลาสที่เฉพาะเจาะจงและไม่ได้กำหนดไว้ในฐานใดฐานหนึ่ง
ตามค่าเริ่มต้นvars(cls)
คลาสว่างจะมีตัวบ่งชี้สามตัว - __dict__
สำหรับการจัดเก็บแอ็ตทริบิวต์ของอินสแตนซ์__weakref__
ซึ่งใช้โดยภายในweakref
และ docstring ของคลาส __slots__
สองคนแรกอาจจะหายไปถ้าคุณกำหนด จากนั้นคุณจะไม่มี__dict__
และ__weakref__
แอตทริบิวต์ แต่คุณจะมีแอตทริบิวต์คลาสเดียวสำหรับแต่ละช่องแทน จากนั้นแอตทริบิวต์ของอินสแตนซ์จะไม่ถูกเก็บไว้ในพจนานุกรมและการเข้าถึงจะถูกจัดเตรียมโดยตัวอธิบายตามลำดับในคลาส
และประการสุดท้ายความไม่ลงรอยกันที่A.__dict__
แตกต่างจากA.__dict__['__dict__']
แอตทริบิวต์__dict__
คือโดยข้อยกเว้นไม่เคยมองหาvars(A)
ดังนั้นสิ่งที่เป็นจริงจึงไม่เป็นความจริงสำหรับแอตทริบิวต์อื่น ๆ ที่คุณใช้ ยกตัวอย่างเช่นเป็นสิ่งเดียวกับA.__weakref__
A.__dict__['__weakref__']
หากไม่มีความไม่สอดคล้องกันนี้การใช้A.__dict__
จะไม่ได้ผลและคุณต้องใช้vars(A)
แทนเสมอ
ive
ตัวแปรตัวอย่างเหมาะสมมากขึ้นจะได้รับ อย่างน้อยมันก็จะทำให้A.__dict__['ive']
คำถามนี้มีมากขึ้น) ฉันจะเห็นตัวเอง