我的Python入门笔记(13)

十章、函数(上)


If the implementation is hard to explain, it's a bad idea.——The Zen of Python


  要把程序分解成较小的部分,主要有三种方法。函数(function)就像是代码的积木,可以反复使用,利用对象(object),可以把程序中的各部分描述为自包含的单元。模块(module)就是包含程序各部分的单独文件。函数是组织好的,可以重复使用的,用来实现单一或者关联功能的代码段。函数可以提高应用的模块性,和代码的重复利用率。

一、函数的创建和调用

  1.创建一个函数

  创建函数也称为定义函数,可以理解为创建一个具有某种用途的工具。使用def关键字实现,其语法格式如下:

  def functionname([parameterlist]):

       [‘’’comments’’’]

       [functionbody]

  functionname:函数名称,在调用函数时使用

  paramenterlist:可选参数,用于指定向函数中传递的参数,如果有多个参数,各参数间使用逗号分隔,如果不指定,则表示该函数没有参数。在调用时,也不指定函数。

  comments:可选参数,表示为函数指定注释,注释的内容通常是说明该函数的功能、要传递的参数的作用等,可以为用户提供友好的提示和帮助内容。

  functionbody:可选参数,用于指定函数体,即该函数被调用后,要执行的功能代码,如果函数有返回值,可以使用return语句返回

  函数没有参数时,也必须保留一对空的小括号,否则会报错。在定义函数时,如果指定了”comments”参数,那么在调用函数时,输入函数的名称及左侧的小括号时,就会显示该函数的帮助信息。函数体”functionbody”和注释”comments”相对于def关键字必须保留一定的缩进。

  2.调用函数

  调用函数就是执行函数,如果想把创建的函数理解为创建一个某种用途的工具,那么函数调用就相当于使用该工具,其语法格式如下:

  functionname([paramentersvalue])

  functionname:函数名称,要调用的函数名称,必须是已经创建好的

  paramentersvalue:可选参数,用于指定各个参数的值,如果需要传递多个参数值,则各个参数值之间使用逗号分隔,如果该函数没有参数,则直接写一对小括号即可。

 1 def filterchar(string):
 2     """
 3     :param string:过滤危险字符(如傻逼),并将过滤后的结果输出
 4     :return: 没有返回值
 5     """
 6     import re
 7     pattern = r'(傻逼)|(沙雕网友)'
 8     sub=re.sub(pattern,'**',string)
 9     print(sub)
10 about='我是来自最右的沙雕,但不是傻逼'
11 filterchar(about)
12 输出:
13 我是来自最右的沙雕,但不是***

  3.pass空语句

  在Python中有一个pass语句,表示空语句,它不做任何事情,一般起到占位作用。例如,创建一个函数,但是我们暂时不知道该函数要实现什么功能,这时候就可以使用pass语句填充函数的主体,表示“以后会填上”,示例如下:

1 def dunc():
2     #pass

  在python3中,允许在可以使用表达式的任何地方使用...(3个连续的点号)来省略代码,由于省略号自身什么都不做,因此,可以当做是pass语句的一种替代方案。

1 def func():
2     ...

 二、参数传递

  在调用函数时,大多数情况下,主调函数和被调用函数之间有数据传递关系,这就是有参数的函数形式。函数参数的作用是传递数据给函数使用,函数利用接受的数据进行具体的操作处理。

  

  

  1.形参和实参

  在使用函数时,经常会用到形式参数(形参)和实际参数(实参)。形参和实参的区别。

  形式参数:在定义函数时,函数名后面的括号中的参数为“形式参数”,也称为形参。

  实际参数:在调用一个函数时,函数名后面的括号中的参数为“实际参数”,也就是将函数的调用者提供给函数的参数称为实际参数,也称之为实参。

  根据实参类型的不同,可以分为将实参的值传递给形参,和将实参的引用传递给形参两种情况。其中,当实参为不可变对象时,进行的是值传递;当实参为可变对象时,进行的是引用传递。实际上,值传递和引用传递的基本区别就是,进行值传递后,改变形参的值,实参的值不变;而进行引用传递后,改变形参的值,实参的值也一同改变。

  函数定义时参数列表中的参数就是形参,而函数调用时传递进来的参数就是实参。

  2.位置参数

  位置参数也称为必备参数,必须按照正确的顺序传到函数中,即调用时的数量和位置必须和定义时是一样的。

    1.数量必须与定义时一致

     在调用函数时,指定的实参数量必须与形参数量一致,否则将会抛出TypeError异常,提示缺少必要位置参数。例如:定义一个函数,该函数有三个参数,但在调用时值传递两个参数,则会提示报错。

    2.位置必须与定义时一致:

  在调用函数时,指定的实参位置必须与形参位置一致,否则将会产生以下两种结果:

    1.抛出TypeError异常,

    2.产生的结果与预期结果不一致(在调用函数时一定要确定好位置,否则容易产生bug,而且不容易被发现)

  3.关键字参数

  关键字参数是指使用形参的名字来确定输入的参数值。通过该方式指定实参时,不再需要与形参的位置一致,只要将参数名写正确即可。这样可以避免用户需要牢记参数位置的麻烦,使得函数的调用和参数的传递更加灵活方便.

  4.为参数设置默认值

       调用函数时,如果没有某个指定参数将抛出异常,即在定义函数时,直接指定形式参数的默认值。这样,当没有传入参数是,则直接使用定义函数时设置的默认值。其语法格式如下:

def functionname(…,[parameter1=defaultvalue]):
    [functionbody]

  functionname:函数名称,在调用函数时使用

  parameter1=defaultvalue:可选参数,用于指定向函数传递的参数,并且为该参数设置默认值为defaultvalue

  functionbody:可选参数,用于指定函数体,即该函数被调用后,要执行的功能代码

  在定义函数时,指定默认的形参必须在所有参数的最后,否则会产生语法错误。此外,在Python中,可以使用“函数名_defaults_”查看函数的默认值参数的当前值,其结果是一个元组。在使用可变对象作为函数参数的默认值时,多次调用可能会导致意料之外的情况。示例如下:

1 def demo(obj=[]): #定义函数并为参数obj指定默认值
2     print("obj的值:",obj)
3     obj.append(1)
4 demo()   #调用demo函数
5 输出:
6 obj的值: []
1 demo()   #在次调用
2 输出:
3 obj的值: []
4 obj的值: [1]

  这显然不是想要的结果,为防止出现这种情况,最好使用None作为可变对象的默认值,这时候还需要进行代码的检查。修改后如下:

 1 def demo(obj=None): #定义函数并为参数obj指定默认值
 2     if obj==None:
 3         obj= []
 4     print("obj的值:",obj)
 5     obj.append(1)
 6 demo()   #调用demo函数
 7 demo()   #在次调用
 8 输出:
 9 obj的值: []
10 obj的值: []

  定义函数时,为形式参数设置默认值要牢记:默认参数必须指向不可变对象。

   5.可变参数

  在Python中,还可以定义可变参数。可变参数也称为不定长参数,即传入函数中的实际参数可以是任意个,在定义可变参数时,主要有两种形式:一种是*parameter,另一种是**parameter。

  1.*parameter

  这种形式表示接收任意多个实际参数并将其放到一个元组中。例如,定义一个函数,让其可以接收任意多个实际参数。

 1 def lovenum(*num):
 2     print('\n我喜欢的数字有:',end=' ')
 3     for item in num:
 4         print(item,end=” ”)
 5 lovenum('220')
 6 lovenum('220','284','26')
 7 lovenum('220','284','1210','1184')
 8 输出:
 9 我喜欢的数字有:
10 220 
11 我喜欢的数字有:
12 220 284 26 
13 我喜欢的数字有:
14 220 284 1210 1184

  如果想使用一个已经存在的列表作为函数的可变参数,可以在列表的名称前加“*”

1 def lovenum(*num):
2     print('\n我喜欢的数字有:')
3     for item in num:
4         print(item,end=' ')
5 list1=[22,26,220,284]
6 lovenum(*list1)
7 输出:
8 我喜欢的数字有:
9 22 26 220 284

  2.**parameter

  这种形式表示接收任意多个显式赋值的实际参数,并将其放入一个字典中,示例,定义一个函数,让其可以接收任意多个显式赋值的实际参数,示例如下:

1 def lovenum(**num):
2     print()
3     for num1,num2 in num.items():
4         print(num1+'喜欢的数字是:'+num2)
5 lovenum(雨霓同学='1210',淑雪同学='1184')
6 输出:
7 雨霓同学喜欢的数字是:1210
8 淑雪同学喜欢的数字是:1184

  如果想要使用一个已经存在的字典作为函数的可变参数,可以在字典的名称前加“***”。示例如下:

 1 def lovenum(**num):
 2     print()
 3     for num1,num2 in num.items():
 4         print(num1+'喜欢的数字是:'+num2)
 5 dict1={'雨霓同学':'1210','淑雪同学':'1184','霜序':'220'}
 6 lovenum(**dict1)
 7 输出:
 8 雨霓同学喜欢的数字是:1210
 9 淑雪同学喜欢的数字是:1184
10 霜序喜欢的数字是:220
posted @ 2019-07-03 22:31  雨霓同学  阅读(281)  评论(0编辑  收藏  举报