__getattribute__
ถูกเรียกเมื่อใดก็ตามที่มีการเข้าถึงคุณลักษณะ
class Foo(object):
def __init__(self, a):
self.a = 1
def __getattribute__(self, attr):
try:
return self.__dict__[attr]
except KeyError:
return 'default'
f = Foo(1)
f.a
สิ่งนี้จะทำให้เกิดการเรียกซ้ำแบบไม่สิ้นสุด return self.__dict__[attr]
ผู้ร้ายที่นี่เป็นเส้น มาทำเป็นแกล้งกัน (มันใกล้ความจริงมากพอ) ว่ามีการเก็บแอตทริบิวต์ทั้งหมดไว้ในself.__dict__
ชื่อของพวกเขา เส้น
f.a
ความพยายามที่จะเข้าถึงแอตทริบิวต์ของa
f
สายf.__getattribute__('a')
นี้ แล้วพยายามที่จะโหลด__getattribute__
เป็นแอททริบิวต์ดังนั้น python จึงเรียกอีกครั้งว่าพยายามเข้าถึงแอททริบิว' นี่เป็นการเรียกซ้ำแบบไม่สิ้นสุดself.__dict__
__dict__
self == f
f.__getattribute__('__dict__')
'__dict__
หาก__getattr__
เคยถูกใช้มาแล้ว
- มันจะไม่ทำงานเพราะ
f
มีa
คุณสมบัติ
- ถ้ามันวิ่ง (ขอบอกว่าคุณถาม
f.b
) แล้วมันจะไม่ได้รับการเรียกตัวไปพบ__dict__
เพราะมันมีอยู่แล้วและ__getattr__
มีการเรียกใช้เฉพาะในกรณีที่วิธีการอื่น ๆ ในการหาแอตทริบิวต์ได้ล้มเหลว
วิธี 'ถูกต้อง' ในการเขียนคลาสข้างต้นโดยใช้__getattribute__
คือ
class Foo(object):
# Same __init__
def __getattribute__(self, attr):
return super(Foo, self).__getattribute__(attr)
super(Foo, self).__getattribute__(attr)
ผูก__getattribute__
เมธอดของซุปเปอร์คลาสที่ใกล้ที่สุด (อย่างเป็นทางการคลาสถัดไปในระเบียบวิธีการแก้ปัญหาของคลาสหรือ MRO) ไปยังวัตถุปัจจุบันself
จากนั้นเรียกมันและอนุญาตให้ทำงานได้
ปัญหาทั้งหมดนี้หลีกเลี่ยงได้โดยการใช้__getattr__
ซึ่งทำให้ Python ทำสิ่งนั้นเป็นเรื่องปกติจนกระทั่งไม่พบคุณลักษณะ ณ จุดนั้น Python มือควบคุม__getattr__
วิธีการของคุณและช่วยให้มันมาพร้อมกับบางสิ่งบางอย่าง
นอกจากนี้ยังเป็นที่น่าสังเกตว่าคุณสามารถใช้เป็น infinite __getattr__
เรียกซ้ำกับ
class Foo(object):
def __getattr__(self, attr):
return self.attr
ฉันจะปล่อยให้สิ่งนั้นเป็นการออกกำลังกาย