• Python tricks(2) -- method默认参数和闭包closure


    Python的method可以设置默认参数, 默认参数如果是可变的类型, 比如list, map等, 将会影响所有的该方法调用. 

    下面是一个简单的例子

    def f(a=None, l=[]):
        if not a:
            return l
        l.append(a)
        return l
    
    if __name__ == "__main__":
        print f("a")
        print f("b")
        print f("b")
        print f(l=[])
        print f()
    

    输出结果如下:

    ['a']
    ['a', 'b']
    ['a', 'b', 'b']
    []
    ['a', 'b', 'b']
    

    我们可以看到f的默认参数l在所有的方法调用中都受到影响了, 这个可能并不一定符合默认参数设置的初衷. 

    想要避免这种影响, 可以这样做.

    def f(a=None, l=None):
        if not l:
            l = []
        if not a:
            return l
        l.append(a)
        return l
    
    if __name__ == "__main__":
        print f("a")
        print f("b")
        print f("b")
        print f(l=[])
        print f()
    

    将l设置为None, 在方法内部判断, 并初始化为空, 这样改变后的输出为:

    ['a']
    ['b']
    ['b']
    []
    []
    

    具体可以查阅官方文档的说明[参考1].

    下面再来说说闭包.

    我个人理解, 闭包的形式是方法的嵌套, 主要的作用是为了在整个调用过程中保存方法的某些状态. 有些时候method的默认参数也可以做到保存方法状态.

    用dict保存一些变量信息, 类似context的东西.

    闭包实现:

    def context():
        data = {}
    
        def _context(key, value=None):
            if value:
                data[key] = value
                return data
            else:
                return data.get(key, None), data
    
        return _context
    
    c = context()
    print c("key")
    print c("key", "value")
    print c("key")
    

    方法默认参数的实现

    def d(key, value=None, data={}):
        if value:
            data[key] = value
            return data
        else:
            return data.get(key, None), data
    
    print d("key")
    print d("key", "value")
    print d("key")
    

    通过实现类的magic method来实现

    class e(object):
        def __init__(self):
            self.data = {}
    
        def __call__(self, key, value=None):
            if value:
                self.data[key] = value
                return self.data
            else:
                return self.data.get(key, None), self.data
    
    f = e()
    print f("key")
    print f("key", "value")
    print f("key")
    

    三种实现的输出结果都是一样的

    (None, {})
    {'key': 'value'}
    ('value', {'key': 'value'})
    

    在python中方法本身也是一个对象, 可以有自己的属性等, 通过第三种实现, 我们可以理解默认参数是方法对象的一个属性, 伴随其生命周期.

    使用def func()定义的时候就是定义了一个方法的类, 之后获取了一个名为func的实例化对象.

    可能有人会奇怪, 这种东西哪里有使用的场景了? 我能想到的一个场景就是, 我想通过查找字典的方式获取一个信息, 这个字典是一个大文件(加载耗时), 我只希望加载一次, 这个时候闭包可以发挥其特殊的作用, 而且代码也比较优雅.

    本文是笔者对于python方法的一些理解. 水平有限, 欢迎拍砖!

    参考文档:

    1. Python Docs: http://docs.python.org/2/tutorial/controlflow.html#default-argument-values
  • 相关阅读:
    2-2. 线性池技术优化
    2-1. 基于OpenSSL的传输子系统实现
    1-4. 嵌入式web服务器BOA的移植及应用
    1-3. Linux下移动图像监测系统——motion的移植及应用
    1-2. 摄像头驱动的使能配置、V4L2编程接口的设计应用
    1-1. OSS/ALSA 声卡的驱动与配置和 Madplay 嵌入式播放器的移植
    嵌入式Linux开发环境搭建,问题ping、nfs的解决
    并发服务器的设计
    WPF 子类访问主类(父类)MainWindow的属性和方法
    stm32 读取多路SDADC
  • 原文地址:https://www.cnblogs.com/icejoywoo/p/3530552.html
Copyright © 2020-2023  润新知