`

关于动态函数的一点理解 — 《Dive Into Python》第十七章学习笔记

阅读更多

关于动态函数的一点理解  -  《Dive Into Python》第十七章学习笔记

平时的笔记都记录在书上,但这次的笔记太长,我准备打印出来用胶水粘到书上。

0. 写在前面

 

如果你有机会看到这一章,你会发现他的标题是“动态函数”。也就是说:“本章要讲述面向函数的编程”这一概念。如果你想学习python有没有看过这一章,我强烈推荐你去看。

Dive Into Python

先说句题外话,Java中函数只是函数,而不是数据,也因此我们无法使用Java语言进行面向函数的编程。反过来说:要想进行面向函数的变成,首先必须要具备的一个思想就是将函数视为数据。因为既然我们要动态函数,就不能像java一样仅仅去声明他,调用他,我们还要操纵他(我们通常管我们操纵的东西叫做数据)。

话题转来,开始对这样章的一个笔记(或者我自己的评论吧)

首先要说的是,关于函数我们需要了解的全部东西也无非就是:“我们可以怎样定义他?”和“你可以怎么持有(或者叫使用)他?”。下面我们就具体看一下python在这两个方面是如何动起来的。

 

1. 关于函数的持有(或者叫使用)方式

要面向函数编程,语言必须支持这样一个东西,我们可以把它当做函数来调用。而他也可以一会儿代表这个函数,一会儿代表那个函数。

C里面这个东西叫做函数指针。C++中你也可以使用”函数对象”的概念,重载运算符:()。
Java里面则没有类似的东西。
而在python中他就是一个函数对象,一个切切实实的对象。
包括python的很多动态语言都是这么做的,他们都已经将函数视为了数据,而不是Java中的与数据相区别的函数了。

2. 关于函数的定义(或者叫声明)方式。

现在我们已经有了“时而可以指向这个函数,时而可以指向那个函数”的东西。显然他在动态方面已经已经有了进步,然而这只是函数的持有方面,持有的手段已经动了起来,下面让我们看一看函数的定义方面。我认为这一部分相比前一部分更为精彩,虽然他们同样重要(好废的话。。。)

Java中,如果我们写下这样的一行代码:
        String str = "abc";


那么我们说,我们使用了字符串字面量"abc"来定义str,这个字面量是编译器直接就能懂的,在编译的时候就已经确定了的。当然,在java中我们要产生一个字符串的方法完全不局限于“字面量”,我们完全可以更动态得生成他。比如很多对象都有能够得到String的方法,最常见的恐怕就是toString()方法了,这种方法还有很多,他们都能动态得生成字符串。

然而Java中的函数呢? 很遗憾,如果和String做一个类比,那么我们可以说:在java中你只能使用“字面量函数”。也就是说如果你想拥有一个函数你就必须老老实实得在编译之前将它定义好。你没有办法得到没有被一字不差得敲入source文件中的任何函数(当然,使用面向切面的技术,使用动态代理,或者操作Java字节码文件除外)。这便是Java的函数不够动态得地方。

讨论了这么多java的函数,现在让我们看看python的函数吧。

 

2.1  lambda函数。

想让我们的代码更简洁吗?不想通篇充斥着只有一行的函数吗?
那么lambda正是我们的选择,他允许我们定义匿名函数,然后再将它赋值或者传递给别人。

是的,传统的函数(相当于字符串字面量的那种)要求必须被规规矩矩的,一板一眼的定义。然而我们要的是动态函数,Lambda函数正式为了改变这种不够动态的局面而生。他允许我们在任何我们想要一个函数的时候,任何我们想要一个函数的地方,去定义一个函数,然后传递或者使用他。(这些时空包括任何两行代码之间,或者一个表达式的内部等等。)

这的确使函数的概念充满了生机,然而这并不是最精彩的部分。当lambda函数遇见闭包的时候,他们将碰撞出更精彩得火花。

2.2  闭包(closure)


在开始闭包之前,让我们先做个停顿,回头看一下我们现在在哪儿。
得益于lambda函数,我们能够在任何地方,任何时候,定义我们自己的函数(插一句, 这个函数会是我们想要的吗? 我们想要的函数到底是一个什么样子呢? 或者还有别的样子吗?)。这是一件很美好的事情。我们现在到得地方就是这里,让我们站在这里想象一下,还有没有更美好的事情呢?

答案当然是“永远有”。如果我们能依赖当前的上下文来定义我们函数就更好了。因为这样的函数势必将更加有用。实际中的函数绝不会像计算a+b之和那么简单。如果定义函数的时候可以依赖上下文,那么我们便有了更强大的威力,去更灵活得定义函数。因为这样一来,我们能够容易得做到下面这些事情:
a. 在当前环境中的叫做language的变量的值是en,还是ch的时候,我所定义的函数表现会有所不同(处理多国语言)。
b. 比如当前环境中的一个叫rules变量不同时,返回将运用不同规则的函数等等。

让我们回到正题,上面所有需求的解决办法就是闭包:
所谓闭包(也有的叫闭合)是指:在一个动态函数中应用外部参数值的技术。

他还有其他的一些解释:所谓“闭包”指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

不管他的定义如何,他的目的都是“让我们能够将外部变量作为常量来定义我们的函数”。 典型的应用是我们会定义这样一写函数,他接受一些参数,而这些函数本身会根据这些参数的不同,构造出并返回不同的函数(他们是当前上下文所需要的函数,或者说是对当前上下文而言正确的函数)以供其他人使用。

 

3. 总结

本书的这一章以“将英文单词复数化的函数”为例,一共展示了六个版本。第一个版本是类似Java风格“传统方式”,重这一版本开始,一步一步得抽象,一步一步得去除重复,分离变化,直到最后使用动态函数的方式解决这一问题。

作者以这种方式告诉了读者:如何使用动态函数编写,更高抽象层次,更少重复,更少耦合,也更为可读得代码。

是的,动态函数并不是我们的目的,我们的目的依然是上面这些。为了他们我们要不遗余力。

 


4. 连接

[Dive Into Python]

 

 

 

 

 

 

 

 

 

 

 

 

 

分享到:
评论
1 楼 wjason 2009-08-10  
昨天看JavaScript,那里面管lambda叫函数直接量。

要是那个兄弟看到了就不好意思了,不对上面的帖子做更新了。

相关推荐

Global site tag (gtag.js) - Google Analytics