Inner Functions - What Are They Good For?
Referece: https://realpython.com/blog/python/inner-functions-what-are-they-good-for/
Let’s look at three common reasons for writing inner functions.
Remember: In Python, a function is a “first-class” citizen, meaning they are on par with any other object (i.e., integers, strings, lists, modules, etc.). You can dynamically create or destroy them, pass them to other functions, return them as values, and so forth.
This tutorial utilizes Python version 3.4.1.
1. Encapsulation
You use inner functions to protect them from anything happening outside of the function, meaning that they are hidden from the global scope.
Here’s a simple example that highlights that concept:
|
Try calling the inner_increment() function:
|
Now comment out the inner_increment call and uncomment the outer function call, outer(10), passing in 10 as the argument:
|
Keep in mind that this is just an example. Although this code does achieve the desired result, it’s probably better to make the
inner_increment()function a top-level “private” function using a leading underscore:_inner_increment().
The following recursive example is a slightly better use case for a nested function:
|
Test this out as well. One main advantage of using this design pattern is that by performing all argument checking in the outer function, you can safely skip error checking altogether in the inner function.
For a more detailed discussion of recursion see, Problem Solving with Algorithms and Data Structures.
2. Keepin’ it DRY
Perhaps you have a giant function that performs the same chunk of code in numerous places. For example, you might write a function which processes a file, and you want to accept either an open file object or a file name:
|
Again, it is common to just make
do_stuff()a private top-level function, but if you want to hide it away as an internal function, you can.
How about a practical example?
Let’s say you want to know the number of WiFi hot spots in New York City. And yes the city has the raw data to tell us: datasource. Visit the site and download the CSV.
|
Run the function:
|
3. Closures and Factory Functions
Now we come to the most important reason to use inner functions. All of the inner function examples we’ve seen so far have been ordinary functions that merely happened to be nested inside another function. In other words, we could have defined these functions in another way (as discussed); there is no specific reason for why they should be nested.
But when it comes to closure, that is not the case: You must utilize nested functions.
What’s a closure?
A closure simply causes the inner function to remember the state of its environment when called. Beginners often think that a closure is the inner function, when it’s really caused by the inner function. The closure “closes” the local variable on the stack and this stays around after the the stack creation has finished executing.
An example
|
What’s happening here?
- The ‘generate_power()’ function is a factory function – which simply means that it creates a new function each time it is called and then returns the newly created function. Thus,
raise_twoandraise_threeare the newly created functions. - What does this new, inner function do? It takes a single argument,
power, and returnsnumber**power. Where does the inner function get the value of
numberfrom? This is where the closure comes into play:nth_power()gets the value ofpowerfrom the outer function, the factory function. Let’s step through this process:- Call the outer function:
generate_power(2) - Build the
nth_power()function which takes a single argumentpower - Take a snapshot of the state of
nth_power()which includespower=2 - Pass that snapshot into the
generate_power()function - Return the
nth_power()function
Put another way, the closure functions to “initialize” the number bar in the
nth_power()function and then returns it. Now, whenever you call that newly returned function, it will always see its own private snapshot that includespower=2.- Call the outer function:
Real World
How about a real world example?
|
This is a simplified function to check if a certain user has the correct permissions to access a certain page. You could easily modify this to grab the user in session to check if they have the correct credentials to access a certain route. Instead of checking if the user is just equal to ‘Admin’, you could query the database to check the permission then return the correct view depending on whether the credentials are correct or not.
Conclusion
The use of closures and factory functions is the most common, and powerful, use for inner functions. In most cases, when you see a decorated function, the decorator is a factory function which takes a function as argument, and returns a new function which includes the old function inside the closure. Stop. Take a deep breath. Grab a coffee. Read that again.
Put another way, a decorator is just syntactic sugar for implementing the process outlined in the generate_power() example.
I’ll leave you with an example:
|
If your code editor allows it, view the generate_power(exponent) and generate_power(number)functions side-by-side to illustrate the concepts discussed. (Sublime Text has Column View, for example).
If you have not coded the two functions, open the code editor and start coding. For new programmers, coding is a hands on activity, like riding a bike you just have to do it – and do it solo. So back to the task at hand. After you typed the code, you can now clearly see that the code is similar in that it produces the same results but there are differences. For those who have never used decorators, noting these differences will be the first step in understanding them if you venture down that path.
If you’d like to know more about this syntax and decorators in general, check out our Primer on Python Decorators. Comment below with questions.
Edits made by Derrick Kearney. Thank you!
Inner Functions - What Are They Good For?的更多相关文章
- asp.net MVC helper 和自定义函数@functions小结
asp.net Razor 视图具有.cshtml后缀,可以轻松的实现c#代码和html标签的切换,大大提升了我们的开发效率.但是Razor语法还是有一些棉花糖值得我们了解一下,可以更加强劲的提升我们 ...
- 【跟着子迟品 underscore】Array Functions 相关源码拾遗 & 小结
Why underscore 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. 阅读一些著名框架类库的源码,就好像和一个个大师对 ...
- 【跟着子迟品 underscore】Object Functions 相关源码拾遗 & 小结
Why underscore 最近开始看 underscore.js 源码,并将 underscore.js 源码解读 放在了我的 2016 计划中. 阅读一些著名框架类库的源码,就好像和一个个大师对 ...
- ajax的使用:(ajaxReturn[ajax的返回方法]),(eval返回字符串);分页;第三方类(page.class.php)如何载入;自动加载函数库(functions);session如何防止跳过登录访问(构造函数说明)
一.ajax例子:ajaxReturn("ok","eval")->thinkphp中ajax的返回值的方法,返回参数为ok,返回类型为eval(字符串) ...
- QM模块包含主数据(Master data)和功能(functions)
QM模块包含主数据(Master data)和功能(functions) QM主数据 QM主数据 1 Material Master MM01/MM02/MM50待测 物料主数据 2 Sa ...
- jQuery String Functions
In today's post, I have put together all jQuery String Functions. Well, I should say that these are ...
- 2-4. Using auto with Functions
在C++14中允许使用type deduction用于函数参数和函数返回值 Return Type Deduction in C++11 #include <iostream> using ...
- [Python] Pitfalls: About Default Parameter Values in Functions
Today an interesting bug (pitfall) is found when I was trying debug someone's code. There is a funct ...
- Kernel Functions for Machine Learning Applications
In recent years, Kernel methods have received major attention, particularly due to the increased pop ...
- Execution Order of Event Functions
In Unity scripting, there are a number of event functions that get executed in a predetermined order ...
随机推荐
- xfsdump命令使用
一:使用xfsdump备份和恢复xfs文件系统 首先了解一下xfsdump的备份级别有以下两种,默认为0(即完全备份) 0 完全备 ...
- codesmith连接postgresql修复bug
转:CodeSmith7代码生成器针对PostgreSQL数据库无法使用的Bug修复全过程 我自己又修改过,完整的PostgreSQLSchemaProvider.cs文件如下 using Npgsq ...
- 【Algorithm】希尔排序
一. 算法描述 希尔排序:将无序数组分割为若干个子序列,子序列不是逐段分割的,而是相隔特定的增量的子序列,对各个子序列进行插入排序:然后再选择一个更小的增量,再将数组分割为多个子序列进行排序..... ...
- c#之hello world
前言:公司开始转型java,作为javaer,负责其他同事转型,期间以为工作需要,需要简单学习c#语法,顾有此文,及其后续的一系列文章(c#里头的一些优点,可以为提升java的思想带来帮助) 1. 安 ...
- PHP中数字检测is_numeric与ctype_digit的区别介绍
PHP中的两个函数is_numeric和ctype_digit都是检测字符串是否是数字,但也存在一点区别 is_numeric:检测是否为数字字符串,可为负数和小数 ctype_digit:检测字符串 ...
- MySQL -- Innodb是如何处理自增列的
对于那些向带有自增列的表中插入行的语句,Innodb提供一种可配置的锁定机制,这种锁定机制可以显著提高SQL语句的可伸缩性和性能. Innodb中为了使用自增机制,自增列必须是索引的部份,从而可以使用 ...
- javascript控件(一):一个好用的日历
一.官网 http://www.my97.net/ 二.引用 <script src="bower_components/My97DatePicker/WdatePicker.js&q ...
- word中公式居中编号在最右端
1 显示标尺 2 设置居中制表符 3 在对应位置做标记 首先让公式居中 使用居中制表符在标尺的灰色地带标记位置,1)标记公式位置,鼠标左击 2)标记右边标号位置,注意和右边留有一定边距 4 公式左对齐 ...
- javascript 20个正则表达式
正则表达式,一个十分古老而又强大的文本处理工具,仅仅用一段非常简短的表达式语句,便能够快速实现一个非常复杂的业务逻辑.熟练地掌握正则表达式的话,能够使你的开发效率得到极大的提升. 正则表达式经常被用于 ...
- MySql(十七):MySql架构设计——高可用设计之思路及方案
前言: 数据库系统是一个应用系统的核心部分,要想系统整体可用性得到保证,数据库系统就不能出现任何问题.对于一个企业级的系统来说,数据库系统的可用性尤为重要.数据库系统一旦出现问题无法提供服务,所有系统 ...