Как правильно связать переменные в python

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

Контекст: назначение переменных — отслеживать некоторые свойства документа, пока я читаю его слово за словом.

Мой текущий подход состоит в том, чтобы связать их в класс:

class MarkdownIsOpen(object):
    def __init__(self):
        self.ChapterOpen = False
        self.SectionOpen = False
        self.ArticleOpen = False

Но мне это кажется немного неправильным, так как я не собираюсь добавлять какие-либо методы или другие функции.

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

Каким будет правильный (самый питонический) способ связать три переменные?

Можете ли вы привести пример вызова функции с этими переменными и что именно вы хотите сделать?

ma3oun 10.04.2019 11:24

Словарь был бы простым.

cdarke 10.04.2019 11:26

Используйте namedtuples, это, вероятно, лучше всего подходит для этого.

cglacet 10.04.2019 11:27

Мне понравился этот: stackoverflow.com/a/18792190/6198978

NoorJafri 10.04.2019 11:28
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
4
752
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

Может взглянуть на этот вопрос: Существование изменяемого именованного кортежа в Python?

С двумя хорошими ответами: рекордкласс и список имен изменяемых альтернатив именованным кортежам

Спасибо за предложения. Я выберу класс данных, потому что он из стандартной библиотеки.

Ottotos 10.04.2019 11:38
namedtuple тоже есть в стандартной библиотеке
cglacet 10.04.2019 11:44

Вы можете использовать классы данных.

@dataclass
class MarkdownIsOpen:
    ChapterOpen: bool = False
    SectionOpen: bool = False
    ArticleOpen: bool = False
Ответ принят как подходящий

Используйте класс данных:

@dataclass
class MarkdownIsOpen:
    ChapterOpen: bool = False
    SectionOpen: bool = False
    ArticleOpen: bool = False

Или:

MarkdownIsOpen = make_dataclass('MarkdownIsOpen', ['ChapterOpen', 'SectionOpen', 'ArticleOpen'])

Обратите внимание, что для этого требуется Python 3.7.

Если вы используете Python <= 3.6, то подойдет и обычный класс. Классы стоят недорого, и они дают подсказку пользователю, что ваша функция ожидает не какой-то старый dict-подобный, а контейнер особый со следующими атрибутами.

Сравните это, например, с C struct или Scala case class, которые в основном служат той же цели.

Кроме того, вы даже можете переопределить __slots__ и/или __getitem__, чтобы разрешить dict-подобный доступ и предотвратить добавление новых атрибутов:

class MarkdownIsOpen:

    __slots__ = ('ChapterOpen', 'SectionOpen', 'ArticleOpen')

    def __init__(self):
        self.ChapterOpen = False
        self.SectionOpen = False
        self.ArticleOpen = False

    def __getattr__(self, key):
        return getattr(self, key)

    def __setattr__(self, key, value):
        setattr(self, key, value)

Пример:

m = MarkdownIsOpen()
m['ChapterOpen'] = True
print(m['SectionOpen'])
m['Nonexistent'] = False

Выход:

False
AttributeError: 'MarkdownIsOpen' object has no attribute 'Nonexistent'

Я не уверен, что понимаю преимущество этого над простым namedtuple, даже ПКП меня не убеждает (если только вам не нужна статическая проверка типа, что здесь, похоже, не так). Я бы все же предложил использовать namedtuple для этого.

cglacet 10.04.2019 11:47

Если вам нравится использовать подход с классами данных, то лучше написать: MarkdownIsOpen = make_dataclass('MarkdownIsOpen', ['ChapterOpen', 'SectionOpen', 'ArticleOpen']).

intellimath 10.04.2019 12:51

@cglacet OP упомянул, что изменчивость необходима, что исключает namedtuple. На самом деле я довольно большой поклонник namedtuple, но у меня есть одна проблема с доступом с числовым индексом.

gmds 10.04.2019 14:13

Другие вопросы по теме