huwenchao
1/21/2016 - 8:02 AM

new_counter.py

'''
v2ex看到的一道题,蛮有意思的。
原文链接:http://www.v2ex.com/t/252207

请实现函数 new_counter ,使得调用结果如下:

c1 = new_counter(10)
c2 = new_counter(20)
print c1(), c2(), c1(), c2()

outputs :
11 21 12 22
'''
def new_counter(n):
    '''类可以用 __call__ 模拟函数的操作'''

    class Counter(object):

        def __init__(self, num):
            self.num = num

        def __call__(self):
            self.num += 1
            return self.num

    return Counter(n)


def new_counter(n):
    '''函数可以被添加新的属性'''
    def c():
        c.var += 1
        return c.var
    c.var = n
    return c


# def new_counter(num):
#     count = num
#     def counter():
#         count += 1
#         return count
#     return counter

# 这是我一开始想到的错误写法,因为 counter 中的 count += 1这一句
# 相当于 count = count + 1,内函数中新创建了一个count,
# 此时count被绑定到了里面这个函数的count,而此时count还没有值
# 因此会报 变量赋值前引用 的错误
# 而下面的方法里,并没有创建新的count,因此count绑定的是外函数里的count,直接修改其中的变量
# 因此不会报错,相应的count也可以改成其它Python可变量(字典、类)

def new_counter(num):
    '''使用闭包,但是要维护一个中间变量,注意与下面的错误示例对比'''
    count = [num]
    def counter():
        count[0] += 1
        return count[0]
    return counter

def new_counter(num):
    '''使用闭包,但是要维护一个中间变量,注意与下面的错误示例对比'''
    count = {'num': num}
    def counter():
        count['num'] += 1
        return count['num']
    return counter