Должен ли я извлечь значения из словарей Python в атрибуты объекта? - PullRequest
0 голосов
/ 13 сентября 2011

У меня есть класс Python, который инициализируется с помощью словаря настроек, например:

def __init__(self, settings):
    self._settings = settings

Словарь настроек содержит 50-100 различных параметров, которые довольно часто используются в других методах:

def MakeTea(self):
    tea = Tea()
    if self._settings['use_sugar']:
        tea.sugar_spoons = self._settings['spoons_of_sugar']
    return tea

Что я хочу знать, так это то, имеет ли смысл предварительно загружать все параметры в атрибуты экземпляра следующим образом:

def __init__(self, settings):
    self._use_sugar = settings['use_sugar']
    self._spoons_of_sugar = settings['spoons_of_sugar']

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

def MakeTea(self):
    tea = Tea()
    if self._use_sugar:
        tea.sugar_spoons = _self._spoons_of_sugar
    return tea

Теперь я довольно новичок в Python, и я работал в основном с компилируемыми языками, где он действительно прост: доступ к полям экземпляра будет намного быстрее, чем поиск значений из любой структуры на основе хеш-таблиц. Однако с интерпретацией Python и прочим я не уверен, что получу какой-либо значительный прирост производительности, потому что на данный момент я почти не знаю, как работает интерпретатор Python. Насколько я знаю, использование имени атрибута в коде может включать использование некоторых внутренних словарей идентификаторов в интерпретируемой среде, поэтому я ничего не получаю.

Итак, вопрос: есть ли существенные преимущества в производительности при извлечении значений из словаря и размещении их в атрибутах экземпляра? Есть ли другие преимущества или недостатки в этом? Что такое хорошая практика?

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

Ответы [ 2 ]

3 голосов
/ 13 сентября 2011

Вы сравниваете доступ к атрибуту (self.setting) с доступом к атрибуту (self.settings) плюс поиск по словарю (settings['setting']). Классы фактически реализованы в виде словарей, поэтому проблема сводится к двум поискам в словаре по сравнению с одним. Один поиск будет быстрее.

Более простой и быстрый способ скопировать диктат инициализации, чем в другом ответе:

class Foobar(object):
    def __init__(self, init_dict):
        self.__dict__.update(init_dict)

Однако я бы не стал этого делать в целях оптимизации. Это и преждевременная оптимизация (вы не знаете, что у вас проблемы со скоростью, или каково ваше узкое место), и микрооптимизация (создание алгоритма O (n 2 ) O (n) сделает больше разницы, чем удаление словарного поиска O (1) из исходного алгоритма).

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

Это два разумных варианта, но вы не должны выбирать один или другой по соображениям производительности. Вместо одного я, вероятно, создал бы другой объект:

class Settings(object):
    def __init__(self, init_dict):
        self.__dict__.update(init_dict)

class Foobar(object):
    def __init__(self, init_dict):
        self.settings = Settings(init_dict)

только потому, что я думаю, self.settings.setting лучше, чем self.settings['setting'], и он все еще поддерживает порядок.

Это хорошее применение для collections.namedtuple, если вы заранее знаете, как называются все настройки.

0 голосов
/ 13 сентября 2011

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

Пример:

>>> class Foobar(object):
    def __init__(self, init_dict):
        for arg in init_dict:
            self.__setattr__(arg, init_dict[arg])
>>> foo = Foobar({'foobar': 'barfoo', 'shroobniz': 'foo'})
>>> print(foo.__dict__)
{'foobar': 'barfoo', 'shroobniz': 'foo'}

Так что, если python смотрит вверх foo.__dict__ или foo._settings, на самом деле ничего не изменится.

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