回答
你的问题让我很好奇,所以我看了一些现实世界中的代码:Python标准库。我发现了67个嵌套函数的例子。这里有一些解释。
一个很简单的理由来使用嵌套功能很简单,就是你定义的功能并不需要是全球性的,因为只有封闭函数使用它。从Python的quopri.py标准库模块一个典型的例子:
def encode(input, output, quotetabs, header = 0):
...
def write(s, output=output, lineEnd='\n'):
# RFC 1521 requires that the line ending in a space or tab must have
# that trailing character encoded.
if s and s[-1:] in ' \t':
output.write(s[:-1] + quote(s[-1]) + lineEnd)
elif s == '.':
output.write(quote(s) + lineEnd)
else:
output.write(s + lineEnd)
... # 35 more lines of code that call write in several places
在这里有是encode
函数中一些常见的代码,所以笔者简单地分解出来进入write
功能。
另一个常见用途为嵌套函数是re.sub
。下面是来自json/encode.py标准库模块的一些代码:
def encode_basestring(s):
"""Return a JSON representation of a Python string
"""
def replace(match):
return ESCAPE_DCT[match.group(0)]
return '"' + ESCAPE.sub(replace, s) + '"'
这里ESCAPE
是一个正则表达式,ESCAPE.sub(replace, s)
发现的ESCAPE
所有比赛中s
和替换每一个与replace(match)
。
事实上,任何API,像re.sub
,它接受一个函数作为参数可能会导致出现嵌套函数是便利的情况。例如,在turtle.py有一些愚蠢的演示代码,这是否:
def baba(xdummy, ydummy):
clearscreen()
bye()
...
tri.write(" Click me!", font = ("Courier", 12, "bold"))
tri.onclick(baba, 1)
onclick
希望你传递一个事件处理函数,所以我们定义一个,并通过它在
这些都是很好的例子,但它们都可以写成全局函数而不会丢失任何功能。嵌套函数不仅仅是语法糖!你应该在需要的地方给出一些例子 – Claudiu 2010-06-05 13:57:14
也值得注意的是,嵌套函数会增加开销。每次调用外部函数时,Python都会创建一个全新的内部函数实例。在很多情况下,这并不重要,但有时候确实如此。 – 2016-05-13 14:59:02
Decorators是嵌套函数非常流行的应用。这是一个装饰器的例子,它在对装饰函数进行任何调用之前和之后都会打印语句。
def entry_exit(f):
def new_f(*args, **kwargs):
print "Entering", f.__name__
f(*args, **kwargs)
print "Exited", f.__name__
return new_f
@entry_exit
def func1():
print "inside func1()"
@entry_exit
def func2():
print "inside func2()"
func1()
func2()
print func1.__name__
该死的!你击败了我:P – Skilldrick 2010-01-06 23:29:46
其实,这是另外一个话题去学习,但如果你看的东西上“使用功能的装饰”,你会看到的嵌套函数的一些例子。
嵌套函数避免混乱与其他函数和变量只能使局部意义上的程序的其他部分。
返回斐波那契数的函数可以被定义如下:
>>> def fib(n):
def rec():
return fib(n-1) + fib(n-2)
if n == 0:
return 0
elif n == 1:
return 1
else:
return rec()
>>> map(fib, range(10))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
编辑:在实践中,发电机将是这一个更好的解决方案,但该示例展示了如何利用嵌套函数的优势。
可能值得注意的是,每次调用fib时,都会创建一个新的rec函数对象。在代码清理的情况下,这通常是不可取的。对于装饰者来说,这基本上是必要的。 – 2010-01-06 23:49:28
我只有创建装饰时使用嵌套函数。嵌套函数基本上是向函数中添加某些行为的一种方式,而无需知道要添加行为的函数。
from functools import wraps
from types import InstanceType
def printCall(func):
def getArgKwargStrings(*args, **kwargs):
argsString = "".join(["%s, " % (arg) for arg in args])
kwargsString = "".join(["%s=%s, " % (key, value) for key, value in kwargs.items()])
if not len(kwargs):
if len(argsString):
argsString = argsString[:-2]
else:
kwargsString = kwargsString[:-2]
return argsString, kwargsString
@wraps(func)
def wrapper(*args, **kwargs):
ret = None
if args and isinstance(args[0], InstanceType) and getattr(args[0], func.__name__, None):
instance, args = args[0], args[1:]
argsString, kwargsString = getArgKwargStrings(*args, **kwargs)
ret = func(instance, *args, **kwargs)
print "Called %s.%s(%s%s)" % (instance.__class__.__name__, func.__name__, argsString, kwargsString)
print "Returned %s" % str(ret)
else:
argsString, kwargsString = getArgKwargStrings(*args, **kwargs)
ret = func(*args, **kwargs)
print "Called %s(%s%s)" % (func.__name__, argsString, kwargsString)
print "Returned %s" % str(ret)
return ret
return wrapper
def sayHello(name):
print "Hello, my name is %s" % (name)
if __name__ == "__main__":
sayHelloAndPrintDebug = printCall(sayHello)
name = "Nimbuz"
sayHelloAndPrintDebug(name)
忽略了“printCall”功能的所有魔神的现在和重点只有“sayHello的”功能及以下。我们在这里做的是我们想要打印出每次调用“sayHello”函数时如何调用,而不知道或改变“sayHello”函数的作用。因此,我们通过将“sayHello”函数传递给“printCall”来重新定义“sayHello”函数,该函数返回一个NEW函数,该函数执行“sayHello”函数的功能并打印“sayHello”函数的调用方式。这是装饰者的概念。
把“@printCall”的定义的sayHello上面完成同样的事情:
@printCall
def sayHello(name):
print "Hello, my name is %s" % (name)
if __name__ == "__main__":
name = "Nimbuz"
sayHello(name)
他们使用的时候非常有用。将其他功能作为输入的功能。说你是在一个函数,并且要排序的字典基础上,项目的价值的项目清单:
def f(items):
vals = {}
for i in items: vals[i] = random.randint(0,100)
def key(i): return vals[i]
items.sort(key=key)
你可以只定义关键在那里,并用它瓦尔斯,一个局部变量。
另一个用例是回调函数。
好的,除了装饰者:假设你有一个应用程序,你需要根据不断变化的子串排序一个字符串列表。现在,sorted
函数采用key=
参数,该参数是一个参数的函数:要排序的项目(在本例中为字符串)。那么如何判断这个子函数需要排序呢?封闭或嵌套功能,非常适合:
def sort_key_factory(start, stop):
def sort_key(string):
return string[start: stop]
return sort_key
简单的eh?您可以通过在元组或片段对象中封装开始和停止,然后将这些序列或迭代传递给sort_key_factory来扩展此功能。
又一个(非常简单)的例子。一个返回另一个函数的函数。请注意内部函数(返回的)如何使用外部函数范围内的变量。
def create_adder(x):
def _adder(y):
return x + y
return _adder
add2 = create_adder(2)
add100 = create_adder(100)
>>> add2(50)
52
>>> add100(50)
150
- 1. 单位对现实世界
- 2. 真实世界的接口实现
- 3. 如何在现实世界中使用函数式编程?
- 4. Exec的现实世界的例子
- 5. “现实世界”中的功能技巧
- 6. 现实世界的坐标骨架
- 7. 仿函数或函数对象的真实世界用法
- 8. 的javascript:在现有的实现嵌套函数
- 9. 你好世界虚拟现实应用
- 10. 实现嵌套GROUP_CONCAT
- 11. 嵌套表实现
- 12. 嵌套栈实现
- 13. 真实世界的目的
- 14. 真实世界中的Glassfish
- 15. 真实世界中的数据结构
- 16. 一种“已排序”数据的现实世界示例
- 17. 现实世界物体之间的四元数差异 - > Unity
- 18. 真实世界的部分函数示例
- 19. 修改现有的嵌套JavaScript函数
- 20. i18n世界您好世界
- 21. C10K为现代世界
- 22. 嵌套函数
- 23. OOP真实世界示例
- 24. Flashpunk。将实体世界
- 25. 真实世界对象
- 26. RabbitMQ真实世界场景
- 27. 真实世界参数优化
- 28. 关系阵营和“现实世界”数据库开发
- 29. Microsoft Kinect SDK深度数据到现实世界坐标
- 30. 在现实世界中使用核心数据关系吗?
内部函数是否将封闭范围内的变量值保留下来,这是事实吗? – Skilldrick 2010-01-06 23:32:32