Как представить файловую структуру как объекты Python - PullRequest
0 голосов
/ 17 января 2019

Я пытаюсь найти способ представить файловую структуру в виде объектов Python, чтобы я мог легко получить конкретный путь без необходимости вводить всю строку. Это работает для моего случая, потому что у меня есть статическая файловая структура (не изменяется).

Я думал, что могу представить каталоги как класс, а файлы в каталоге как класс / статические переменные.

Я хочу иметь возможность перемещаться по объектам Python, чтобы он возвращал путь, который я хочу, т. Е.

print(FileStructure.details.file1) # root\details\file1.txt
print(FileStructure.details) # root\details

Вместо этого я получаю следующий код:

print("{0}".format(FileStructure())) # root
print("{0}".format(FileStructure)) # <class '__main__.FileStructure'>
print("{0}".format(FileStructure.details)) # <class '__main__.FileStructure.details'>
print("{0}".format(FileStructure.details.file1)) # details\file1.txt

Код, который у меня пока есть ...

import os 

class FileStructure(object): # Root directory
    root = "root"

    class details(object): # details directory
        root = "details"
        file1 = os.path.join(root, "file1.txt") # File in details directory
        file2 = os.path.join(root, "file2.txt") # File in details directory

        def __str__(self):
            return f"{self.root}"

    def __str__(self):
        return f"{self.root}"

Я не хочу создавать экземпляр класса для этой работы. Мой вопрос:

  1. Как я могу вызвать объект класса и получить вместо него строку текста
  2. Как я могу иметь вложенные классы, использующие их родительские классы?

Ответы [ 2 ]

0 голосов
/ 17 января 2019

Предварительно: это плохое решение, но оно отвечает вашим требованиям с минимальными изменениями. По сути, вам нужно, чтобы экземпляры __str__ работали, поэтому это обманывает, используя синтаксис декоратора, чтобы изменить объявление класса в одноэлементное создание объявленного класса. Поскольку невозможно неявно ссылаться на внешние классы из вложенных классов , ссылка выполняется явно. А для повторного использования __str__, file1 и file2 были превращены в @property s, чтобы они могли использовать форму str экземпляра details для создания себя.

@object.__new__
class FileStructure(object): # Root directory
    root = "root"

    @object.__new__
    class details(object): # details directory
        root = "details"
        @property
        def file1(self):
            return os.path.join(str(self), 'file1')
        @property
        def file2(self):
            return os.path.join(str(self), 'file2')

        def __str__(self):
            return f"{os.path.join(FileStructure.root, self.root)}"

    def __str__(self):
        return f"{self.root}"

Опять же: хотя это и приводит к желаемому поведению, это все же плохое решение. Я сильно подозреваю, что у вас проблема XY здесь, но это отвечает на поставленный вопрос.

0 голосов
/ 17 января 2019

Давайте начнем с: вы, вероятно, на самом деле не хотите этого. API pathlib в Python3 выглядит лучше, чем этот, и уже широко поддерживается.

root = pathlib.Path('root')
file1 = root / 'details' / 'file1'  # a Path object at that address

if file1.is_file():
    file1.unlink()
else:
    try:
        file1.rmdir()
    except OSError as e:
        # directory isn't empty

Но если вы по какой-то причине не уверены в этом, вам придется переопределить __getattr__, чтобы создать новый объект FileStructure и отслеживать родителей и детей.

class FileStructure(object):
    def __init__(self, name, parent):
        self.__name = name
        self.__children = []
        self.__parent = parent

    @property
    def parent(self):
        return self.__parent

    @property
    def children(self):
        return self.__children

    @property
    def name(self):
        return self.__name

    def __getattr__(self, attr):
        # retrieve the existing child if it exists
        fs = next((fs for fs in self.__children if fs.name == attr), None)
        if fs is not None:
            return fs

        # otherwise create a new one, append it to children, and return it.
        new_name = attr
        new_parent = self
        fs = self.__class__(new_name, new_parent)
        self.__children.append(fs)
        return fs

Затем используйте его с:

root = FileStructure("root", None)
file1 = root.details.file1

Вы можете добавить __str__ и __repr__, чтобы помочь вашим представлениям. Вы можете даже включить path свойство

# inside FileStructure
@property
def path(self):
    names = [self.name]
    cur = self
    while cur.parent is not None:
        cur = cur.parent
        names.append(cur.name)
    return '/' + '/'.join(names[::-1])

def __str__(self):
    return self.path
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...