Получить доступ к атрибутам класса - PullRequest
0 голосов
/ 21 сентября 2018
import yaml

class Import_Yaml_Setting():
    def __init__(self, path):
        self.read_yaml(path)

    def read_yaml(self, path):
        stream = open(path, 'r')
        self.settings = yaml.load(stream)
        stream.close()


class MasterDef(Import_Yaml_Setting):
    def __init__(self, path):
        Import_Yaml_Setting.__init__(self, path)


def function_1():
    path = 'path_to_settings\\yaml_file.yaml'

    MasterDef(path)


def function_2():
    MasterDef.settings


if __name__ == '__main__':
    function_1()
    function_2()

Мой план - иметь класс Import_Yaml_Setting, который импортирует настройки из файла yaml.Класс MasterDef наследует класс Import_Yaml_Setting.После 'function_1' вызывает MasterDef для импорта настроек.Я хочу сделать это один раз в моей программе.После этого я просто хочу получить доступ к импортированным настройкам, не импортируя их снова.Это должно сделать function_2.

Моя проблема

Я не знаю, как мне сначала позвонить MasterDef.Если бы я создал экземпляр MasterDef из них, у меня не было бы доступа к этому экземпляру в function_2.

Кроме того, я получаю ошибку, в которой говорится, что MasterDef не имеет атрибута settings.

Как правильно это сделать.

1 Ответ

0 голосов
/ 21 сентября 2018

Есть несколько неправильных вещей, поэтому давайте начнем с самого очевидного.

Если у вас есть класс MasterDef, вызов MasterDef() создает экземпляр этого класса.Если вы не назначите это переменной, этот экземпляр немедленно исчезнет.

Выполнение MasterDef.settings в дальнейшем может сработать, если у класса есть атрибут класса или метод с именем settings, но в этом случае вы не обращаетесь к атрибуту settings в экземпляре.

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

from __future__ import print_function, absolute_import, division, unicode_literals


class MasterDef(object):
   def __init__(self):
       self.settings = dict(some='setting')

master_def = None

def function_1():
    global master_def
    if master_def is None:
        master_def = MasterDef()

def function_2():
    print('master_def:', master_def.settings)

if __name__ == '__main__':
    function_1()
    function_2()

, что дает:

master_def: {'some': 'setting'}

Несколько замечаний к вышесказанному:

  • Если по какой-либо причине выделая что-то новое на Python 2.7, сделайте вещи более совместимыми с Python3, включив импорт from __future__, как указано.Даже если вы просто используете функцию print (вместо устаревшего оператора print).Это упростит переход (2.7 в EOL в 2020 году)
  • Опять в 2.7 ваш базовый класс становится подклассом object, что позволяет, например, иметь свойства.
  • Путем проверки этогоmaster_def is None Вы можете вызывать function_1 несколько раз

Вы также должны знать, что PyYAML load, как написано в его документации, может быть небезопасным, когда выне иметь полного контроля над вашим входом.Редко нужно использовать load(), поэтому используйте safe_load() или обновите мой пакет ruamel.yaml, который реализует более новый стандарт YAML 1.2 (выпущенный в 2009 году, поэтому нет оправдания использованию PyYAML, который до сих пор не поддерживает это).

Поскольку вы также, похоже, работаете в Windows (предполагается, что вы используете \\), рассмотрите возможность использования необработанных строк, где вам не нужно экранировать обратную косую черту, используя os.path.join().Я опускаю вашу часть пути в моем полном примере, так как я не на Windows:

from __future__ import print_function, absolute_import, division, unicode_literals

import ruamel.yaml

class Import_Yaml_Setting(object):
    def __init__(self, path):
        self._path = path  # stored in case you want to write out the configuration 
        self.settings = self.read_yaml(path)

    def read_yaml(self, path):
        yaml = ruamel.yaml.YAML(typ='safe')
        with open(path, 'r') as stream:
            return yaml.load(stream)

class MasterDef(Import_Yaml_Setting):
    def __init__(self, path):
        Import_Yaml_Setting.__init__(self, path)


master_def = None

def function_1():
    global master_def
    path = 'yaml_file.yaml'
    if master_def is None:
        master_def = MasterDef(path)

def function_2():
    print('master_def:', master_def.settings)


if __name__ == '__main__':
    function_1()
    function_2()

Если ваш файл YAML выглядит следующим образом:

example: file
very: simple

, вывод вышеуказанной программы будетбыть:

master_def: {'example': 'file', 'very': 'simple'}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...