Сделать заказной по умолчанию? - PullRequest
0 голосов
/ 24 ноября 2018

Можно ли сделать литерал по умолчанию буквальным для создания упорядоченных, а не неупорядоченных?

Я хотел бы напечатать сложные вложенные конфигурации, такие как:

config = {
   'train': {
       'speed': 0.001,
       'initial_values': [1, 2, 3]
   },
   'model': {
...
   }
}

и идею написатьбеспорядок скобок

config = OrderedDict([(
    'train', OrderedDict([(
       'speed', 0.001), (
       'initial_values', [1, 2, 3])]),(
    'model', OrderedDict([(
...

абсолютно неприменим.

Пожалуйста, не говорите о философии, почему мое желание плохо.


Хорошо, в настоящее время я написал бы что-то вроде:

def od(*args):
   return OrderedDict([(args[i], args[i+1]) for i in range(0, len(args), 2)])

config = od(
    'train', od(
        'speed', 0.001,
        'initial_values', [1, 2, 3]
     ),
     'model', od(
    ...
     )
)

Ответы [ 3 ]

0 голосов
/ 24 ноября 2018

Нет философской причины, почему вы не должны этого делать, но вы не можете сделать это, изменив фундаментальный синтаксис Python.Как уже упоминалось, словари Python могут сохранять порядок после 3.6, но если вы должны использовать OrderedDict

d = OrderedDict

config = d([(...)])

Вы можете сделать то же самое с методами, такими как .update

0 голосов
/ 24 ноября 2018

Хотя это не дает прямого ответа на ваш вопрос так, как вы его сформулировали, я думаю, вы действительно хотите иметь возможность обрабатывать некоторые конфиги.Я обычно предпочитаю сохранять конфиги не в файлах python, а в каком-то формате структурированных данных.Поэтому, если вы можете допустить использование json, вы можете сделать следующее:

from collections import OrderedDict
import json

result = json.loads(
'''
    {
       "train": {
           "speed": 0.001,
           "initial_values": [1, 2, 3]
       },
       "model": {
            "name": "model_name",
            "wheight" : 128000
       }
    }
''', 
object_pairs_hook=lambda pairs: OrderedDict(pairs))

Это должно работать даже в Python 2.7.

И если у вас есть выделенный файл для конфигурации, вы можете сделатьчто-то вроде

from collections import OrderedDict
import json

with open('settings.conf', 'r') as f:
    settings_str = f.read()
    settings = json.loads(settings_str, object_pairs_hook=lambda pairs: OrderedDict(pairs))
0 голосов
/ 24 ноября 2018

Нет, вы не можете изменить синтаксис Python, не изменив исходный код CPython и не перекомпилировав его, но тогда это больше не будет Python.

Лучшее, что вы можете сделать, это обновить до Python 3.6 или новее , где словари сохраняют порядок вставки по умолчанию .Если у вас должен быть полный набор функций OrderedDict (переупорядочение, реверсирование, наложение диктов с упорядочением), то преобразуйте эти обычные словари в OrderedDict объекты после факта:

from collections import OrderedDict
from functools import singledispatch

@singledispatch
def to_ordered_dict(d):
    """Convert dictionaries to OrderedDict objects, recursively

    Assumes you want to use current dictionary iteration order; in Python 3.7
    and newer that's the same as insertion order (or earlier if on PyPy, or 
    when using CPython, 3.6 and newer).

    """
    return d

@to_ordered_dict.register(dict)
def _dict(d):
    return OrderedDict(
        (to_ordered_dict(k), to_ordered_dict(v))
        for k, v in d.items()
    )

@to_ordered_dict.register(list)
@to_ordered_dict.register(tuple)
def _sequence(s):
    return type(s)(map(to_ordered_dict, s))

# add additional type registrations for other compound or container types

и затем придерживайтесь{...} обозначение с config = to_ordered_dict(config) строкой в ​​конце.

...