Точечная нотация в стиле Javascript для словарных ключей unpythonic? - PullRequest
25 голосов
/ 22 октября 2008

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

class DictObj(object):
    def __init__(self):
        self.d = {}
    def __getattr__(self, m):
        return self.d.get(m, None)
    def __setattr__(self, m, v):
        super.__setattr__(self, m, v)

Обновление: на основе этого потока я изменил реализацию DictObj:

class dotdict(dict):
    def __getattr__(self, attr):
        return self.get(attr, None)
    __setattr__= dict.__setitem__
    __delattr__= dict.__delitem__

class AutoEnum(object):
    def __init__(self):
        self.counter = 0
        self.d = {}
    def __getattr__(self, c):
        if c not in self.d:
            self.d[c] = self.counter
            self.counter += 1        
        return self.d[c]

где DictObj - это словарь, доступ к которому можно получить с помощью точечной нотации:

d = DictObj()
d.something = 'one'

Я нахожу это более эстетичным, чем d['something']. Обратите внимание, что доступ к неопределенному ключу возвращает None вместо вызова исключения, что тоже неплохо.

Обновление: Smashery делает хорошую мысль, которую mhawke расширяет для более простого решения. Мне интересно, есть ли нежелательные побочные эффекты использования dict вместо определения нового словаря; если нет, то мне очень нравится решение Мхавке.

AutoEnum - это автоинкрементный Enum, используемый следующим образом:

CMD = AutoEnum()

cmds = {
    "peek":  CMD.PEEK,
    "look":  CMD.PEEK,
    "help":  CMD.HELP,
    "poke":  CMD.POKE,
    "modify": CMD.POKE,
}

Оба работают хорошо для меня, но я чувствую себя неуверенно по отношению к ним.

Это на самом деле плохие конструкции?

Ответы [ 11 ]

22 голосов
/ 22 октября 2008

Ваш пример DictObj на самом деле довольно распространен. Доступ к точечной нотации в объектном стиле может быть выигрышным, если вы имеете дело с «вещами, которые похожи на объекты», т.е. они имеют фиксированные имена свойств, содержащие только символы, допустимые в идентификаторах Python. Такие вещи, как строки базы данных или представления форм, могут быть с пользой сохранены в объектах такого типа, что делает код немного более читабельным без превышения ['item access'].

Реализация немного ограничена - вы не получите красивый синтаксис конструктора dict, len (), сравнений, «in», итерации или хороших повторений. Конечно, вы можете реализовать эти вещи самостоятельно, но в мире классов новых стилей вы можете получить их бесплатно, просто подклассифицируя dict:

class AttrDict(dict):
    __getattr__ = dict.__getitem__
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

Чтобы получить поведение по умолчанию к None, просто создайте подкласс класса Python 2.5 Коллекции.defaultdict вместо dict.

12 голосов
/ 22 октября 2008

Что касается DictObj, подойдет ли вам следующее? Пустой класс позволит вам произвольно добавлять или заменять вещи в объекте контейнера.

class Container(object):
    pass

>>> myContainer = Container()
>>> myContainer.spam = "in a can"
>>> myContainer.eggs = "in a shell"

Если вы не хотите бросать AttributeError, когда атрибута нет, что вы думаете о следующем? Лично я бы предпочел использовать dict для ясности или использовать предложение try / исключением.

class QuietContainer(object):
    def __getattr__(self, attribute):
        try:
            return object.__getattr__(self,attribute)
        except AttributeError:
            return None

>>> cont = QuietContainer()
>>> print cont.me
None

правый

8 голосов
/ 22 октября 2008

Это более простая версия вашего класса DictObj:

class DictObj(object):
    def __getattr__(self, attr):
        return self.__dict__.get(attr)

>>> d = DictObj()
>>> d.something = 'one'
>>> print d.something
one
>>> print d.somethingelse
None
>>> 
3 голосов
/ 25 октября 2008

Это не «неправильно», и это может быть лучше, если ваши словари в какой-то момент имеют сильную возможность превращаться в объекты, но с осторожностью относитесь к причинам, связанным с доступом к скобкам:

  1. Точка доступа не может использовать ключевые слова в качестве ключей.
  2. Точка доступа должна использовать в ключах допустимые символы Python-идентификатора.
  3. Словари могут содержать любой хешируемый элемент - не только строки.

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

В таком случае я бы по умолчанию использовал мантру «количество читабельности»: предположительно, другие программисты на Python будут читать ваш код и, вероятно, не будут ожидать, что везде будут встречаться гибриды словаря / объекта. Если это хорошее дизайнерское решение для конкретной ситуации, используйте его, но я бы не стал использовать его без необходимости.

3 голосов
/ 22 октября 2008

Насколько я знаю, классы Python используют словари для хранения своих атрибутов в любом случае (это скрыто от программиста), поэтому мне кажется, что то, что вы там сделали, эффективно эмулирует класс Python ... используя python учебный класс.

2 голосов
/ 24 июля 2012

Существует симметрия между этим и этим ответом:

class dotdict(dict):
    __getattr__= dict.__getitem__
    __setattr__= dict.__setitem__
    __delattr__= dict.__delitem__

Тот же интерфейс, только реализованный наоборот ...

class container(object):
    __getitem__ = object.__getattribute__
    __setitem__ = object.__setattr__
    __delitem__ = object.__delattr__
2 голосов
/ 25 октября 2008

Одним из основных недостатков использования чего-то вроде вашего DictObj является то, что вы либо должны ограничить допустимые ключи, либо у вас не может быть методов для вашего DictObj, таких как .keys(), .values(), .items() и т. Д.

1 голос
/ 24 октября 2014

Не забывайте Букет .

Это дочерний словарь, который может импортировать YAML или JSON или преобразовывать любой существующий словарь в пакет и наоборот. Как только "bundify" 'd, словарь получает точечные нотации без потери каких-либо других методов словаря.

1 голос
/ 22 октября 2008

Это не плохо, если это служит вашей цели. «Практичность побеждает чистоту».

Я видел такой подход в другом месте (например, в Paver ), так что это можно считать общая потребность (или желание).

1 голос
/ 22 октября 2008

Мне нравятся точечные обозначения намного лучше, чем словарные поля лично. Причина в том, что благодаря этому автозаполнение работает намного лучше.

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