Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/351.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python:修改“globals”以动态地将内容放入范围_Python_Monads - Fatal编程技术网

python:修改“globals”以动态地将内容放入范围

python:修改“globals”以动态地将内容放入范围,python,monads,Python,Monads,这是一个多么糟糕的主意?类monad使用接口实现以将内容放入和移出范围,因此我可以编写一个通用函数库,如m_chain,它引用函数unit和bind,它们可以在运行时放入实现。(不管这些代码做什么,也不管它是否是个好主意。) 我尝试过的其他想法都是围绕一个包含unit/bind的结构作为参数或kwarg传递,或者将m_链放在一个类中,根据self.unit和self.bind实现它,并让派生类提供它们。但它增加了代码和语法的复杂性,并将unit/bind与python中单子的表达方式联系起来。使

这是一个多么糟糕的主意?类
monad
使用
接口实现
以将内容放入和移出范围,因此我可以编写一个通用函数库,如m_chain,它引用函数
unit
bind
,它们可以在运行时放入实现。(不管这些代码做什么,也不管它是否是个好主意。)

我尝试过的其他想法都是围绕一个包含unit/bind的结构作为参数或kwarg传递,或者将m_链放在一个类中,根据self.unit和self.bind实现它,并让派生类提供它们。但它增加了代码和语法的复杂性,并将unit/bind与python中单子的表达方式联系起来。使用scope来实现这一点感觉好多了

class monad:
    """Effectively, put the monad definition in lexical scope.
    Can't modify the execution environment `globals()` directly, because
    after globals().clear() you can't do anything.
    """
    def __init__(self, monad):
        self.monad = monad
        self.oldglobals = {}

    def __enter__(self):
        for k in self.monad:
            if k in globals(): self.oldglobals[k]=globals()[k]
            globals()[k]=self.monad[k]

    def __exit__(self, type, value, traceback):
        """careful to distinguish between None and undefined.
        remove the values we added, then restore the old value only
        if it ever existed"""
        for k in self.monad: del globals()[k]
        for k in self.oldglobals: globals()[k]=self.oldglobals[k]


def m_chain(*fns):
    """returns a function of one argument which performs the monadic
    composition of fns"""
    def m_chain_link(chain_expr, step):
        return lambda v: bind(chain_expr(v), step)
    return reduce(m_chain_link, fns, unit)




identity_m = {
    'bind':lambda v,f:f(v),
    'unit':lambda v:v
}

with monad(identity_m):
    assert m_chain(lambda x:2*x, lambda x:2*x)(2) == 8


maybe_m = {
    'bind':lambda v,f:f(v) if v else None,
    'unit':lambda v:v
}

with monad(maybe_m):
    assert m_chain(lambda x:2*x, lambda x:2*x)(2) == 8
    assert m_chain(lambda x:None, lambda x:2*x)(2) == None

我认为连续打环球绝对是个糟糕的主意。依赖globals似乎与您在这里模仿的功能风格相反

为什么不将m_链定义为:

def m_chain(bind, *fns):
    """returns a function of one argument which performs the monadic
    composition of fns"""
    def m_chain_link(chain_expr, step):
        return lambda v: bind(chain_expr(v), step)
    return reduce(m_chain_link, fns, unit)
然后:

变得简单:

assert m_chain(lambda v,f:f(v), lambda x:2*x, lambda x:2*x)(2) == 8

实际上,显式传递函数看起来更像是python,并且似乎不会使您失去任何灵活性。

似乎是合法的。我对一些答案感兴趣。我挖掘其效果,让您根据需要交换函数的变体。如果有缺点,我看不到。我可能会小心地提供
m_chains
将要使用的函数的默认定义,或者在未设置它们的情况下抛出一个有意义的异常,否则我可以看到一些类似这样的应用程序。
assert m_chain(lambda v,f:f(v), lambda x:2*x, lambda x:2*x)(2) == 8