Несколько классов объектов "цепочки"? - PullRequest
0 голосов
/ 23 декабря 2019

Я новичок в Python и имею опыт работы в VBA. Я хочу создать классы в Python таким образом, чтобы я мог получить следующий синтаксис:

Company('MS').Department('Finance').Employee('John').FullName = 'John MacDonalds'
Company('MS').Department('Finance').Employee('John').Wages = '5000'

Я начинаю понимать, что объявление структуры классов в Python сильно отличается от VBA.

AmЯ на правильном подходе? Если нет, будет ли какой-либо другой рекомендуемый подход для этой структуры Parent / Child?

Ответы [ 2 ]

0 голосов
/ 23 декабря 2019

Вы на самом деле не сказали, какой синтаксис должен выполняться, что было бы полезно знать ...

Вложенные классы, как показано ниже, позволят вам достичь желаемого синтаксиса, норезультат не только очень «не пифоничен» - он также совершенно бесполезен, и я не могу придумать разумный способ реализовать это, чтобы изменить это.

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

Обратите внимание, что я изменил имена, которым вы должны были следовать в соответствии с соглашениями о присвоении имен PEP 8 .

class Company:
    def __init__(self, name):
        self.name = name

    class Department:
        def __init__(self, dept_name):
            self.dept_name = dept_name

        class Employee:
            def __init__(self, given_name):
                self.given_name = given_name


Company('MS').Department('Finance').Employee('John').full_name = 'John MacDonalds'

Вот способ реализовать древовидную структуру через "автовивификацию" Python, используя словарь Vividict, определенный в этом ответе .

Я адаптировал егоподдерживать разные Vividict подклассы на каждом уровне иерархии: то есть Company, Department и Employee. Каждый подкласс определяет атрибут класса с именем subtype, который базовый класс Vividict будет использовать __missing__() при создании пропущенных значений ключа. Я также добавил __repr__() метод к каждому из них, чтобы экземпляр печатал все содержащиеся в нем элементы.

Это всего лишь подтверждение концепции, и я действительно не знаю, можете ли вы использовать его или нет, но он должен дать вам хорошее представление об одном способе выполнения того, что вы хотите, с довольно читаемым синтаксисом.

class Vividict(dict):  # Base class.
    subtype = dict
    def __missing__(self, key):
        value = self[key] = self.subtype(key)
        return value

class Employee:  # Leaf - Regular class
    def __init__(self, given_name):
        self.given_name = given_name
    def __repr__(self):
        return f'{self.__class__.__name__}({self.given_name!r})'

class Department(Vividict):  # Branch.
    subtype = Employee
    def __init__(self, dept_name):
        self.dept_name = dept_name
    def __repr__(self):
        return (f'{self.__class__.__name__}({self.dept_name!r})' + '\n    '
                + repr(list(self.values())))

class Company(Vividict):  # Root of tree.
    subtype = Department
    def __init__(self, co_name):
        self.co_name = co_name
    def __repr__(self):
        return (f'{self.__class__.__name__}({self.co_name!r})' + '\n  '
                + repr(list(self.values())))

company = Company('MS')
company['Finance']['George'].full_name = 'George Brown'
company['Finance']['Mary'].full_name = 'Mary Jones'
print(company)

Вывод:

Company('MS')
  [Department('Finance')
    [Employee('George'), Employee('Mary')]]
0 голосов
/ 23 декабря 2019

Я действительно не думаю, что это хорошее использование наследования. Хорошее наследование - это когда дочерний класс можно легко заменить на родительский класс без каких-либо трудностей. Подходит ли сотрудник для отдела? Это не кажется правильным. Разве департамент не сможет сделать кучу вещей, которые не мог бы сделать сотрудник? Для каждой функции, имеющейся у вас в отделе, которую сотрудник не может выполнить, вы должны будете иметь «выбрасывать новое, не реализованное» в дочернем классе.

Это известно как принцип замещения Лискова. В основном подклассы должны быть заменяемыми для их базовых классов. Мой любимый пример с птицами и пингвинами. Вы могли бы сделать урок птицы и иметь много разных видов птиц, унаследованных от этого класса. Но что происходит, когда вы создаете класс пингвинов, унаследованный от птицы? Пингвины не могут летать, а птицы могут. Таким образом, в классе пингвинов вы реализуете эту функцию и должны будете сказать «выбросить новое, не реализовано». Это нехорошо, потому что если вы поместите пингвина в то место, где функция ожидает птицу, он взбесится и рухнет, когда вы дадите ей пингвина.

Надеюсь, это поможет. Я не слишком хорошо знаком с Python, но понимаю наследование.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...