跳转到主要内容

暴露函数的内联作用域

项目描述

Innerscope

conda-forge pypi PyPI - Python Version License Tests Coverage

innerscope暴露函数的内联作用域,并提供适合创建管道的原语。它探索围绕函数、字典和类的架构空间。

使用pip安装: pip install innerscope

使用conda安装: conda install -c conda-forge innerscope

函数可以被制作成像字典一样使用

@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!'

有时我们希望函数更加函数式并接受参数

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'

太酷了!

但是,如果我们想要重用info中计算的数据?我们可以在函数内部(包括从闭包和全局变量;稍后将详细介绍)精确控制作用域内的哪些值。让我们将info中的变量绑定到一个新函数

@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是一个ScopedFunction。它返回一个Scope,这是我们之前已经见过的类似字典的对象。

scoped_function 真是不错!

除了最简单的任务(如上例中的 callcallwith),通常应优先使用 scoped_function

# 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

假设你(像我一样)是个偏执狂,想控制函数是否使用闭包或全局变量的值。你很幸运!

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()
- UserWarning: Undefined variables: 'global_x', 'closure_y'.
- Perhaps 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

怎么办?

这个库使用 execeval、AST 或源代码。它在 CPythonPyPyStackless Python 上运行。你应该感到使用 innerscope 是很舒适的。它实际上提供了两种获取内部作用域的方法,两种都非常可靠。当然,我们在底层做了些神奇的魔法,我希望能有一天解释一下。

为什么?

这都是因为 @mrocklin 提出了一个 问题innerscope 正在探索一个可能方便在 dask 上远程运行代码的数据模型。我相信它甚至可以用来构建 dask 管道。我确信还有其他创新用途等待被发现。更新: afar 已诞生!

这个库非常棒,你应该使用它并告诉你的所有朋友 😉

项目详情


下载文件

下载适合您平台文件的文件。如果您不确定该选择哪个,请了解更多关于 安装包 的信息。

源代码分发

innerscope-0.7.0.tar.gz (22.9 kB 查看哈希值)

上传时间 源代码

构建分发

innerscope-0.7.0-py3-none-any.whl (19.3 kB 查看哈希值)

上传时间 Python 3

支持者

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面