Python 嵌套函数

简述

在 Python 中,函数的用法可谓是千变万化,只不过我们平日接触的大多是一些基本用法。函数强大之处当然不止于此,它还有很多高级用法 - 闭包、装饰器。。。

这些高级用法都与嵌套函数紧密相关,所以有必要先熟悉一下嵌套函数。

  • 简述
  • 嵌套函数
  • 封装 - 数据隐藏
  • 贯彻 DRY 原则

版权所有:一去丶二三里,转载请注明出处:http://blog.csdn.net/liang19890820

嵌套函数

嵌套函数(Nested function)是在另一个函数(即:封闭函数)中定义的函数

嵌套函数的基本概念在前面已经介绍过了,参见:Python 函数的高级用法

那么,一般在什么情况下使用嵌套函数?

  • 封装 - 数据隐藏
  • 贯彻 DRY 原则
  • 闭包

除此之外,嵌套函数还有其他用法,只不过这些是比较常用的。另外,闭包的内容较为丰富,后面做单独分享。

封装 - 数据隐藏

可以使用内层函数来保护它们不受函数外部变化的影响,也就是说把它们从全局作用域隐藏起来。

来看一个简单的例子 - 求一个数字 n 的倍数:

>>> def outer(n):
...     def inner_multiple(n):  # 从外部代码隐藏
...         return n * 2
...     num = inner_multiple(n)
...     print(num)
...
>>>

尝试调用 inner_multiple(n) 会引发错误:

>>> outer(5)
10
>>>
>>> inner_multiple(5)  # 外部无法访问
...
NameError: name 'inner_multiple' is not defined

这是因为它被定义在 outer() 的内部,被隐藏了起来,所以外部无法访问。

Python 递归函数 一节中,分享过一个关于阶乘的递归实现,但是存在一个问题 - 没有做容错处理。

下面来利用嵌套函数,对递归做一个更好的实现:

>>> def factorial(n):
...
...     # 错误处理
...     if not isinstance(n, int):  # 仅限整形
...         raise TypeError("Sorry. 'n' must be an integer.")
...     if n < 0:  # 仅限 0 和 正数
...         raise ValueError("Sorry. 'n' must be zero or positive.")
...
...     def inner_factorial(n):
...         if n <= 1:
...             return 1
...         return n * inner_factorial(n - 1)
...     return inner_factorial(n)
...
>>> 

这样以来,程序就会变得更加健壮,当数据类型或值不合理时,便会引发错误:

>>> factorial('Py')  # 类型错误
...
TypeError: Sorry. 'n' must be an integer.
>>>
>>> factorial(-10)  # 值错误
...
ValueError: Sorry. 'n' must be zero or positive.
>>>
>>> factorial(5)  # OK
120

使用这种模式的主要优势在于:利用外部函数执行所有的参数检查,便可以在内部函数中跳过错误检查,并安全放心地进行使用。

贯彻 DRY 原则

DRY(Don’t Repeat Yourself)- 是指在程序设计以及计算中避免重复代码,因为这样会降低灵活性、简洁性,并且有可能导致代码之间的矛盾。

DRY 更多的是一种架构设计思想,在软件开发过程中的万事万物均可能重复,大到标准、框架、开发流程;中到组件、接口;小到功能、代码均纯存在自我重复。而 DRY 提倡的就是在软件开发过程中应消除所有这些自我重复。

如果看过《程序员修炼之道》,想必对这一思想有所了解,那里面做了很好的阐述。

例如,处理文件时,需要支持打开的文件对象和文件名,传统方式是采用两个函数分别实现。

支持文件对象:

>>> def print_file(f):
...     for line in f:
...         print(line)
...
>>> f = open('data.txt', 'r')
>>> print_file(f)
Hi, all

I am a pythoner

>>> 

支持文件名:

>>> def print_file_content(file_name):
...     if isinstance(file_name, str):
...         with open(file_name, 'r') as f:
...             for line in f:
...                 print(line)
...
>>> print_file_content('data.txt')
Hi, all

I am a pythoner

>>> 

很显然,有很多代码可以复用,通过嵌套函数来实现:

>>> def print_file(file):
...     def inner_print(file_process):
...         for line in file_process:
...             print(line, end = '')
...
...     if isinstance(file, str):
...         with open(file, 'r') as f:
...             inner_print(f)
...     else:
...         inner_print(file)
...
>>>

这样,一个函数便可以支持多种方式,简洁很重要。

>>> f = open('data.txt', 'r')
>>> print_file(f)
Hi, all
I am a pythoner
>>>
>>> print_file('data.txt')
Hi, all
I am a pythoner

除此之外,通常也会把 inner_print() 作为一个顶层私有函数,但是若想要将其作为一个内层函数隐藏起来,就用嵌套函数。

时间: 2024-10-02 02:54:41

Python 嵌套函数的相关文章

python常用函数详解_python

1.函数的介绍 为什么要有函数?因为在平时写代码时,如果没有函数的话,那么将会出现很多重复的代码,这样代码重用率就比较低...并且这样的代码维护起来也是很有难度的,为了解决这些问题,就出现了函数,用来将一些经常出现的代码进行封装,这样就可以在任何需要调用这段代码的地方调用这个函数就行了. 函数的定义:函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性: 代码重用 保持一致性 可扩展性 2.函数的创建 在python中函数定义的格式如下: def

Python中函数的参数传递与可变长参数介绍

  这篇文章主要介绍了Python中函数的参数传递与可变长参数介绍,本文分别给出多个代码实例来讲解多种多样的函数参数,需要的朋友可以参考下 1.Python中也有像C++一样的默认缺省函数 代码如下: def foo(text,num=0): print text,num foo("asd") #asd 0 foo("def",100) #def 100 定义有默认参数的函数时,这些默认值参数 位置必须都在非默认值参数后面. 调用时提供默认值参数值时,使用提供的值,

python回调函数用法实例分析

  这篇文章主要介绍了python回调函数用法,较为详细的分析了常用的调用方式,并实例介绍了Python回调函数的使用技巧,需要的朋友可以参考下 软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用.回调和异步调用.同步调用是一种阻塞式调用,调用方要等待对方执行完毕 才返回,它是一种单向调用;回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;异步调用是一种类似消息或事件的机制,不过它 的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,

Python open()函数文件打开、读、写基础操作

说明:         python的文件读写和打开操作都有自己特定的函数和方法,操作起来很简单.下面就来简单的了解下python文件的文件基本操作方法有哪些. 一.Python open()函数文件打开操作     打开文件会用到open函数,标准的python打开文件语法如下: 1 open(name[,mode[,buffering]])     open函数的文件名是必须的,而模式和缓冲参数都是可选的.比如说有个a.txt的文本文件,存放在c:\text下,那么你要打开它可以这样操作:

Python回调函数用法实例详解

  本文实例讲述了Python回调函数用法.分享给大家供大家参考.具体分析如下: 一.百度百科上对回调函数的解释: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应. 二.什么是回调: 软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用.回调和异步调用.同步

Python中函数的参数定义和可变参数用法实例分析

  本文实例讲述了Python中函数的参数定义和可变参数用法.分享给大家供大家参考.具体如下: 刚学用Python的时候,特别是看一些库的源码时,经常会看到func(*args, **kwargs)这样的函数定义,这个*和**让人有点费解.其实只要把函数参数定义搞清楚了,就不难理解了. 先说说函数定义,我们都知道,下面的代码定义了一个函数funcA ? 1 2 def funcA(): pass 显然,函数funcA没有参数(同时啥也不干:D). 下面这个函数funcB就有两个参数了, ? 1

python通过函数属性实现全局变量的方法

  本文实例讲述了python通过函数属性实现全局变量的方法.分享给大家供大家参考.具体分析如下: python的函数可以定义属性,而且是全局的,这个非常好用,例如用于数字累加,你不用专门去定义一个全局变量,使用函数的属性即可. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 def add(x=1): try: add.sum += x except AttributeError: add.sum = x return add.sum

Python查找函数f(x)=0根的解决方法

  这篇文章主要介绍了Python查找函数f(x)=0根的解决方法,涉及Python数学运算函数求解的相关技巧,需要的朋友可以参考下 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ''' root = ridder(f,a,b,tol=1.0e-9). Finds a root of f(x) = 0 with Ridder's method. The root m

Object-C---&amp;gt;Swift之(七)嵌套函数与闭包

嵌套函数 函数分为全局函数和局部函数,前面已经介绍了全局函数,下面介绍下局部函数,定义在函数体内部的函数可以成为嵌套函数. 注意:嵌套函数对外是隐蔽的,只能在其封闭函数内有效,嵌套函数只能在其封闭函数内有效,其封闭函数也可以返回嵌套函数,以便于程序在其他作用域内使用嵌套函数. func Math(#type:String)->(Int)->Int { func square(val:Int)->Int { return val*val } func cube(val:Int)->I