函数(1)
函数(1)
函数,对于⼈类来讲,能够发展到这个数学思维层次,是⼀个飞跃。可以说,它的提出,直接加快了现代科技和社会的发展,不论是现代的任何科技门类,乃⾄于经济学、政治学、社会学等,都已经普遍使⽤函数。
下⾯⼀段来⾃维基百科(在本教程中,⼤量的定义来⾃维基百科,因为它真的很百科):函数这个数学名词是莱布尼兹在1694年开始使⽤的,以描述曲线的⼀个相关量,如曲线的斜率或者曲线上的某⼀点。莱布尼兹所指的函数现在被称作可导函数,数学家之外的普通⼈⼀般接触到的函数即属此类。对于可导函数可以讨论它的极限和导数。此两者描述了函数输出值的变化同输⼊值变化的关系,是微积分学的基础。
中⽂的“函数”⼀词由清朝数学家李善兰译出。其《代数学》书中解释:“凡此變數中函(包含)彼變數者,則此為彼之函數”。
函数,从简单到复杂,各式各样。前⾯提供的维基百科中的函数词条,⾥⾯可以做⼀
个概览。但不管什么样⼦的函数,都可以⽤下图概括:
有初中数学⽔平都能理解⼀个⼤概了。这⾥不赘述。
本讲重点说明⽤python 怎么来构造⼀个函数。
深⼊理解函数
在中学数学中,可以⽤这样的⽅式定义函数:y=4x+3,这就是⼀个⼀次函数,当然,也可以写成:f(x)=4x+3。其中x 是变量,它可以代表任何数。
当x=2时,代⼊到上⾯的函数表达式:
f(2) = 4*2+3 = 11
所以:f(2) = 11
但是,这并不是函数的全部,在函数中,其实变量并没有规定只能是⼀个数,它可以是馒头、还可是苹果,不知道读者是否对函数有这个层次的理解。请继续阅读即更深
刻
变量不仅仅是数
变量x 只能是任意数吗?其实,⼀个函数,就是⼀个对应关系。看官尝试着将上⾯表达式的x 理解为馅饼,4x+3,就是4个馅饼在加上3(⼀般来讲,单位是统⼀的,但你⾮让它不统⼀,也⽆妨),这个结果对应着另外⼀个东西,那个东西⽐如说是iphone 。或者说可以理解为4个馅饼加3就对应⼀个iphone 。这就是所谓映射关系。
所以,x ,不仅仅是数,可以是你认为的任何东西。
变量本质——占位符
函数中为什么变量⽤x ?这是⼀个有趣的问题,⾃⼰google ⼀下,看能不能找到答案。我也不清楚原因。不过,我清楚地知道,变量可以⽤x ,也可以⽤别的符号,⽐如y,z,k,i,j... ,甚⾄⽤alpha,beta 这样的字母组合也可以。
变量在本质上就是⼀个占位符。这是⼀针见⾎的理解。什么是占位符?就是先把那个位置⽤变量占上,表⽰这⾥有⼀个东西,⾄于这个位置放什么东西,以后再说,反正先⽤⼀个符号占着这个位置(占位符)。
其实在⾼级语⾔编程中,变量⽐我们在初中数学中学习的要复杂。但是,先不管那些,复杂东西放在以后再说了。现在,就按照初中数学的⽔平来研究python 中的变量。
通常使⼩写字母来命名python 中的变量,也可以在其中加上下划线什么的,表⽰区别。
⽐如:alpha,x,j,p_beta,这些都可以做为python 的变量。
建⽴简单函数
>>> a = 2
>>> y = 3 * a + 2
>>> y
8
这种⽅式建⽴的函数,跟在初中数学中学习的没有什么区别。当然,这种⽅式的函数,在编程实践中没有什么⽤途。
别急躁,你在输⼊a=3,然后输⼊y ,看看得到什么结果呢?
>>> a = 2
>>> y = 3 * a + 2
>>> y
8
>>> a = 3
>>> y
8
是不是很奇怪?为什么后⾯已经让a 等于3了,结果y 还是8。
还记得前⾯已经学习过的关于“变量赋值”的原理吗?a=2的含义是将2这个对象贴上了变量a 标签,经过计算,得到了8,之后变量y 引⽤了对象8。当变量a 引⽤的对象修改为3的时候,但是y 引⽤的对象还没有变,所以,还是8。再计算⼀次,y 的连接对象就变了:
>>> a = 3
>>> y
8
>>> y = 3 * a + 2
>>> y
11
特别注意,如果没有先 a = 2 ,就直接下函数表达式了,像这样,就会报错。
>>> y = 3 * a + 2
Traceback (most recent call last):
File "", line 1, in
NameError: name 'a' is not defined
注意看错误提⽰,a 是⼀个变量,提⽰中告诉我们这个变量没有定义。显然,如果函数中要使⽤某个变量,不得不提前定义出来。定义⽅法就是给这个变量赋值。
建⽴实⽤的函数
上⾯⽤命令⽅式建⽴函数,还不够“正规化”,那么就来写⼀个.py ⽂件吧。
例如下⾯的代码:
#!/usr/bin/env python
#coding:utf-8
def add_function(a, b):
c = a + b
print c
if __name__ == "__main__":
add_function(2, 3)
然后将⽂件保存,我把她命名为20101.py ,你根据⾃⼰的喜好取个名字。
然后我就进⼊到那个⽂件夹,运⾏这个⽂件,出现下⾯的结果,如图:
你运⾏的结果是什么?如果没有得到上⾯的结果,你就⾮常认真地检查代码,是否跟我写的完全⼀样,注意,包括冒号和空格,都得⼀样。冒号和空格很重要。下⾯开始庖丁解⽜:
def add_function(a, b): 这⾥是函数的开始。在声明要建⽴⼀个函数的时候,⼀定要使⽤def (def 就是英⽂define 的前三个字母),意思就是告知计算机,这⾥要声明⼀个函数;add_function是这个函数名称,取名字是有讲究的,就好⽐你的名字⼀样。在python 中取名字的讲究就是要有⼀定意义,能够从名字中看出这个函数是⽤来⼲什么的。从add_function这个名字中,是不是看出她是⽤来计算加法的呢(严格地说,是把两个对象“相加”,这⾥相加的含义是⽐较宽泛的,包括对字符串等相加)?(a,b)这个括号⾥⾯的是这个函数的参数,也就是函数变量。冒号,这个冒号⾮常⾮常重要,如果少了,就报错了。冒号的意思就是下⾯好开始真正的函数内容了。c = a + b 特别注意,这⼀⾏⽐上⼀⾏要缩进四个空格。这是python 的规定,要牢记,不可丢掉,丢了就报错。然后这句话就是将两个参数(变量) 相加,结果赋值与另外⼀个变量c 。print c 还是提醒看官注意,缩进四个空格。将得到的结果c 的值打印出来。
if __name__ == "__main__": 这句话先照抄,不解释,因为在有说明,不知道你是不是认真阅读了。注意就是不缩进了。add_function(2,3) 这才是真正调⽤前⾯建⽴的函数,并且传⼊两个参数:a=2,b=3。仔细观察传⼊参数的⽅法,就是把2放在a 那个位置,3放在b 那个位置(所以说,变量就是占位符).
解⽜完毕,做个总结:
定义函数的格式为:
def 函数名(参数1,参数2,... ,参数n) :
函数体(语句块)
是不是样式很简单呢?⼏点说明:
函数名的命名规则要符合python 中的命名要求。⼀般⽤⼩写字母和单下划线、数字等组合def 是定义函数的关键词,这个简写来⾃英⽂单词define 函数名后⾯是圆括号,括号⾥⾯,可以有参数列表,也可以没有参数千万不要忘记了括号后⾯的冒号函数体(语句块),相对于def 缩进,按照python 习惯,缩进四个空格
看简单例⼦,深⼊理解上⾯的要点:
>>> def name(): #定义⼀个⽆参数的函数,只是通过这个函数打印... print "qiwsir" #缩进4个空格
...
>>> name() #调⽤函数,打印结果
qiwsir
>>> def add(x,y): #定义⼀个⾮常简单的函数
... return x+y #缩进4个空格
...
>>> add(2,3) #通过函数,计算2+3
5
注意上⾯的add(x,y)函数,在这个函数中,没有特别规定参数x,y 的类型。其实,这句话本⾝就是错的,还记得在前⾯已经多次提到,在python 中,变量⽆类型,只有对象才有类型,这句话应该说成:x,y 并没有严格规定其所引⽤的对象类型。这是python 跟某些语⾔⽐如java 很⼤的区别,在有些语⾔中,需要在定义函数的时候告诉函数参数的数据类型。python 不⽤那样做。
为什么?列位不要忘记了,这⾥的所谓参数,跟前⾯说的变量,本质上是⼀回事。只有当⽤到该变量的时候,才建⽴变量与对象的对应关系,否则,关系不建⽴。⽽对象才有类型。那么,在add(x,y)函数中,x,y 在引⽤对象之前,是完全飘忽的,没有被贴在任何⼀个对象上,换句话说它们有可能引⽤任何对象,只要后⾯的运算许可,如果后⾯的运算不许可,则会报错。
>>> add("qiw","sir") #这⾥,x="qiw",y="sir",让函数计算x+y,也就是"qi 'qiwsir'
>>> add("qiwsir",4)
Traceback (most recent call last):
File "", line 1, in
File "", line 2, in add
TypeError: cannot concatenate 'str' and 'int' objects #仔细阅读报错信从实验结果中发现:x+y的意义完全取决于对象的类型。在python 中,将这种依赖关系,称之为多态。对于python 中的多态问题,以后还会遇到,这⾥仅仅以此例⼦显⽰⼀番。请看官要留⼼注意的:python 中为对象编写接⼜,⽽不是为数据类型。读者先留⼼⼀下这句话,或者记住它,随着学习的深⼊,会领悟到其真谛的。
此外,也可以将函数通过赋值语句,与某个变量建⽴引⽤关系:
>>> result = add(3,4)
>>> result
7
在这⾥,其实解释了函数的⼀个秘密。add(x,y)在被运⾏之前,计算机内是不存在的,直到代码运⾏到这⾥的时候,在计算机中,就建⽴起来了⼀个对象,这就如同前⾯所学习过的字符串、列表等类型的对象⼀样,运⾏add(x,y)之后,也建⽴了⼀个add(x,y)的对象,这个对象与变量result 可以建⽴引⽤关系,并且add(x,y)将运算结果返回。于是,通过result 就可以查看运算结果。
如果看官上⾯⼀段,感觉有点吃⼒或者晕乎,也不要紧,那就再读⼀边。是在搞不明
⽩,就不要搞了。随着学习的深⼊,它会被明⽩的。
关于命名
到现在为⽌,我们已经接触过变量的命名、函数的命名问题。似乎已经到了将命名问题进⾏总结的时候了。
在某国,向来重视“名”,所谓“名不正⾔不顺”,取名字或者给什么东西命名,常常是天⼤的事情,在很多时候就是为了那个“名”进⾏争⽃。
江湖上还有的⼤师,会通过某个⼈的名字来预测他/她的吉凶祸福等。看来名字这玩意太重要了。“名不正,⾔不顺”,歪解:名字不正规化,就不顺。这是歪解,希望不要影响看官正确理解。不知道⼤师们是不是能够通过外国⼈名字预测外国⼈⼤的吉凶祸福呢?⽐如Aoi sola,这个⼈怎么样?不管怎样,某国⼈是很在意名字的,旁边有个国家似乎就不在乎,⽐如⼭本五⼗六,在名字中间出现数字,就好像我们的张三李四王⼆⿇⼦那样随便,不过,有⼀种说法,“⼭本五⼗六”的意思是这个⼈出⽣时,他⽗亲56岁,看来跟张三还不⼀样的。
python 也很在乎名字问题,其实,所有⾼级语⾔对名字都有要求。为什么呢?因为如果命名乱了,计算机就有点不知所措了。看python 对命名的⼀般要求。
⽂件名:全⼩写, 可使⽤下划线
函数名:⼩写,可以⽤下划线风格单词以增加可读性。如:myfunction ,my_example_function。注意:混合⼤⼩写仅被允许⽤于这种风格已经占据优势的时候,以便保持向后兼容。有的⼈,喜欢⽤这样的命名风格:myFunction ,除了第⼀个单词⾸字母外,后⾯的单词⾸字母⼤写。这也是可以的,因为在某些语⾔中就习惯如此。
函数的参数:如果⼀个函数的参数名称和保留的关键字(所谓保留关键字,就是python 语⾔已经占⽤的名称,通常被⽤来做为已经有的函数等的命名了,你如果还⽤,就不⾏了。) 冲突,通常使⽤⼀个后缀下划线好于使⽤缩写或奇怪的拼写。
变量:变量名全部⼩写,由下划线连接各个单词。如color = WHITE,this_is_a_variable = 1。
其实,关于命名的问题,还有不少争论呢?最典型的是所谓匈⽛利命名法、驼峰命名等。如果你喜欢,可以google ⼀下。以下内容供参考:,如果看官的英⽂可以,⼀定要阅读。如果英⽂稍逊,可以来阅读, 不⽤梯⼦能⾏吗?看你命了。
调⽤函数
前⾯的例⼦中已经有了⼀些关于调⽤的问题,为了深⼊理解,把这个问题单独拿出来看看。
为什么要写函数?从理论上说,不⽤函数,也能够编程,我们在前⾯已经写了程序,就没有写函数,当然,⽤python 的内建函数姑且不算了。现在之所以使⽤函数,主要是:
1. 降低编程的难度,通常将⼀个复杂的⼤问题分解成⼀系列更简单的⼩问题,然后将⼩问题继续划分成更⼩的问题,当问题细化为⾜够简单时,就可以分⽽治之。为了实现这种分⽽治之的设想,就要通过编写函数,将各个⼩问题逐个击破,再集合起来,解决⼤的问题。(看官请注意,分⽽治之的思想是编程的⼀个重要思想,所谓“分治”⽅法也。)2. 代码重(chong,⼆声⾳) ⽤。在编程的过程中,⽐较忌讳同样⼀段代码不断的重复,所以,可以定义⼀个函数,在程序的多个位置使⽤,也可以⽤于多个程序。当然,后⾯我们还会讲到“模块”(此前也涉及到了,就是import 导⼊的那个东西),还可以把函数放到⼀个模块中供其他程序员使⽤。也可以使⽤其他程序员定义的函数(⽐如import ...,前⾯已经⽤到了,就是应⽤了别⼈——创造python 的⼈——写好的函数)。这就避免了重复劳动,提供了⼯作效率。这样看来,函数还是很必要的了。废话少说,那就看函数怎么调⽤吧。以add(x,y)为例,前⾯已经演⽰了基本调⽤⽅式,此外,还可以这样:
>>> def add(x,y): #为了能够更明了显示参数赋值特点,重写此函数... print "x=",x #分别打印参数赋值结果
... print "y=",y
... return x+y
...
>>> add(10,3) #x=10,y=3
x= 10
y= 3
13
>>> add(3,10) #x=3,y=10
x= 3
y= 10
13
所谓调⽤,最关键是要弄清楚如何给函数的参数赋值。这⾥就是按照参数次序赋值,根据参数的位置,值与之对应。
>>> add(x=10,y=3) #同上
x= 10
y= 3
13
还可以直接把赋值语句写到⾥⾯,就明确了参数和对象的关系。当然,这时候顺序就不重要了,也可以这样
>>> add(y=10,x=3) #x=3,y=10
x= 3
y= 10
13
在定义函数的时候,参数可以像前⾯那样,等待被赋值,也可以定义的时候就赋给⼀个默认值。例如:
>>> def times(x,y=2): #y的默认值为2
... print "x=",x
... print "y=",y
... return x*y
...
>>> times(3) #x=3,y=2
x= 3
y= 2
6
>>> times(x=3) #同上
x= 3
y= 2
6
如果不给那个有默认值的参数传递值(赋值的另外⼀种说法),那么它就是⽤默认的值。如果给它传⼀个,它就采⽤新赋给它的值。如下:
>>> times(3,4) #x=3,y=4,y的值不再是2
x= 3
y= 4
12
>>> times("qiwsir") #再次体现了多态特点
x= qiwsir
y= 2
'qiwsirqiwsir'
给列位看官提⼀个思考题,请在闲暇之余⽤python 完成:写两个数的加、减、乘、除的函数,然后⽤这些函数,完成简单的计算。
注意事项
下⾯的若⼲条,是常见编写代码的注意事项:
1. 别忘了冒号。⼀定要记住符合语句⾸⾏末尾输⼊“:”(if,while,for 等的第⼀⾏)2. 从第⼀⾏开始。要确定顶层(⽆嵌套)程序代码从第⼀⾏开始。3. 空⽩⾏在交互模式提⽰符下很重要。模块⽂件中符合语句内的空⽩⾏常被忽视。但是,当你在交互模式提⽰符下输⼊代码时,空⽩⾏则是会结束语句。4. 缩进要⼀致。避免在块缩进中混合制表符和空格。5. 使⽤简洁的for 循环,⽽不是while or range.相⽐,for 循环更易写,运⾏起来也更快6. 要注意赋值语句中的可变对象。7. 不要期待在原处修改的函数会返回结果, ⽐如list.append(),这在可修改的对象中特别注意8. 调⽤函数是,函数名后⾯⼀定要跟随着括号,有时候括号⾥⾯就是空空的,有
时候⾥⾯放参数。9. 不要在导⼊和重载中使⽤扩展名或路径。
以上各点如果有不理解的,也不要紧,在以后编程中,时不时地回来复习⼀下,能不断领悟其内涵。
W3Cschool (www.w3cschool.cn )最⼤的技术知识分享与学习平台此篇内容来⾃于w3cschool.cn ⽹站⽤户上传并发布。