วิธี__getattribute__
การใช้คืออะไร?
เรียกว่าก่อนการค้นหาแบบจุดปกติ ถ้ามันขึ้นAttributeError
เราก็โทร__getattr__
.
การใช้วิธีนี้ค่อนข้างหายาก มีเพียงสองคำจำกัดความในไลบรารีมาตรฐาน:
$ grep -Erl "def __getattribute__\(self" cpython/Lib | grep -v "/test/"
cpython/Lib/_threading_local.py
cpython/Lib/importlib/util.py
ปฏิบัติที่ดีที่สุด
property
วิธีที่เหมาะสมในการควบคุมการเข้าถึงโปรแกรมที่จะแอตทริบิวต์เดียวกับ D
ควรเขียนคลาสดังนี้ (โดยตัวเซ็ตเตอร์และเดเลเตอร์สามารถเลือกที่จะจำลองพฤติกรรมที่ตั้งใจไว้ได้):
class D(object):
def __init__(self):
self.test2=21
@property
def test(self):
return 0.
@test.setter
def test(self, value):
'''dummy function to avoid AttributeError on setting property'''
@test.deleter
def test(self):
'''dummy function to avoid AttributeError on deleting property'''
และการใช้งาน:
>>> o = D()
>>> o.test
0.0
>>> o.test = 'foo'
>>> o.test
0.0
>>> del o.test
>>> o.test
0.0
คุณสมบัติเป็นตัวบอกข้อมูลดังนั้นจึงเป็นสิ่งแรกที่ค้นหาในอัลกอริทึมการค้นหาแบบจุดปกติ
ตัวเลือกสำหรับ __getattribute__
คุณมีหลายทางเลือกหากคุณจำเป็นต้องใช้การค้นหาทุกแอตทริบิวต์ผ่านทาง__getattribute__
.
- เพิ่มขึ้น
AttributeError
ทำให้__getattr__
ถูกเรียก (หากมีการใช้งาน)
- คืนบางสิ่งบางอย่างจากมันโดย
- ใช้
super
เพื่อเรียกการติดตั้งพาเรนต์ (อาจจะobject
เป็น)
- โทร
__getattr__
- ใช้อัลกอริทึมการค้นหาแบบจุดของคุณเอง
ตัวอย่างเช่น:
class NoisyAttributes(object):
def __init__(self):
self.test=20
self.test2=21
def __getattribute__(self, name):
print('getting: ' + name)
try:
return super(NoisyAttributes, self).__getattribute__(name)
except AttributeError:
print('oh no, AttributeError caught and reraising')
raise
def __getattr__(self, name):
"""Called if __getattribute__ raises AttributeError"""
return 'close but no ' + name
>>> n = NoisyAttributes()
>>> nfoo = n.foo
getting: foo
oh no, AttributeError caught and reraising
>>> nfoo
'close but no foo'
>>> n.test
getting: test
20
สิ่งที่คุณต้องการในตอนแรก
และตัวอย่างนี้แสดงให้เห็นว่าคุณจะทำสิ่งที่คุณต้องการในตอนแรกได้อย่างไร:
class D(object):
def __init__(self):
self.test=20
self.test2=21
def __getattribute__(self,name):
if name=='test':
return 0.
else:
return super(D, self).__getattribute__(name)
และจะประพฤติเช่นนี้:
>>> o = D()
>>> o.test = 'foo'
>>> o.test
0.0
>>> del o.test
>>> o.test
0.0
>>> del o.test
Traceback (most recent call last):
File "<pyshell#216>", line 1, in <module>
del o.test
AttributeError: test
การตรวจสอบโค้ด
รหัสของคุณพร้อมความคิดเห็น __getattribute__
คุณมีการค้นหาประตนเองใน นี่คือสาเหตุที่คุณได้รับข้อผิดพลาดในการเรียกซ้ำ คุณสามารถตรวจสอบว่าชื่อ"__dict__"
และการใช้งานsuper
ในการแก้ปัญหา __slots__
แต่ที่ไม่ครอบคลุม ฉันจะปล่อยให้มันเป็นแบบฝึกหัดสำหรับผู้อ่าน
class D(object):
def __init__(self):
self.test=20
self.test2=21
def __getattribute__(self,name):
if name=='test':
return 0.
else:
return self.__dict__[name]
>>> print D().test
0.0
>>> print D().test2
...
RuntimeError: maximum recursion depth exceeded in cmp