python:变异“globals”以动态地将内容放入scop

2024-06-11 12:49:01 发布

您现在位置:Python中文网/ 问答频道 /正文

这主意有多可怕?类monad实现了with接口,以将内容放入或超出范围,因此我可以编写一个泛型函数库,例如引用函数unit和{}的函数库,这些函数可以在运行时放入实现。(不管这些代码做了什么,或者是否是个好主意)

我尝试过的其他想法都是围绕一个包含unit/bind作为参数或kwarg的结构传递,或者将m_-chain放在一个类中,根据自我单位以及自我约束并且让派生类提供它们。但它增加了代码和语法的复杂性,并将单元/绑定绑定绑定到python中表示monad的方式上。用范围来做这件事感觉好极了。在

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

Tags: thelambdainselfnonechainforif
1条回答
网友
1楼 · 发布于 2024-06-11 12:49:01

我认为连续不断地在全球范围内出击绝对是个糟糕的主意。依赖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)

然后:

^{pr2}$

变得简单:

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

实际上,显式地传递函数似乎更像python,而且似乎不会导致您失去任何灵活性。在

相关问题 更多 >