LINUX.ORG.RU

Python и странная структура данных


0

0

Есть большой код, который из определенных данных создает дерево, хранящееся в словарях (dict). Доступ к элементам осуществляется так value = tree['node1']['node2'].

Возникла необходимость прицепить к каждому узлу еще одно значение (смещение от начала потока, но это не важно). Эта информация никому не нужна внутри строилки дерева, но нужна при отображении результатов.

Соответственно хочется такой тип данных, который при обращении по имени переменной врзвращал одно значение, а при специальном обращении - другое.

Поясню :) Нужно что-то типа tuple, но они не подходят, так как внутри кода постороения дерева второго значения просто не должно быть видно. То-есть для вышеприведенного примера нужно полцчить возможность сделать примерно так offset = tree['node1']['node2'][1]. Где 1 - индекс добавленой переменной (0 - индекс самого значения).

Вот как-то так, надеюсь понятно объяснил :)

★★★★

То-есть ко втолрому значению имеют доступ его генератор и функции отрисовки. Соответственно разрешается поменять генератор и отрисовку. Остальной код должен остаться прежним.

alexru ★★★★
() автор топика

> а при специальном обращении - другое.

как вы себе это представляете с т.з. синтаксиса?

> Соответственно разрешается поменять генератор и отрисовку.

менять код, строящий дерево нельзя?

Предлагаю обработать дерево после постоения и заменить все tree['node1']['node2'] на Wrapper(tree['node1']['node2'])

phoenix ★★★★
()
Ответ на: комментарий от phoenix

> как вы себе это представляете с т.з. синтаксиса?

Я-то представлю :) Ну например tree['node1']['node2'].offset

> Предлагаю обработать дерево после постоения и заменить все tree['node1']['node2'] на Wrapper(tree['node1']['node2'])

Не совсем понял. Если после посторения, то где хранить значения смещений во время построения? И нужно двустроннее обращение, то есть tree['node1']['node2'] = val тоже должно работать.

alexru ★★★★
() автор топика
Ответ на: комментарий от alexru

Вопрос даже не в том, что tuple нельзя. Естественно можно потратить пол дня и заменить все tree['node1']['node2'] на tree['node1']['node2'][0] но читаемость кода это явно не улучшит, тем более в коде построения ничего кроме [0] не будет.

alexru ★★★★
() автор топика
Ответ на: комментарий от alexru

Сорри за флуд, tuple тут не подойдет, конечно. Они не поддерживают модификацию произвольного элемента, но массив додойдет, но не хочется ужас как.

alexru ★★★★
() автор топика
Ответ на: комментарий от alexru

> Если после посторения, то где хранить значения смещений во время построения?

эти значения появляются в момент постоения дерева? Тогда ведь функцию постоения все равно менять придется?

> И нужно двустроннее обращение, то есть tree['node1']['node2'] = val тоже должно работать.

и это ломать нельзя? Т.е. хочется полностью сохранить семантику tree['node1']['node2'] = val и val = tree['node1']['node2'], но нацепить дополнительно .offset ?

phoenix ★★★★
()
Ответ на: комментарий от phoenix

> эти значения появляются в момент постоения дерева? Тогда ведь функцию постоения все равно менять придется?

Нет функция построения есть класс - источник данных (абстракция от реального источника). У него еcть методы getInt8, getInt16 и т.д. Произвольного обращения к даным нет - только последовательно. Строилка дерева соответственно дергает эти методы.

> и это ломать нельзя?

Код строилки очень большой и пока читаемый, любые такие улучшения могут убить читаемость нафиг, чего не хочется :)

Есть идея сделать это как-то через свой класс, экземпляр которого будут возвращать get* методы. Такого раньше не делал, изучаю возможно-ли это.

alexru ★★★★
() автор топика

А не проще ли создать свой класс для dict, и в нем уже реализовать всё что нужно?

anonymous
()

Всем известно, что если после запуска твоей программы образуется странная структура данных, ее масса не будет скомпенсирована, и ОС схлопнится. Это еще Саныч говорил.

anonymous
()
Ответ на: комментарий от alexru

я видать не совсем понимаю проблемы, но что мешает быть ноде примерно такой:

McPi% cat test.py   


class Val(object):
    def __init__(self):
        self.__hash = {}
    
    def __getitem__(self, key):
        return self.__hash[key]

    def __setitem__(self, key, val):
        self.__hash[key] = val

    def set_offset(self, offset):
        self.__offset = offset

    def get_offset(self):
        return self.__offset

def main():
    v = Val()
    v['foo'] = 'bar'
    print v['foo']
    v.set_offset(42)
    print v.get_offset()

if __name__ == "__main__":
    main()
McPi% python test.py 
bar
42
McPi% 

Pi ★★★★★
()
Ответ на: комментарий от Pi

Ничего не мешает. О чем-то таком я уже и начал думать :) Спсибо за код, он подходит :)

alexru ★★★★
() автор топика
Ответ на: комментарий от Pi

Хотя нет, нужно v['foo'].set_offset(42), потому что смещение есть у каждого листа. 'foo' в данном случае лист и должен его иметь.

alexru ★★★★
() автор топика
Ответ на: комментарий от alexru

То-есть нужно, чтобы было так:

v = val(data, offset)

print v - Печатает Data

v = 5 - НЕ присваивает переменной v значение 5, а вызывает некий метод класса Val

alexru ★★★★
() автор топика
Ответ на: комментарий от Pi

Потому что способ обращения в этом случае меняется и проще тогда не делать своих классов, а использовать массив из 2-х элементов.

alexru ★★★★
() автор топика
Ответ на: комментарий от alexru

> Хотя нет

ну так тебе не готовое решение дали а proof of concept. Допили под то как тебе надо :)

true_admin ★★★★★
()
Ответ на: комментарий от alexru

странный подход... значение на ровне с офсетом загнать в проперть белее ничего не меняя (ведь тебе будет доступен весь аппарат встроенных спец методов аля __cmp__) оказалось сложнее, нежели впихивать этот весь агригат в списки и потом биться головой об индексы, пытаясь проводить какие-либо операции над элементами...

Pi ★★★★★
()
Ответ на: комментарий от Pi

Я тут подумал и решил все-таки все переписать на нормальные деревья. Так что странные структуры не нужны :)

alexru ★★★★
() автор топика

> Возникла необходимость прицепить к каждому узлу еще одно значение

симптомы говорят о том, что структура данных спроектирована не правильно. вообще, объекты, обладающие свойством "древесности" встречаются не очень часто. правильный древесный тип рекурсивен (т.е. все узлы дерева должны быть одного типа), и это редкость. гораздо чаще нужно распределять объекты по некоторой древовидной таксономии (из прямой ботанической аналогии: если нужно, чтобы ветки крепились к стволу, листья к веткам, а мухи к листьям -- то это как раз не "дерево", ведь типы объектов разные). в таких случаях от дерева требуется лишь возможность прикреплять к узлам объекты; менять тип самих узлов и создавать в них дополнительные атрибуты не нужно.

class Node:
. . left : Node
. . right : Node
. . o: Object

раскидав объекты по такому дереву получишь что-то типа: offset = tree['node1']['node2'].o.offset

Lucky ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.