Подтвердить что ты не робот

Обозначение точки стиля Javascript для словарных клавиш unpythonic?

Я начал использовать такие конструкции:

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']. Обратите внимание, что доступ к ключу undefined возвращает None вместо создания исключения, что тоже приятно.

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

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

CMD = AutoEnum()

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

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

Это действительно плохие конструкции?

4b9b3361

Ответ 1

Это более простая версия вашего класса 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
>>> 

Ответ 2

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

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

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

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

Ответ 3

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

class Container(object):
    pass

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

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

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

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

Right?

Ответ 4

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

Ответ 5

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

  • Доступ к точкам не может использовать ключевые слова в качестве ключей.
  • Доступ к Dot должен использовать допустимые символы Python-identifier в ключах.
  • Словари могут содержать любой хешируемый элемент, а не только строки.

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

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

Ответ 6

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

Ответ 7

Там есть симметрия между этим и этим:

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

Тот же интерфейс, просто реализованный по-другому...

class container(object):
    __getitem__ = object.__getattribute__
    __setitem__ = object.__setattr__
    __delitem__ = object.__delattr__

Ответ 8

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

Ответ 9

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

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

Ответ 10

Не забывайте Bunch.

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

Ответ 11

Потому что вы просите о нежелательных побочных эффектах:

Недостаток заключается в том, что в визуальных редакторах, таких как eclipse + pyDev, вы увидите много переменных ошибки w90 для строк с использованием точечной нотации. Pydef не сможет найти такие определения "объекта" времени выполнения. Если в случае нормального словаря он знает, что вы просто получаете запись в словаре.

Вам нужно будет: 1) игнорировать эти ошибки и жить с красными крестами; 2) подавить эти предупреждения в строке за строкой, используя # @UndefinedVariable или 3) полностью отключить ошибку переменной undefined, в результате чего вы пропустите настоящие определения переменных undefined.