Эффективный способ доступа к классу вложенных атрибутов - PullRequest
0 голосов
/ 07 июня 2018

Предположим, что у нас есть 5 классов Python X1, X2, X3, X4, X5 и следующий код:

class Schedule:
    def __init__(self):
        pass

class DateBound:
    def __init__(self):
        self.attr3 = Schedule()


class Behavior:
    def __init__(self):
        self.attr2 = DateBound()


class Host:
    def __init__(self):
        self.attr1 = Behavior()

class PeriodController:
    def __init__(self):
        self.attr0 = Host()

Теперь предположим, что функции в PeriodController необходим доступ к attr3class DateBound :

class PeriodController:
    def __init__(self):
        self.attr0 = ()

    def example_function(self):
        return self.attr0.attr1.attr2.attr3

Как мне эффективно получить доступ к attr3 в такой ситуации?Я ничего не имею против доступа к нему, как example_function () , но это не кажется правильным из-за повторения attr0.attr1 ... attrn

Вкратце,концепция этой реализации состоит в том, что Host имеет Bahavior , который определяет среди прочего, в какое время он должен быть подключен к серверу.

Класс DateBound существует, потому что иногда хост может быть подключен к серверу в другое время, отличное от его обычного поведения , но это действительно хороший хостследовательно, обычное время соединения Host не указывается с использованием экземпляра Datebound .

A DateBound имеет Расписание , которое содержит время, которое имеет экземпляр DateBound , следовательно, время Host должен быть подключен.Наконец, PeriodController контролирует, подключен ли Host в соответствии с его обычным Behavior , поэтому PeriodController необходим доступ к self.attr3 * 1051.*

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

Хотя Ajax победил меня, я работал над более изящным решением:

def examplefunction(startObject, differenceInX):
    for _ in range(differenceInX + 1):
        startObject = getattr(startObject, (any(item.startswith('attr') for item in dir(startObject))[0])
    return startObject

Это должно быть определено вне любых классов.

Использование: startObject будет экземпляромX5() в этом случае и differenceInX будет 5 - 2 = 3.

Хорошая особенность этого метода в том, что его можно использовать для любого класса без необходимости его повторного определения.Обратите внимание, что (any(item.startswith('attr') for item in dir(startObject))[0]) полагается только на один атрибут, начинающийся с 'attr' для каждого класса (в данном случае attr0/1/2/3/n).

0 голосов
/ 07 июня 2018

Вы можете использовать рекурсию:

class X5:
  def __init__(self):
    self.attr0 = X4()
  def example_function(self, count = 1):
    if count == 4:
      return self.attr0
    self.attr0 = getattr(self.attr0, f'attr{count}')
    return self.example_function(count+1)

print(X5().example_function())

Вывод:

<__main__.X1 object at 0x1012cc278>

Печать X5().attr0.attr1.attr2.attr3) достигает того же результата:

<__main__.X1 object at 0x1012cc278>

Добавление __repr__методы для каждого класса облегчают визуализацию:

class X1:
  ...
  def __repr__(self):
    return f'<{self.__class__.__name__}>'

print(X5().example_function())

Вывод:

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