Найти - Пользователи
Полная версия: Аналог перлового оператора defined-or
Начало » Python для новичков » Аналог перлового оператора defined-or
1 2 3
worldmind
В Perl'е есть такой удобный оператор //, обычно он используется для задания дефолтных значений, в питоне можно для параметров функций задавать дефолтные значения, но это не подходит для сложных структур (например когда нужен дефолт для отдельных полей).
Пример того как это выглядит в перле:
 my $var = $struct{key1}{key2} // 'defaul_value';
Это значит, что если $struct{key1}{key2} не определено, то $var получит значение ‘defaul_value’, если кто не заметил, то обычный ИЛИ тут не подходит т.к. $struct{key1}{key2} может иметь значение трактуемое как ложь, а дефолт нужно применить только когда значение не определено.
Т.к. в питоне нет автовивификации то видимо такой оператор должен проверять что ключ в словаре существует и если существует то не имеет значения (is None).

Пытался погуглить, но увидел только всякие try и проверки на существования ключа с помощью in, конечно можно самому написать функцию с такой логикой, но это придётся делать только если точно узнать что в языке нет ничего удобного для этой задачи.
py.user.next
В словаре можно использовать метод get() вместо квадратных скобок, у него есть значение по умолчанию.
  
>>> {}.get('x')
>>> {}.get('x', 'no')
'no'
>>>

Если же нужно вглубь словаря спускаться, когда там чего-то может не быть, то использует отлов KeyError.
  
>>> try:
...   x = {}['a']['b']['c']
... except KeyError:
...   x = 1
... 
>>> x
1
>>>
worldmind
Да, я тут подумал что надо этот try обернуть в свой оператор и будет что-то похожее
worldmind
worldmind
Да, я тут подумал что надо этот try обернуть в свой оператор и будет что-то похожее
если это можно сделать нормальным способом
worldmind
 from infix import shift_infix as infix
@infix
def exist_or(value, default_value):
    try:
        result = value
    except KeyError:
        result = default_value
    return result

 >>> from existor import exist_or
>>> struct = {'key1': {'key2': 'aaa'}}
>>> var = struct['key1']['key2'] <<exist_or>> '7'
>>> var
'aaa'
>>> var = struct['key1']['key3'] <<exist_or>> '7'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'key3'
т.е. питон вычисляет выражение раньше
FishHook
 d = {}
x = d.get("a", {}).get("b", {}).get("c", 1)
worldmind
FishHook
Вариант конечно, мой вариант выше можно доработать
 from infix import shift_infix as infix
@infix
def exist_or(value_func, default_value):
    try:
        result = value_func()
    except KeyError:
        result = default_value
    return result
и делать так
 >>> from existor import exist_or
>>> struct = {'key1': {'key2': 'aaa'}}
>>> var = (lambda:struct['key1']['key2']) <<exist_or>> '7'
>>> var
'aaa'
>>> var = (lambda:struct['key1']['key3']) <<exist_or>> '7'
>>> var
'7'
хотя это уже не та читаемость которой хотелось бы достичь
ABKorotky
Можно посмотреть в сторону https://docs.python.org/2/library/stdtypes.html?highlight=setdefault#dict.setdefault
 >>> d = {}
>>> d
{}
>>> val = d.setdefault('key', 'value')
>>> val
'value'
>>> d
{'key': 'value'}
Также есть вот такая штука: https://docs.python.org/2/library/collections.html?highlight=defaultdict#collections.defaultdict
Может быть полезен вот для такого рода вещей:
 >>> from collections import defaultdict
>>> d = defaultdict(list)
>>> d
defaultdict(<type 'list'>, {})
>>> d['list1'].append(1)
>>> d
defaultdict(<type 'list'>, {'list1': [1]})
>>> d['list1'].append(2)
>>> d
defaultdict(<type 'list'>, {'list1': [1, 2]})
Правда, для рекурсивной инициализации не совсем подходит - придётся повозиться…
FishHook
worldmind
ну это как-то извращением попахивает, если хочется изобрести велосипед, то лучше от dict отнаследоваться.
doza_and
ABKorotky
Правда, для рекурсивной инициализации не совсем подходит

А в чем проблема?
 d = defaultdict(lambda:defaultdict(list))
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB