Expose the inner scope of functions
Project description
Innerscope
innerscope
exposes the inner scope of functions and offers primitives suitable for creating pipelines. It explores a design space around functions, dictionaries, and classes.
A function can be made to act like a dictionary:
@innerscope.call
def info():
first_name = 'Erik'
last_name = 'Welch'
full_name = f'{first_name} {last_name}'
return 'success!'
>>> info['first_name']
'Erik'
>>> info['full_name']
'Erik Welch'
>>> info.return_value
'success!'
Sometimes we want functions to be more functional and accept arguments:
if is_a_good_idea:
suffix = 'the amazing'
else:
suffix = 'the bewildering'
@innerscope.callwith(suffix)
def info_with_suffix(suffix=None):
first_name = 'Erik'
last_name = 'Welch'
full_name = f'{first_name} {last_name}'
if suffix:
full_name = f'{full_name} {suffix}'
>>> info_with_suffix['full_name']
'Erik Welch the bewildering'
Cool!
But, what if we want to reuse the data computed in info
? We can control exactly what values are within scope inside of a function (including from closures and globals; more on these later). Let's bind the variables in info
to a new function:
@info.bindto
def add_suffix(suffix):
full_name = f'{first_name} {last_name} {suffix}'
>>> scope = add_suffix('the astonishing')
>>> scope['full_name']
'Erik Welch the astonishing'
add_suffix
here is a ScopedFunction
. It returns a Scope
, which is the dict-like object we've already seen.
scoped_function
ftw!
Except for the simplest tasks (as with call
and callwith
above), using scoped_function
should usually be preferred.
# step1 becomes a ScopedFunction that we can call
@scoped_function
def step1(a):
b = a + 1
>>> scope1 = step1(1)
>>> scope1 == {'a': 1, 'b': 2}
True
# Bind any number of mappings to variables (later mappings have precedence)
@scoped_function(scope1, {'c': 3})
def step2(d):
e = max(a + d, b + c)
>>> step2.outer_scope == {'a': 1, 'b': 2, 'c': 3}
True
>>> scope2 = step2(4)
>>> scope2 == {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
True
>>> scope2.inner_scope == {'d': 4, 'e': 5}
True
Suppose you're paranoid (like me!) and want to control whether a function uses values from closures or globals. You're in luck!
global_x = 1
def f():
closure_y = 2
def g():
local_z = global_x + closure_y
return g
# If you're the trusting type...
>>> g = f()
>>> innerscope.call(g) == {'global_x': 1, 'closure_y': 2, 'local_z': 3}
True
# And for the intelligent...
>>> paranoid_g = scoped_function(g, use_closures=False, use_globals=False)
>>> paranoid_g.missing
{'closure_y', 'global_x'}
>>> paranoid_g()
- NameError: Undefined variables: 'global_x', 'closure_y'.
- Use `bind` method to assign values for these names before calling.
>>> new_g = paranoid_g.bind({'global_x': 100, 'closure_y': 200})
>>> new_g.missing
set()
>>> new_g() == {'global_x': 100, 'closure_y': 200, 'local_z': 300}
True
How?
This library requires surprisingly little magic. Perhaps I'll explain it some day. Here's a hint: the wrapped function should only return at the very end of the function.
Why?
It's all @mrocklin's fault for asking a question.
innerscope
is exploring a data model that could be convenient for running code remotely with dask.
I bet it would even be useful for building pipelines with dask.
This library is totally awesome and you should use it and tell all your friends 😉 !
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file innerscope-0.0.4.tar.gz
.
File metadata
- Download URL: innerscope-0.0.4.tar.gz
- Upload date:
- Size: 28.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/49.6.0 requests-toolbelt/0.9.1 tqdm/4.48.2 CPython/3.8.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2114b736a82d019177c24a41f10e6f1c391ef739ae319b984b6c593b0e3c3bb0 |
|
MD5 | c0072a8b39b21ad43d5816db7ad6824e |
|
BLAKE2b-256 | 1d8aebe26734481fe95ea1ad91d468073a8517522ef6ec0eace6a3c239ce696d |
Provenance
File details
Details for the file innerscope-0.0.4-py3-none-any.whl
.
File metadata
- Download URL: innerscope-0.0.4-py3-none-any.whl
- Upload date:
- Size: 11.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/49.6.0 requests-toolbelt/0.9.1 tqdm/4.48.2 CPython/3.8.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2345746d2eab69990607fab4298922b09e52dd0ce03629fd7e3686ed2b4eb198 |
|
MD5 | 231f7ba7f846b3dc43904d656f4dfe58 |
|
BLAKE2b-256 | 6f55b4647f28939f47b3eead57f44cb032bc22c1d18bc7abb1ea7ebb464af83c |