refactor to use Python yield and objects