Уведомления

Группа в Telegram: @pythonsu

#1 Дек. 16, 2019 16:55:16

KlauGreph
Зарегистрирован: 2019-12-16
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Помогите, не понимаю как это происходит!

Добрый вечер/день/etc., на данный момент осваиваю асинхронность, в одном видеокурсе объясняется асинхронность на генераторах и в нем объявляен следующий пример для асинхронной работы с сокетами:

 import socket
from select import select
tasks = []
to_read = {}
to_write = {}
def server():
    serv_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    serv_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    serv_socket.bind(('localhost', 5000))
    serv_socket.listen()
    while True:
        yield ('read', serv_socket)
        client_socket, addr = serv_socket.accept()
        tasks.append(client(client_socket))
def client(client_socket):
    while True:
        yield ('read', client_socket)
        request = client_socket.recv(4096)
        if not request:
            break
        else:
            yield ('write', client_socket)
            client_socket.send('Request from the serv_socket..\n'.encode())
    client_socket.close()
def event_loop():
    while any([tasks, to_read, to_write]):
        while not tasks:
            ready_to_read, ready_to_write, _ = select(to_read, to_write, [])
            for sock in ready_to_read:
                tasks.append(to_read.pop(sock))
            for sock in ready_to_write:
                tasks.append(to_write.pop(sock))
        try:
            task = tasks.pop(0)
            reason, sock = next(task)
            if reason == 'read':
                to_read[sock] = task
            if reason == 'write':
                to_write[sock] = task
        except StopIteration:
            pass
tasks.append(server())
event_loop()
Так вот, я не понимаю, каким образом в этом коде идет обращение к генераторной функции и соотв. проход кода до следующего йилда?

Отредактировано KlauGreph (Дек. 16, 2019 17:02:44)

Офлайн

#2 Дек. 16, 2019 17:16:27

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Помогите, не понимаю как это происходит!

KlauGreph
как работает генератор вы понимаете?



Офлайн

#3 Дек. 16, 2019 17:29:00

KlauGreph
Зарегистрирован: 2019-12-16
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Помогите, не понимаю как это происходит!

FishHook
KlauGrephкак работает генератор вы понимаете?

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

Отредактировано KlauGreph (Дек. 16, 2019 17:46:03)

Офлайн

#4 Дек. 16, 2019 17:46:10

KlauGreph
Зарегистрирован: 2019-12-16
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Помогите, не понимаю как это происходит!

FishHook
KlauGrephкак работает генератор вы понимаете?

 def do_iter():
    i = 50
    while i > 0:
        a = 1
        b = a-i
        i += -1
        yield b

Условный список наполняется элементами во время единоразового вызова функции или каждый элемент добавляется при вызове следующего объекта генератора?
 obj_iter = do_iter()
next(obj_iter)

Отредактировано KlauGreph (Дек. 16, 2019 18:02:24)

Офлайн

#5 Дек. 16, 2019 17:58:03

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Помогите, не понимаю как это происходит!

KlauGreph
В данном случае, при вызове функции создается список со всеми элементами до завершения цикла или же они создаются при каждом последующем обращении к объекту генератора?

Да никакой список не создаётся. Генератор - это функция, которая запоминает внутренне состояние между вызовами. Это не имеет отношения ни к спискам, ни к итерируемым объектам. Генераторы можно использовать, для создания объектов, по которым можно ходить циклом, но суть их не в этом.
Сначала вы создаете объект генератор. Все локальные переменные функции становятся атрибутами этого объекта, таким образом он хранит состояние.
 obj_iter = do_iter()
Затем вы вызываете next.
Генератор работает, пока не встретит yield и сохраняет точку кода в которой это произошло. Потом происходит возврат из функции. А на следующем вызове next генератор начинает работу с сохраненного на предудущем этапе места.



Офлайн

#6 Дек. 16, 2019 18:46:36

KlauGreph
Зарегистрирован: 2019-12-16
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Помогите, не понимаю как это происходит!

FishHook
Спасибо большое, понемногу приходит понимание.

Офлайн

#7 Дек. 16, 2019 22:03:36

KlauGreph
Зарегистрирован: 2019-12-16
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Помогите, не понимаю как это происходит!

FishHook
Спасибо огромное, понял, почему это работает - в словари и списки сохраняются состояния, к которым потом обращается пайтон, как бы прокручивая дальше выполнение функции, и скрипт записывает новое состояние в словарь, понял как то вот так. Список tasks тут получается как бы буффером очереди состояний.

Отредактировано KlauGreph (Дек. 16, 2019 22:05:12)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version