V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
SlipStupig
V2EX  ›  Python

Python 为什么要使用函数嵌套函数

  •  
  •   SlipStupig · 2017-02-20 17:47:47 +08:00 · 7732 次点击
    这是一个创建于 2866 天前的主题,其中的信息可能已经有所发展或是发生改变。

    看一些代码会写成函数中嵌套函数,例如:

    
     def func():
         def new_func():
              return 1
        a = new_func()
    
    

    这种写法和 lambda 和单独创建一个 function 有什么区别或优势吗?

    21 条回复    2018-01-22 22:02:19 +08:00
    clino
        2
    clino  
       2017-02-20 17:54:57 +08:00
    对啊,要写闭包的时候很好用的
    RadishWind
        3
    RadishWind  
       2017-02-20 18:03:54 +08:00   ❤️ 1
    查看一下柯里化的定义,这样写返回的新函数能够保持当时的状态,而且能够达到惰性求值的效果(用到这个函数的时候再处理传入的参数)
    ansheng
        4
    ansheng  
       2017-02-20 18:07:03 +08:00
    例如装饰器传参,就是多层嵌套的函数,
    picasso250
        5
    picasso250  
       2017-02-20 18:18:23 +08:00
    因为 lambda 的限制
    firstway
        6
    firstway  
       2017-02-20 21:07:01 +08:00   ❤️ 1
    你的例子确实 lambda 也可以做到。但是下面的呢?

    def func(x):
    def new_func(y):
    return x+y
    return new_func

    >>> a = func(10)
    >>> a(3)
    13
    >>> a(5)
    15
    ic3z
        7
    ic3z  
       2017-02-20 22:27:16 +08:00 via Android
    也许是为了方便吧。脚本嘛
    Yinz
        8
    Yinz  
       2017-02-20 22:48:30 +08:00
    额,其实我也不是很了解这两种用法的差异的,不过一不小心就写了出来 @firstway

    In [1]: def func(x):
    ...: return lambda y:y+x
    ...:

    In [2]: a = func(10)

    In [3]: a(3)
    Out[3]: 13

    In [4]: a(5)
    Out[4]: 15
    will0404
        9
    will0404  
       2017-02-20 22:57:23 +08:00
    @firstway 你的例子不合适啊。

    >>> a = lambda x: lambda y: x + y
    >>> b = a(10)
    >>> b(3)
    13
    >>> b(5)
    15
    will0404
        10
    will0404  
       2017-02-20 23:08:38 +08:00
    因为 lambda 是匿名的,我想区别应该是名字是否有意义,比如递归吧。

    >>> def func(x, sum):
    ... if(x==0):
    ... return sum
    ... return func(x-1, sum + x)
    ...
    >>> func(10, 0)
    55

    lambda 大概写不出上面这个递归?
    fwrq41251
        11
    fwrq41251  
       2017-02-20 23:35:47 +08:00 via Android
    能省几个参数,函数的作用域小了
    gamexg
        12
    gamexg  
       2017-02-21 00:08:01 +08:00 via Android
    一般是返回一个函数指针时用。一般外部固定了函数指针的参数,但是自己又需要传递给函数指针一些数据,这样嵌套函数可以使得内部函数可以访问外部函数的变量。关键字:闭包,需求的例子:装饰器。

    不用 lambda 的原因是 lambda 限制太大,不方便。
    est
        13
    est  
       2017-02-21 08:29:38 +08:00
    这就是 meta 编程啊
    enenaaa
        14
    enenaaa  
       2017-02-21 09:14:42 +08:00
    lambda 你能多写几行么
    lll9p
        15
    lll9p  
       2017-02-21 09:44:52 +08:00 via Android
    Python 里 lambda 只能写一行啊
    drlalll
        16
    drlalll  
       2017-02-21 10:14:32 +08:00
    @gamexg
    需要做到这个的话直接用指针不行吗?
    gamexg
        17
    gamexg  
       2017-02-21 10:30:52 +08:00   ❤️ 1
    @drlalll 无法实现,像下面的装饰器例子:

    https://gist.github.com/GameXG/ed84b114067fb4a7b398cb811a9241ca

    需要将 @w(123) 的 123 传递给 fffff 函数,但是 fffff 函数是会被当作 hello3 参数给用户调用的,用户不会帮你把 123 传递进去,只能通过闭包的方式传递进去 123 .
    wizardoz
        18
    wizardoz  
       2017-02-21 10:35:18 +08:00
    lambda 写复杂的函数很麻烦啊
    sadscv
        19
    sadscv  
       2017-02-21 13:55:52 +08:00   ❤️ 2
    这是一种嵌套函数的写法,有时候它和 lambda 没什么区别,但有些情况下它会实现一个闭包,所以我姑且认为楼主是想知道闭包的特性.
    那么这里首先强烈建议楼主了解一下 namespace 与变量作用域的相关知识.
    http://python.jobbole.com/81367/
    如果只要了解闭包的概念,请参考这篇文章.
    http://blog.csdn.net/marty_fu/article/details/7679297
    如果想知道闭包的实现原理.那么你必须得明白函数调用过程.因为闭包本身就是调用一个函数反回另一个函数.
    这里推荐 UCSB 的教程,提供了一个交互式的函数调用演示程序.共6个课程,每个课程都很短,但看完这些你大概能对函数调用帧栈有初步了解.
    https://www.cs.ucsb.edu/~pconrad/cs8/topics.beta/theStack/01/
    到现在你已经可以开始探究 python 在函数调用中如何精妙地完成参数传递.
    http://www.jianshu.com/p/d00108741a18
    如果能坚持到这里,那么你已经停不下来了...函数调用过程中所有涉及到的源码作者都给出了分析,看完之后应该什么都明白了
    http://python.jobbole.com/83545/
    以下链接可以看看,也许能帮助你理解源码.
    http://www.cnblogs.com/hackerl/p/5985102.html
    http://eli.thegreenplace.net/2012/03/23/python-internals-how-callables-work/
    julyclyde
        20
    julyclyde  
       2017-02-26 14:16:47 +08:00
    一种劣习,让函数变成有状态的,或者叫不完全依赖于字面输入,还依赖一个隐藏输入的东西
    uygnef
        21
    uygnef  
       2018-01-22 22:02:19 +08:00
    我用这个是因为 有时候要用递归,把 helper 放函数里面可以把外面函数的变量当全局变量。
    另外就是 helper 只用这里会用,写外面不清晰。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1101 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 148ms · UTC 23:00 · PVG 07:00 · LAX 15:00 · JFK 18:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.