在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
在C#中没有独立的函数存在,只有类的(动态或静态)方法这一概念,它指的是类中用于执行计算或其它行为的成员。在Python中,你可以使用类似C#的方式定义类的动态或静态成员方法,因为它与C#一样支持完全的面向对象编程。你也可以用过程式编程的方式来编写Python程序,这时Python中的函数与类可以没有任何关系,类似C语言定义和使用函数的方式。此外,Python还支持函数式编程,虽然它对函数式编程的支持不如LISP等语言那样完备,但适当使用还是可以提高我们工作的效率。 本章主要介绍在过程编程模式下Python中函数的定义和使用方法,关于在面向对象编程中如何使用函数,我们将在下一章再讨论。此外,我还会简要介绍Python中的函数编程功能。 3.1 函数的定义函数定义是最基本的行为抽象代码,也是软件复用最初级的方式。Python中函数的定义语句由def关键字、函数名、括号、参数(可选)及冒号:组成。下面是几个简单的函数定义语句:
可能你已经注意到了,Python定义函数的时候并没有约束参数的类型,它以最简单的形式支持了泛型编程。你可以输入任意类型的数据作为参数,只要这些类型支持函数内部的操作(当然必要时需要在函数内部做一些类型判断、异常处理之类的工作)。 3.2 函数的参数3.2.1 C#与Python在函数参数定义方面的差别C#中方法的参数有四种类型: (1) 值参数不含任何修饰符 Python中函数参数的形式也有四种类型: (1) f(arg1,arg2,...) 这是最常用的函数定义方式 可以看出,Python函数参数定义与C#相比,最大的两个区别是支持关键字参数和字典参数。
3.29更新:根据JeffreyZhao提示,C# 4.0 已经支持命名参数(即关键字参数)和可选参数(即参数默认值),详情可见生鱼片blog上的:《C#4.0新特性:可选参数,命名参数,Dynamic》。在此向两位致谢。
3.2.2 关键字参数关键字参数可以使我们调用含有很多参数、同时一些参数具有默认值的Python函数变得更简单,也是Python实现函数重载的一种重要手段(到类与对象部分再详细说这个问题)。下面的例子说明了如何定义和调用含关键字参数的函数(引自Guido van Rossum《Python入门》,包括后面的几个例子):
3.2.3 字典参数如果形参表中有一个形为**name的形参,在调用时这个形参可以接收一个字典,字典中包含所有不与任何形参匹配的关键字参数。例如下面的函数:
client : John Cleese 3.2.4 函数参数调用的顺序调用Python函数时,参数书写的顺序分别为:非关键字参数,关键字参数,元组参数,字典参数。请记住以下几点规则: * 通过位置分配非关键字参数 一般说来,实参表中非关键字参数在前,关键字参数在后,关键字名字必须是形参名字。形参有没有缺省值都可以用关键字参数的形式调用。每一形参至多只能对应一个实参,因此,已经由位置参数传入值的形参就不能在同一调用中再作为关键字参数。 总之,由于Python的函数参数定义和调用方式太灵活了,所以一开始容易把人搞晕。不过可以慢慢来,你会越来越发现Python的简便所在。 3.3 函数文档在C#,可以使用文档XML标记对函数进行注释,这样在VS等IDE中,输入函数名后就会提示函数的功能、参数及返回值等的说明,方便函数的调用者。在Python中,也有类似的功能,即文档字符串(Docstrings)。但Python的文档字符串不像C#中的文档XML标记那么丰富,基本等同于C#中的<summary>标记,下面让我们一起来通过一个例子了解一下(引自《简明Python教程》):
输出 $ python func_doc.py The two values must be integers. 在上述函数中,第一个逻辑行的字符串是这个函数的文档字符串。文档字符串的惯例是一个多行字符串,它的首行以大写字母开始,句号结尾。第二行是空行,从第三行开始是详细的描述,描述对象的调用方法、参数说明、返回值等具体信息。 可以使用__doc__(注意双下划线)调用printMax函数的文档字符串属性(属于函数的名称,请记住Python把每一样东西都作为对象,包括这个函数)。它等同于用Python的内建函数help()读取函数的说明。很多Python的IDE也依赖于函数的文档字符串进行代码的智能提示,因此我们在编写函数时应养成编写文档字符串的习惯。 3.4 函数编程Python中加入了一些在函数编程语言和Lisp中常见的功能,如匿名函数、高阶函数及列表内涵等,关于最后一个问题我在《2 运算符、表达式和流程控制》已经介绍过了,本章只介绍匿名函数和高阶函数。 3.4.1 匿名函数lambda函数是匿名函数,用来定义没有名字的函数对象。在Python 中,lambda只能包含表达式:lambda arg1, arg2 ... : expression。lambda 关键字后就是逗号分隔的形参列表,冒号后面是一个表达式,表达式求值的结果为lambda的返回值。 虽然lambda的滥用会严重影响代码可读性,不过在适当的时候使用一下lambda 来减少键盘的敲击还是有其实际意义的,比如做排序的时候,使用data.sort(key=lambda o:o.year)显然比
要方便许多。(引自《可爱的Python》)
3.29更新:根据JeffreyZhao提示,重新整理C#中匿名函数的内容(本部分主要参考MSDN,见http://msdn.microsoft.com/zh-cn/library/bb882516.aspx): 在C#中也有匿名函数功能。在 C# 1.0 中,通过使用在代码中其他位置定义的方法显式初始化委托来创建委托的实例。C# 2.0引入了匿名方法的概念,作为一种编写可在委托调用中执行的未命名内联语句块的方式。C# 3.0 引入了 Lambda表达式,这种表达式与匿名方法的概念类似,但更具表现力并且更简练。这两个功能统称为“匿名函数”。通常,针对 .NET 3.5 及更高版本的应用程序应使用 Lambda 表达式。 Lambda 表达式可以包含表达式和语句,并且可用于创建委托或表达式目录树类型。所有 Lambda 表达式都使用 Lambda 运算符 =>, 运算符的左边是输入参数(如果有),右边包含表达式或语句块。可以将此表达式分配给委托类型,如下所示:
3.4.2 高阶函数高阶函数(High Order)是函数式编程的基础,常用的高阶函数有: Python通过map、filter、reduce三个内置函数来实现上述三类高阶函数功能。本文不对这三个函数的用法进行详细介绍,仅给出它们使用的示例代码(引自《Python的map、filter、reduce函数》),请细细体会:
运行结果如下: 3.29更新:根据JeffreyZhao提示,C#可以用委托实现函数编程的大部分功能。不过说实话我没这么用过,因为是接触了Python后才有的函数编程概念,以前用C#写程序就压根没有函数编程思想,虽然知道"委托允许将方法作为参数进行传递"。但具体细节估计各位C#高手比我要清楚得多,我就不乱写了。
3.5 小结本章讨论了Python中函数的定义和使用方法,要点如下: (1) Python用def关键字、函数名、括号、参数(可选)及冒号定义函数(要记得函数体缩进呀),函数可以有0、1或多个返回值;
进一步阅读的参考:[1] 本章内容较多的参考了Python之父Guido van Rossum的《Python入门》以及国内的一本经典教程《可爱的Python》,再次向大家推荐这两本书,在此对作者及译者致谢。 [2] 限于篇幅和深度,关于Python函数中的一些重要主题没有讨论,例如作用域、函数嵌套、递归等,我的观点是先不要把事情弄得太复杂,慢慢来总是不错的。如果你已学会了本章的内容,推荐你进一步阅读《深入Python》,这本书中对很多主题的讨论都是(我看多的书中)最深入的。
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论