七、Python的函数编程(之一)

本文从高中生视角出发,详细介绍了Python函数编程的基础知识,包括函数的定义、调用、参数设置及返回值处理等内容,并探讨了变量作用域的概念。

七、Python的函数编程(之一)

----From a high schoolstudent's view to learn Python

 

关键字:

python 高中生学编程 MIT公开课视频Python函数编程 递归 递归函数 递归调用


一、为什么会引入函数

------------------------


在学习的初期阶段,我们写的程序都比较简单,功能比较单一,代码的行数也不会太多;那我们想一想,如果需要处理的应用越来越复杂,我们是不是顺着我们的思路,一直将我们的代码在一个地方不停地写下去呢?如果这样下去,会是什么结果呢?

你可以想一想,如果一部长篇小说,没有章节划分,甚至连段落都没有,拿到它进行阅读,会是怎样的阅读感受呢?

其实,我们编写代码,一方面实现代码的功能,另一方面还需要具有较好的可读性,便于维护、修改、和别人使用;所以,随着功能变得复杂,我们会将应用进行分割,简单化、模块化,就象买回来的组装玩具一样,函数(Function)就是这些玩具的各个部件。

我们在学习之初,都用到了print,print其实就是一个函数,只不过它是系统提供的一个函数,他可以被任何人在任何时候使用,来实现它的功能。


下面剪辑的视频还是来自MIT的公开课视频,比较详细的介绍了在编程中为何需要引入函数;

【这里插入视频】

 

为什么需要引入函数的视频


 

函数的实际应用讲解



二、函数的定义

---------------

1. 函数的定义


我们从一个例子开始,这是一个可以计算任意大小的斐波那契数列的函数:



1

2

3

4

5

6


def fib(n):   # write Fibonacci series up ton 

   """Print a Fibonacci series up ton.""" 

   a, b = 0, 1 

   while a <n: 

       printa, 

       a, b = b,a+b




在详细的介绍函数的定义之前,我们先看看这段代码:

line 1:定义函数

line2:还记得吗,这是一行注释,三引号(单引号效果一项)

line3:比较奇特,其实就是赋值语句,对于多个变量需要赋值时,可以按照这样的方式来写,看着比较简洁,按照等号前面的变量顺序,逐个将后面的值赋给变量,这里给变量赋的都是整数,其实任意类型都可以,如:

aa, bb, cc, dd = 1, 2.3, 1.3e2,“string”

line4:while循环语句,注意写这样的语句,不要忘记”:”

line5:这一句我们应该很熟了,但是注意a后面的”,”;这表示在print变量a之后,不换行,因为是循环,所以在下次执行这个print语句时,print的内容会跟在上一次print的后面,不会换行;但是,如果没有”,”那每次执行完print都会自动换行

line 6:在line3我们介绍了这是一种赋值的写法,这一句又深入了,赋值的内容是多个表达式

特别再次强调:注意缩进,本例有两层缩进


函数的定义:

要素一:关键字def

要素二:函数名,和变量名的规则差不多,但是一般好的编程风格是将函数名和它实现的功能变现出来

要素三:函数名后面有一对()

要素四:()中可以含有一个和多个参数,当然也可以没有参数

要素五:”:”

要素六:函数体必须缩进


2. 函数的调用


函数在定义了之后,我们只有进行调用,函数才能够执行,其实在使用print语句的时候,我们就是在“调用print函数“。

那如何调用我们在上面给出的示例呢?

...>>># Now call the function wejust defined: 

...fib(2000

0 1 1 2 3 5 8 13 21 34 55 89144 233 377 610 987 1597 

fib(2000)就是调用,在下面的一行,就是该函数的执行结果,显示了2000以下的斐波那契数列;因为我们在printa后面加了”,”,所以数列显示在一行,否则,这些数将一行一个竖着显示出来。


3. 关于函数的参数


函数的参数对我们初学者,是比较绕的(个人感觉),其实跟我们数学中的函数有异曲同工之处,数学中的函数如:

y=f(x)

y=f(x1,y1)

y=f(x1, x2, …, xn)

所以,我们可以这么理解:

函数的参数就相当于我们数学中函数的自变量。

函数可以没有参数,也可以有一个或多个参数。


还有一种特殊情况:

回想一下print的使用,我们可以:

print a

也可以:

print a, b, c, d, e

也就是说,参数的数量是可变的。

以上只是简单的概念性介绍,python在函数参数方面还有很多特点:


1) 缺省参数(default argumentvalues)


1

2

3

4

5

6


deffib(n=2000):    # writeFibonacci series up to n 

   """Print a Fibonacci series up ton.""" 

   a, b = 0, 1 

   while a <n: 

       printa, 

       a, b = b,a+b




这样定义的函数,我们在调用时,可以直接使用

>>>fib() 

0 1 1 2 3 5 8 13 21 34 55 89144 233 377 610 987 1597 

但是,如果不是缺省参数定义,这样调用系统会报错:

>>>fib()

Traceback (most recent calllast):

  File"<stdin>", line 1, in<module>

TypeError: fib() takes exactly1 argument (0 given)


2) 关键字参数(keywordarguments)


关键字参数是针对函数调用而进行设计的语法规则;

对于函数:

function_ex(arg1, arg2=”arg2”,arg3)

pass#关键字,用来占位

我们可以采用以下的几种方法来调用(我们假设参数的类型为string):

function_ex(“arg1”)

function_ex(arg1=”arg111”,“arg333”)

function_ex(”arg111”,arg3=“arg333”)

function_ex(arg3=”arg333”,arg1=”arg111”,arg2=”arg222”)


采用关键字参数可以不按照参数列表的实际顺序,但是尽量按照顺序来写,否则很容易引起错误


4. 函数的返回值


还是拿我们数学的函数来进行说明:

对于函数:

y=f(x)

y=f(x1,y1)

y=f(x1, x2, …, xn)

如果我们给定自变量值,肯定有一个y值对应,我们可以类似的认为,y就是函数的返回值。

将上面的fib函数稍作修改:


1

2

3

4

5

6

7

8

def fib2(n): # returnFibonacci series up to n 

   """Return a list containing the Fibonacciseries up to n.""" 

   result = [] 

   a, b = 0, 1 

   while a <n: 

      result.append(a)   # seebelow 

       a, b = b,a+b 

   return result



修改之处有:

line1:我们重新取了个名,现在函数名为fib2

line3:新增加了一个变量result,还记得吗,[]表示list类型,我们给result初始化成一个空得list,这一句实现了两个目的:一是隐含的说明了result是一个list类型的变量,二是对变量进行了初始化

line6:这句会比较难懂,list类型在前面的博客中已经有介绍,它包含有有很多的“方法(method)“,来实现各种不同的功能,如:append用来添加一个元素到list,pop可以将list的最后一个元素弹出等…,注意这种调用的写法。result.append(a)等同于result= result + [a]

line7:返回result


对于返回值,还需要强调:


要素一:

函数可以没有return语句,但在没有return时,返回值是None,这也是一个保留关键字;

>>>fib(0

>>>printfib(0

None


要素二:

return语句可以没有值,这种情况,也返回None


要素三:

正常情况,return value


下面是一段视频讲解

插入视频

 



三、变量的作用域

---------------------

我们在程序中会定义很多的变量,在引入了函数之后,变量的作用域(或者说变量的可使用范围)就需要仔细的考虑了。

在函数的外面定义的变量,在函数里可以使用吗?

在函数里定义的变量,在函数体之外还能够使用吗?

这些都是我们在这一节讨论的问题。


1、局部变量

简单的说,在函数体之内定义的变量,它的作用域就被限定在函数体内,如果在函数体外使用,就会报错

>>>def func_test01():

...    a1=10

...    print a1

... 

>>>func_test01()

10

>>>print a1

Traceback (most recent calllast):

  File"<stdin>", line 1, in<module>

NameError: name 'a1' is notdefined


2、全局变量

如上述,反之就是全局变量,看如下示例:

>>>a1=1

>>>def test_func():

...    print a1

...    print a2

... 

>>>a2=2

>>>test_func()

1

2

就算a2定义在函数的后面,在函数中也是可以使用的


3、强制为全局变量

如果在函数体内声明一个与全局变量一样名字的变量时,这时候,全局变量将被覆盖,如同声明了一个名字一样的局部变量。



1

2

3

4

5

6

7

8

9

def foo():

   print "\ncalling foo()..."

   bar = 200

   print "in foo(), bar is", bar


bar = 100

print "in __main__, bar is",bar

foo()

print "\nin __main__, bar is(still)", bar



得出的输出结果如下:

in __main__, bar is100

calling foo()...

in foo(), bar is 200

in __main__, bar is (still)100


如何解决这种问题?这就需要使用global来强制将变量设为全局变量,改动如下:



1

2

3

4

5

6

7

8

9

10

def foo():

   global bar

   print "\ncalling foo()..."

   bar = 200

   print "in foo(), bar is", bar


bar = 100

print "in __main__, bar is",bar

foo()

print "\nin __main__, bar is(still)", bar



得出的输出结果如下:

in __main__, bar is100

calling foo()...

in foo(), bar is 200

in __main__, bar is (still)200


这样的话,在调用函数之后,bar的值变被更改了。

我的更多文章:
  • (2013-10-06 22:57:35)
  • (2013-10-03 22:18:28)
  • (2013-10-02 22:15:46)
  • (2013-10-02 22:10:41)
  • (2013-09-23 23:31:49)
  • (2013-09-21 23:37:27)
  • (2013-09-21 23:32:54)
  • (2013-09-20 23:09:39)
  • (2013-09-19 16:53:58)
  • (2013-09-02 19:26:01)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值