Я люблю лайнеры Python One:
u = payload.get("actor", {}).get("username", "")
Проблема, с которой я сталкиваюсь, заключается в том, что я не контролирую, что содержит «полезная нагрузка», кроме того, что знаю, что это словарь. Таким образом, если в «полезной нагрузке» нет «субъекта» или он есть, а у «актера» есть или нет «имя пользователя», этот однострочник подходит.
Проблема, конечно, возникает, когда у полезного груза есть актер, но актер не является словарем.
Есть ли такой прекрасный способ сделать это всесторонне, как один вкладыш, и рассмотреть возможность того, что «актер» может не быть словарем?
Конечно, я могу проверить тип, используя 'isinstance', но это не так хорошо.
Я не требую одного вкладыша как такового, просто требую наиболее эффективного способа обеспечения того, чтобы 'u' заполнялось без исключения и без предварительного знания того, что именно находится в 'полезной нагрузке'.
4 ответа
Использование EAFP
Как предполагает xnx, вы можете воспользоваться следующей парадигмой Python:
Вы также можете использовать его на KeyError
:
try:
u = payload["actor"]["username"]
except (AttributeError, KeyError):
u = ""
Использование обертки с прощающей индексацией
Иногда было бы неплохо иметь что-то вроде нулевых условных операторов в Python. С помощью некоторого вспомогательного класса это можно сжать в однострочное выражение:
class Forgive:
def __init__(self, value = None):
self.value = value
def __getitem__(self, name):
if self.value is None:
return Forgive()
try:
return Forgive(self.value.__getitem__(name))
except (KeyError, AttributeError):
return Forgive()
def get(self, default = None):
return default if self.value is None else self.value
data = {'actor':{'username': 'Joe'}}
print(Forgive(data)['actor']['username'].get('default1'))
print(Forgive(data)['actor']['address'].get('default2'))
Ps: кроме __getitem__
можно также переопределить __getattr__
, так что вы даже можете написать Forgive(data)['actor'].username.get('default1')
.
Hege_hegedus дал правильный ответ, однако есть одно предостережение в том, что обработка исключений намного медленнее, чем выполнение оператора if..else.
Например, если вы перебираете более тысячи payload
объектов, и запись об актере лишь иногда не является словарем, этот код является абсолютно допустимым.
Однако, если вы перебираете более тысячи payload
объектов, а каждая другая запись actor
не является словарем, вам лучше использовать этот код.
u = ''
if 'actor' in payload and isinstance(payload['actor'], dict):
u = payload['actor'].get('username', '')
Для получения дополнительной информации перейдите сюда - https://mail.python.org/ pipermail / Репетитор / 2011 - январь / 081143.html
ОБНОВИТЬ
Также оператор кода может быть переписан как однострочный, хотя и не так легко читаемый, как двухстрочный
u = payload['actor'].get('username', '') if 'actor' in payload and isinstance(payload['actor'], dict) else ''
Почему бы не использовать исключение:
try:
u = payload.get("actor", {}).get("username", "")
except AttributeError:
u = ""
Если вам действительно нужно сделать это в 1 строку, вам придется реализовать функциональность самостоятельно. Что стоит делать, если вы много раз используете эту семантику в своей программе.
Есть два способа сделать это: функция или пользовательский словарь-подобный объект для payload
.
1) Функция обрабатывает случай, когда actor
не является dict
. Он может проверить isinstance
или выполнить try
или что-то еще - это не обязательно. Использование будет выглядеть примерно так: u = get("username", "", payload.get("actor", {}))
или u = get("", payload, 'actor', 'username')
(с произвольным количеством вложенных вызовов элементов в payload
).
2) Класс пользовательских объектов - мощная вещь - делайте это, если вам действительно нужна эта абстракция в программе. Потомок dict
или UserDict
(в Python3) может проверить, что он хранит или выводит при вызовах __getitem__
.
Похожие вопросы
Новые вопросы
python
Python - это многопарадигмальный, динамически типизированный, многоцелевой язык программирования. Он разработан для быстрого изучения, понимания и использования, а также для обеспечения чистого и единообразного синтаксиса. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Тем не менее, для вопросов о Python, связанных с версией, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas и NumPy) включите его в теги.