Có rất nhiều getattr tốt() - chức năng như để phân tích cấu trúc điển lồng nhau, chẳng hạn như:Python setattr đệ quy() - chức năng như để làm việc với các từ điển lồng nhau
- Finding a key recursively in a dictionary
- Suppose I have a python dictionary , many nests
- https://gist.github.com/mittenchops/5664038
Tôi muốn tạo một setattr song song(). Về cơ bản, đưa ra:
cmd = 'f[0].a'
val = 'whatever'
x = {"a":"stuff"}
Tôi muốn tạo ra một chức năng như vậy mà tôi có thể gán:
x['f'][0]['a'] = val
Nhiều hơn hoặc ít hơn, điều này sẽ làm việc theo cách tương tự như:
setattr(x,'f[0].a',val)
để mang lại:
>>> x
{"a":"stuff","f":[{"a":"whatever"}]}
Tôi là c urrently gọi đó là setByDot()
:
setByDot(x,'f[0].a',val)
Một vấn đề với điều này là nếu một phím ở giữa không tồn tại, bạn cần phải kiểm tra và thực hiện một chính trung gian nếu nó không tồn tại --- tức là, cho ở trên:
>>> x = {"a":"stuff"}
>>> x['f'][0]['a'] = val
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'f'
vì vậy, trước tiên bạn phải thực hiện:
>>> x['f']=[{}]
>>> x
{'a': 'stuff', 'f': [{}]}
>>> x['f'][0]['a']=val
>>> x
{'a': 'stuff', 'f': [{'a': 'whatever'}]}
khác là keying cho khi mục tiếp theo là một danh sách sẽ khác so với keying khi mục tiếp theo là một chuỗi, tức là:
>>> x = {"a":"stuff"}
>>> x['f']=['']
>>> x['f'][0]['a']=val
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
... không thành công vì gán cho chuỗi rỗng thay vì một giá trị rỗng. Các dict null sẽ được chuyển nhượng quyền cho mỗi phi danh sách trong dict cho đến khi người cuối cùng --- mà có thể là một danh sách, hoặc một giá trị.
Vấn đề thứ hai, được nêu trong phần bình luận bên dưới bởi @TokenMacGuy, là khi bạn phải tạo danh sách không tồn tại, bạn có thể phải tạo ra rất nhiều giá trị trống. Vì vậy,
setattr(x,'f[10].a',val)
--- có nghĩa là thuật toán sẽ phải thực hiện một như trung gian:
>>> x['f']=[{},{},{},{},{},{},{},{},{},{},{}]
>>> x['f'][10]['a']=val
để mang
>>> x
{"a":"stuff","f":[{},{},{},{},{},{},{},{},{},{},{"a":"whatever"}]}
như rằng đây là setter gắn liền với getter ...
>>> getByDot(x,"f[10].a")
"whatever"
Thêm quan trọng, các trung gian nên/không/ghi đè các giá trị đã tồn tại.
Dưới đây là ý tưởng junky tôi có cho đến nay --- Tôi có thể xác định danh sách so với dicts và các loại dữ liệu khác và tạo chúng ở nơi chúng không tồn tại. Tuy nhiên, tôi không thấy (a) nơi đặt cuộc gọi đệ quy, hoặc (b) cách 'xây dựng' đối tượng sâu khi tôi lặp qua danh sách, và (c) cách phân biệt/thăm dò/tôi làm như tôi xây dựng các đối tượng sâu từ/thiết lập/tôi phải làm gì khi tôi đạt đến cuối của ngăn xếp.
def setByDot(obj,ref,newval):
ref = ref.replace("[",".[")
cmd = ref.split('.')
numkeys = len(cmd)
count = 0
for c in cmd:
count = count+1
while count < numkeys:
if c.find("["):
idstart = c.find("[")
numend = c.find("]")
try:
deep = obj[int(idstart+1:numend-1)]
except:
obj[int(idstart+1:numend-1)] = []
deep = obj[int(idstart+1:numend-1)]
else:
try:
deep = obj[c]
except:
if obj[c] isinstance(dict):
obj[c] = {}
else:
obj[c] = ''
deep = obj[c]
setByDot(deep,c,newval)
Điều này có vẻ rất phức tạp vì bạn cần phải kiểm tra loại/tiếp theo/đối tượng nếu bạn đang tạo địa điểm và bạn phải nhìn sau để xây dựng đường dẫn lên như bạn đi.
CẬP NHẬT
thời gian gần đây tôi đã this question trả lời, quá, mà có thể có liên quan hoặc hữu ích.
Điều này trông rất tuyệt, nhưng dường như không hiệu quả với tôi. '>>> x = {" a ":" công cụ "} >>> _setattr (x," f [0] .a "," test ") >>> x {'a': 'stuff' } ' – Mittenchops
@Mittenchops Vì lý do nào đó' build_instructions' mà tôi đã lưu khác với những gì trên SO. Tôi đã cập nhật nó nên nó sẽ hoạt động ngay bây giờ. – FastTurtle
@Mittenchops Haha, hóa ra tôi đã chuyển các đối số trong 'build_instructions' một cách tình cờ. Hãy cho tôi biết nếu vẫn còn bất kỳ vấn đề! – FastTurtle