Использование урожая с пониманием dict
Как надуманный пример:
myset = set(['a', 'b', 'c', 'd'])
mydict = {item: (yield ''.join([item, 's'])) for item in myset}
и list(mydict)
дает:
['as', 'cs', 'bs', 'ds', {'a': None, 'b': None, 'c': None, 'd': None}]
Что здесь происходит? Что делает yield
? И соответствует ли это поведение независимо от того, какое выражение следует за yield
?
Примечание. Я знаю, что выполнение mydict = {item: ''.join([item, 's']) for item in myset}
даст словарь {'a': 'as', 'b': 'bs', 'c': 'cs', 'd': 'ds'}
, который, кажется, я пытаюсь сделать здесь.
Ответы
Ответ 1
Прежде всего, что возвращает yield
? Ответ в этом случае None
, потому что yield
возвращает параметр, переданный в next()
, который в этом случае ничего нет (list
ничего не передает next
).
Теперь вот ваш ответ:
>>> myset = set(['a', 'b', 'c', 'd'])
>>> mydict = {item: (yield ''.join([item, 's'])) for item in myset}
>>> mydict
<generator object <dictcomp> at 0x0222BB20>
Понимание dict превращается в генератор, потому что вы использовали yield
в контексте тела функции! Это означает, что все это не оценивается до тех пор, пока оно не перейдет в list
.
Итак, что происходит:
-
list
вызывает next(mydict)
.
- Доходность возвращает
''.join([item, 's'])
до list
и замораживает понимание.
-
list
вызывает next(mydict)
.
- Понимание возобновляется и присваивает результат
yield
(None
) в item
в словаре и запускает новую итерацию понимания.
- Вернитесь к 1.
И наконец, фактический объект-генератор возвращает временное тело, которое было dict
. Почему это происходит, мне неизвестно, и это, вероятно, также не документированное поведение.
Ответ 2
Я думаю, что yield
превращает ваше замечательное понимание слова в выражение генератора. Итак, когда вы выполняете итерацию по генератору, yield "уступает" элементам, которые выглядят as
, bs
..., но оператор yield ...
возвращает None
. Итак, в конце дня вы получаете словарь, похожий на {'a': None, 'b': None, ...}
.
Часть, которая меня смущает, - это то, почему словарь действительно уступает в конце. Я предполагаю, что это поведение на самом деле не совсем определено стандартом, но я мог ошибаться в этом.
Интересно, если вы попробуете это с пониманием списка, питон жалуется:
>>> a = [(yield i) for i in myset]
File "<stdin>", line 1
SyntaxError: 'yield' outside function
Но он Хорошо в генераторе (видимо).
Ответ 3
Я нахожу! ^ _ ^
В нормальной жизни выражение
print {item: (yield ''.join([item, 's'])) for item in myset}
оцените следующее:
def d(myset):
result = {}
for item in myset:
result[item] = (''.join([item, 's']))
yield result
print d(myset).next()
Почему yield result
вместо return result
? Я думаю, что необходимо поддерживать вложенные списки * следующим образом:
print {i: f.lower() for i in nums for f in fruit} # yes, it works
Итак, будет выглядеть как этот код?
def d(myset):
result = {}
for item in myset:
result[item] = (yield ''.join([item, 's']))
yield result
и
>>> print list(d(myset))
['as', 'cs', 'bs', 'ds', {'a': None, 'b': None, 'c': None, 'd': None}]
Сначала будут возвращены все значения ''.join([item, 's'])
, и последний будет возвращен dict result
. Значение выражения yield
None
, поэтому значения в result
тоже None
.
* Более правильная интерпретация оценки вложенных списков:
print {i: f.lower() for i in nums for f in fruit}
# eval like this:
result = {}
for i, f in product(nums, fruit): # product from itertools
key, value = (i, f.lower())
result[key] = value
print result
Ответ 4
Я думаю, что ваш код должен выполнить сходство этого:
def d(myset):
for item in myset:
yield item, (yield ''.join([item, 's']))
d(myset)
Сначала оцениваем yield ''.join([item, 's']
(и возвращаем 'as', 'cs' и т.д.). Значение выражения yield равно None, потому что отправляется обратно генератору. И затем eval yield item, None
, который возвращает кортежи ('a', None), ('b', None).
Итак, у меня есть:
>>> list(d(myset))
['as', ('a', None), 'cs', ('c', None), 'bs', ('b', None), 'ds', ('d', None)]
Что будет дальше, я не понимаю.