尊敬的同事們!
請考慮...
#!/usr/bin/env python3.6
class Child(object):
def __init__(self, name:str, value = 0):
self.name = name;
self.value = value;
def __repr__(self):
return ' child "{}" has value {}\n'.format(self.name, self.value)
class Parent(object):
def __init__(self, name:str):
self.name = name
self.children = {}
def __repr__(self):
s = 'Parent "{}":\n'.format(self.name)
for k, v in self.children.items():
s = v.__repr__()
return s
def __getattr__(self, name:str):
if name == 'children':
return self.children;
elif name in self.children.keys():
return self.children[name].value
else:
return super().__getattr__(name)
def __setattr__(self, prop, val):
if prop == 'name':
super().__setattr__(prop, val)
else:
super().__setattr__('children[{}]'.format(prop), val)
p = Parent('Tango')
p.children['Alfa'] = Child('Alfa', 55)
p.children['Bravo'] = Child('Bravo', 66)
print(p)
print(p.children['Alfa']) # Returns '55' (normal)
print(p.Alfa) # Returns '55' (__getattr__)
print('-----')
p.Alfa = 99 # This is creating a new variable, need __setattr__ ...
print(p.Alfa) # Prints new variable. __setattr__ is not called!
print('-----')
print(p.children['Alfa']) # Still '55'
print(p) # Still '55'
該代碼的目的是允許持有 a 的人Parent以children兩種方式訪問它:p.children['Alfa']或p.Alfa。
使用__getattr__()I 可以完成這個的讀取端。(注釋掉def __setattr__()上面代碼中的 ,您可以看到讀取端按預期作業。)沒有setattr () 的輸出是:
Parent "Tango":
child "Alfa" has value 55
child "Bravo" has value 66
child "Alfa" has value 55
55
-----
99
-----
child "Alfa" has value 55
Parent "Tango":
child "Alfa" has value 55
child "Bravo" has value 66
當然,現在我需要__setattr__()完成這個的寫端。我希望將 99 分配給阿爾法。到現在為止,還沒有想出能避免各種問題的咒語。
上面帶有setattr ()的代碼引發了RecursionError:
Traceback (most recent call last):
File "./test.py", line 37, in <module>
p.children['Alfa'] = Child('Alfa', 55)
File "./test.py", line 23, in __getattr__
return self.children;
File "./test.py", line 23, in __getattr__
return self.children;
File "./test.py", line 23, in __getattr__
return self.children;
[Previous line repeated 328 more times]
File "./test.py", line 22, in __getattr__
if name == 'children':
RecursionError: maximum recursion depth exceeded in comparison
我希望接下來的測驗代碼表明,通過寫入p.Alfa,我實際上是在更新self.children['Alfa']. 分配后,列印時應該出現99,而不是原來的55。
請注意,在現實世界中,可能的孩子、他們的名字和他們的內容幾乎是無限的。
感謝您的幫助和洞察力!
uj5u.com熱心網友回復:
def __setattr__(self, attr, val):
if attr == 'name':
super().__setattr__(self, 'name', val)
return
self.children[attr] = val
您的代碼永遠不會初始化名為 的屬性children。它初始化一個名為children[children]. 因此,當您稍后嘗試分配給 時self.children['Alfa'],它嘗試做的第一件事就是找到一個名為 的屬性children。當沒有找到時,它呼叫__getattr__,這表示當 時name == "children",它應該回傳self.children,然后無限回圈開始。
__getattr__是僅當通過正常程序中沒有找到的屬性呼叫。有了__setattr__正確定義,__getattr__不應該要求children,因為你定義它__init__。定義可以簡化為
def __getattr__(self, name:str):
if name in self.children.keys():
return self.children[name].value
else:
return super().__getattr__(name)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/315077.html
上一篇:多次單擊按鈕時僅打開1個視窗
