fichtefoll / resumeback Goto Github PK
View Code? Open in Web Editor NEWPython module for using callbacks to resume your code
Home Page: https://fichtefoll.github.io/resumeback/
License: MIT License
Python module for using callbacks to resume your code
Home Page: https://fichtefoll.github.io/resumeback/
License: MIT License
At first glance, I did not know what yield do in Python, but after having a hard time studying it, I finally understand the idea. But having calling
this = yield
and later passing the mysteriousthis.send
as callback, does not seem clear than right away defining some lambda or closure. However, you should ask this to a python beginning which do not know neither closures nor what yield does, because I am already used to lambdas and closures. Or perhaps I am not seeing the big picture because the example is too simple or I am too dumb, therefore in a more complex scenario this could have great advantages. Then you could add also a complex example using closures vs resumeback.
I got that linear order, however I do not see how that can easier than just use closures. My problem is against the declaration of the first this = yield
and the second yield function(this.send)
. If I look both codes:
closure
def main():
arbitrary_value = 10
def on_done(number):
number = str(number)
print("Result:", number * arbitrary_value)
ask_for_user_input("Please enter a number", on_done)
resumeback
from resumeback import send_self
@send_self
def main():
this = yield # "this" is now a reference to the just-created generator
arbitrary_value = 10
# Yield pauses execution until one of the generator methods is called,
# such as `.send`, which we provide as the callback parameter.
number = yield ask_for_user_input("Please enter a number", this.send)
number = str(number)
print("Result:", number * arbitrary_value)
I can clearly understand when I what is going on with closures. But when looking at those two yield
's with resumeback
, I do not see it working clearly. Basically, I would say that closures are more intuitive than the this = yied
plus the second yield function(this.send)
call.
I think it would help, if the first this = yield
call could not required, so I can forget about it. Hence, only the second yield
call could be done like this:
from resumeback import send_self
@send_self
def main():
arbitrary_value = 10
# Yield pauses execution until one of the generator methods is called,
# such as `.send`, which we provide as the callback parameter.
number = yield ask_for_user_input("Please enter a number", send_self)
number = str(number)
print("Result:", number * arbitrary_value)
Can the this = yield
call be embed inside the decorator @send_self
and formerly to "send myself"
I could just call yield function(send_self)
?
I would say that it would look much better than having to remember both to do the first call this = yield
and yield function(this.send)
.
@FichteFoll I could do this:
from resumeback import send_self @send_self def main(this): # Yield pauses execution until one of the generator methods is called, # such as `.send`, which we provide as the callback parameter. number = yield ask_for_user_input("Please enter a number", this.send) number = str(number) print("Result:", number * arbitrary_value)I'm unsure how I would make the above work for methods though. Gonna need even more magic
I would suggest the this
to be a function pointer, so, it can be more straight forward. However, I do not know about other usages of it where could not be pointing to a function directly:
from resumeback import send_self
@send_self
def main(myself):
arbitrary_value = 10
# Yield pauses execution until one of the generator methods is called,
# such as `.send`, which we provide as the callback parameter.
number = yield ask_for_user_input("Please enter a number", myself)
number = str(number)
print("Result:", number * arbitrary_value)
For classmethods, perhaps it could be a cumulative sum of decorators:
from resumeback import send_self
@send_self
@classmethod
def main(myself, cls):
arbitrary_value = 10
# Yield pauses execution until one of the generator methods is called,
# such as `.send`, which we provide as the callback parameter.
number = yield ask_for_user_input("Please enter a number", myself)
number = str(number)
print("Result:", number * arbitrary_value)
But I do not know whether or not you can patch stuff like that in Python.
Something must have changed with how classmethods function in 3.9.
λ pytest -k test_classmethod
================================================= test session starts =================================================
platform linux -- Python 3.9.5, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /home/fichte/code/resumeback
plugins: xonsh-0.9.27
collected 60 items / 58 deselected / 2 selected
tests/test_descriptors.py F. [100%]
====================================================== FAILURES =======================================================
__________________________________________________ test_classmethod ___________________________________________________
def test_classmethod():
ts = State()
class B:
@classmethod
@send_self
def clsmethod(this, cls, param):
yield defer(this.next)
assert cls is B
ts.run = param
b = B()
> wait_until_finished(b.clsmethod(123))
tests/test_descriptors.py:33:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
resumeback/__init__.py:371: in __call__
gen_wrapper.next() # Start the first iteration
resumeback/__init__.py:109: in _next
return self._send(generator)
resumeback/__init__.py:147: in _send
return generator.send(value)
resumeback/__init__.py:357: in wrapper
return (yield from self.func(gen_wrapper, *args, **kwargs))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
this = <class 'tests.test_descriptors.test_classmethod.<locals>.B'>
cls = <resumeback.GeneratorWrapper object at 0x7f68d3808430>, param = 123
@classmethod
@send_self
def clsmethod(this, cls, param):
> yield defer(this.next)
E AttributeError: type object 'B' has no attribute 'next'
tests/test_descriptors.py:28: AttributeError
------------------------------------------------ Captured stdout call -------------------------------------------------
<bound method test_classmethod.<locals>.B.clsmethod of <class 'tests.test_descriptors.test_classmethod.<locals>.B'>> (123,)
=============================================== short test summary info ===============================================
FAILED tests/test_descriptors.py::test_classmethod - AttributeError: type object 'B' has no attribute 'next'
===================================== 1 failed, 1 passed, 58 deselected in 0.13s ======================================
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.