代码之家  ›  专栏  ›  技术社区  ›  sof

替换全局变量

  •  0
  • sof  · 技术社区  · 7 年前

    下面,我提出了人工传递引用var的方法 n2 f2() g2(x) 而不是全局var n 在里面 f() 以及嵌套的 g() . 在这种情况下,还有其他更好的方法来替换全局变量吗?

    from random import randint
    
    # global value var
    def f():
        global n
        n=0    
        def g(): 
            global n
            if randint(1,100)>50: n+=1    
        for _ in range(100): g()
        print(n)
    
    # local reference var
    def f2():
        n2=[0]
        for _ in range(100): g2(n2)
        print(n2[0])    
    def g2(x):
        if randint(1,100)>50: x[0]+=1
    
    2 回复  |  直到 7 年前
        1
  •  2
  •   UltraInstinct    7 年前

    简短的回答

    更长的答案 :(注意:这可能不是您问题的直接答案。)

    g2() 需要知道有一个变量应该作为其调用的一部分进行更新吗?有没有一种方法可以让更新变量的责任属于定义变量的责任?怎么样 f2() 是定义变量并更新它的那个吗?这样就可以将对该变量的所有更改限制在一个很小的范围内( f2() ).

    def f2():
        n2 = 0
        for _ in range(100):
            n2 += g2()
        print(n2)
    
    def g2():
        return 1 if randint(1,100)>50 else 0
    
        2
  •  2
  •   David Maze    7 年前

    从使用函数语言开始,从尝试编写可复制的测试开始,我通常尝试采用这样一个规则:函数应该将其所有输入声明为参数,并将其所有输出生成为返回值:在最大可能的范围内,函数不应该有副作用。使用 global 关键字可能表示您违反了此规则。

    from random import randint
    def g(n):
        """Returns either n or n+1, with 50% probability."""
        if randint(1,100)>50:
            return n+1
        else:
            return n
    

    然后迭代函数可以多次调用:

    def f():
        """Produces a number between 0 and 100 with $DISTRIBUTION."""
        n = 0
        for _ in range(100):
            n = g(n)
        return n
    

    最后在高层:

    if __name__ == '__main__':
        print(f())
    

    因为我们从来都不能完全确定我们的代码,所以我们可以编写一些测试。

    def test_f():
        n = f()
        assert n >= 0 and n < 100
    
    def test_g():
        n = g(0)
        assert n == 0 or n == 1
    
    def test_g_dist():
        count = 100
        ns = [g(0) for _ in range(count)]
        assert(all(n == 0 or n == 1) for n in ns)
        zeros = len([n for n in ns if n == 0])
        ones = len([n for n in ns if n == 1])
        assert zeros + ones == count
        # won't always pass; probability of failure left as an exercise
        assert zeros > 0.45 * count and zeros < 0.55 * count
    

    f() g(n)