ประการแรก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']คำถามนี้มีมากขึ้น) ฉันจะเห็นตัวเอง