пытаясь вернуть дикт, вместо этого не получить - PullRequest
0 голосов
/ 15 марта 2020

Я пытаюсь создать программу python, которая автоматически генерирует файлы классов с учетом ввода в указанном формате c. Чтобы упростить хранение и анализ данных, я определил класс Class_Dict, который содержит спецификации для одного класса. при вводе данные выглядят следующим образом:

class name : attr1, attr2, attr3 : method1, method 2

, и машина понимает их как:

{"class_name" : ['attr1,attr2,attr3', 'method1,method2']}

Примечание. Я называю объект "Class_Dict", но его более справедливо назвать пара ключ-значение. Я хочу подчеркнуть, что объект dict класса следует отличать от контейнера (также словаря), который может содержать множество пар ключ-значение, каждая из которых задает новый класс, который должен быть сгенерирован.

Итак, чтобы разобраться с наследованием, я определил синтаксис для его представления и функцию, которая анализирует входной формат и создает объекты class_dict. По сути, он проходит по каждой паре ключ-значение в словаре class_container, и если в нем есть «>» (обозначает родительское дочернее отношение), то он вызывает функцию наследования для этой записи. Функция наследования принимает запись, которая детализирует иерархию наследования и создает соответствующие классы. например, если у нас есть:

classA, classB > classC : A1, A2 / B1, B2 > C1, C2, C3 : Amethod1 / Bmethod1 > Cmethod2

, то classA и classB являются родителями класса C, поэтому в машине:

{"classA, classB > classC" : "A1, A2 / B1, B2 > C1, C2, C3","Amethod / Bmethod > Cmethod"}

становится:

{ClassA : [A1, A2],[Amethod], ClassB : [B1, B2],[Bmethod], ClassC(ClassA, ClassB) : [C1, C2, C3], [Cmethod]}

По крайней мере, это то, что я пытаюсь сделать. У меня есть некоторые проблемы с дизайном, которые мешают мне реализовать это простым способом. То есть Class_Dict (объект, инкапсулирующий спецификации для одного класса) не повторяется, поэтому, как только я выполню преобразование применения правил наследования, я не могу просто сделать

#psuedocode
del class_container[old entry]
class_container.update(new_entry) #because new_entry is a type Class_Dict, not an iterable

, и я не могу найти способ сделать Class_Dict Iterable, потому что это одна вещь. Я полагаю, что я мог бы вставить его в итеративный метод, предоставив ему методы iter и next , не реализовав для них значимой функциональности.

Есть и вторая проблема, что означает, что вы не можете изменить размер словаря во время его циклического перемещения (необходимо l oop, чтобы определить, на каких записях запускать функцию-наследник). Для реализации это означает, что у меня должен быть отдельный словарь внутри функции наследования, который содержит вновь сгенерированные class_dicts, затем возвращает его и обновляет class_container возвращаемым значением. У меня проблема в том, что мой код выдает действительные результаты в функции наследования (с типом dict), затем я возвращаю эти результаты и получаю None / Nonetype. Я предполагаю, что это потому, что я обновляю "new" (local dict) с помощью Class_Dict (a, b, c). repr (), и это фактически не создает объект в памяти, необходимой для его храниться в структуре данных времени выполнения (я не знаю много о реализации python, просто делаю снимок)

код:

class_container = {}

def from_file(f):
    """
builds a container out of text file
containing class dict specifications.
    """    
    #need to account for lack of .txt in POSIX systems
    with open("{}.txt".format(f), "r") as file:
        for lines in file:
            #if line format OK:
            class_container.update(Class_Dict.to_dict(lines.strip("\n")))
            #else:
            ###throw an error cuz no bueno


def inheritance(name, attr, methods, new = {}):
    family, family_attr, family_methods = name.split(">"), attr.split(">"), methods.split(">")
    #error checking: does the numbers of ops match up. can not proceed if no.
    parents, parent_attr, parent_methods = family[0].split(","), family_attr[0].split("/"), family_methods[0].split("/")
    for a, b, c in zip(parents, parent_attr, parent_methods):
        new.update(Class_Dict(a,b,c).__repr__())
    del family[0], family_attr[0], family_methods[0]
    name, attr, methods = ">".join(family), ">".join(family_attr), ">".join(family_methods)
    if len(family) > 0:
        inheritance(name, attr, methods)
    else:
        return(new)


from_file("classes")
for entries in class_container:
    if entries.count(">") > 0:
        class_container.update(inheritance(entries, class_container[entries][0], class_container[entries][1]))
        #del class_container[entries]
        #class_container.extend(new)

1 Ответ

0 голосов
/ 19 марта 2020

Поэтому моя проблема заключалась в том, что тело моего базового случая:

if len(family) > 0:
   inheritance(name, attr, methods)

не возвращало значение. Просто изменив это, это решило проблему.

if len(family) > 0:it 
   return inheritance(name, attr, methods)

Мне интересно, почему это решает проблему. Это кажется довольно парадоксальным - тот факт, что None был возвращен ранее, будет означать, что случай else никогда не запускается, но это необходимо для того, чтобы функция возвращала желаемое значение. Как создание базового случая, возвращающего рекурсивный вызов, изменило эту ситуацию?

...