Python 函数
阅读本文需要5分钟
Python函数
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。
定义一个函数
你可以定义一个由自己想要功能的函数,以下是简单的规则:
- 函数代码块以def关键词开头,后接函数标识符名称和圆括号()。
- 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
- 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以冒号起始,并且缩进。
- Return[expression]结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
语法:
def 函数名( 参数 ): 函数表达式 return 函数表达式值
默认情况下,参数值和参数名称是按函数声明中定义的的顺序匹配起来的。
实例
def abc_123( str ): print(str) return
函数调用说明
定义一个函数只给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从Python提示符执行。
参数传递:
在python中,类型属于对象,变量是没有类型的:
a=[1,2,3] a="tuolaji"
以上代码中,[1,2,3] 是 List 类型,"tuolaji"是String类型,而变量a是没有类型,它仅仅是一个对象的引用(一个指针),可以是List类型对象,也可以指向 String类型对象。
可更改(mutable)与不可更改(immutable)对象
在python中,strings, tuples, 和numbers是不可更改的对象,而 list,dict 等则是可以修改的对象。
- 不可变类型:变量赋值a=5后再赋值a=10,这里实际是新生成一个int值对象10,再让a指向它,而5被丢弃,不是改变a的值,相当于新生成了a。
- 可变类型:变量赋值la=[1,2,3,4] 后再赋值la[2]=5则是将list la的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。
python 函数的参数传递:
- 不可变类型:如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。
- 可变类型:如 列表,字典。如fun(a),则是将 a 真正的传过去,修改后fun外部的la也会受影响
python中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。
def ChangeInt(a): a = 10 b = 2 ChangeInt(b) print(b) # 输出 2
实例中有int对象2,指向它的变量是b,在传递给ChangeInt函数时,按传值的方式复制了变量b,a和b都指向了同一个 Int 对象,在a=10时,则新生成一个int值对象 10,并让a指向它。
按值传递参数和按引用传递参数(传可变对象实例)
按值参数传递:是指一个变量的值来取代一个函数参数的做法。
如果这个值在函数代码组中改变,对于调用这个函数的代码来说,其中相应的变量值并不会受到任何影响,可以把这个参数认为是原变量值的一个副本。
按引用参数传递:是指对于调用这个函数的代码,会维护这个代码中变量的一个链接
如果函数代码组中的变量改变,那么在调用这个函数的代码中,相应的变量值也会改变,可以把这个参数认为是原变量的一个别名。
例如:
def double(arg): print('Before:', arg) arg = arg * 2 print('After:', arg) num = 10 double(num) print('num:', num) saying = 'Hello' double(saying) print('saying:', saying) # 输出 Before: 10 After: 20 num: 10 Before: Hello After: HelloHello saying: Hello
传入函数的和在末尾添加新内容的对象用的是同一个引用。
参数
1 向函数传递参数
向函数中传递任意参数,这样打印出的结果就可以根据自己的选择,做出改变。
def greet_user(username): """显示简单的问候语""" print("hello," + username + "!" ) greet_user('python')
输出结果
hello,python!
2、形参与实参
什么是形参?顾名思义,形参就是形式上的参数,可以理解为数学的X,没有实际的值,通过别人赋值后才有意义。相当于变量。
什么是实参?顾名思义,实参就是实际意义上的参数,是一个实际存在的参数,可以是字符串或是数字等。
def greet_user(username): # username 是形参 """显示简单的问候语""" print("hello," + username + "!" ) greet_user('python') # python 是实参 就是在函数名中定义一个形参,然后在函数调用的时候,给函数名中的形参传递一个实际的参数,这个就变为实参。这样的话执行函数体内容时就会执行对应的操作。
注意:传入实参时,一定要加上引号,否则会报错。
3、传递实参(位置实参、关键字实参、默认值、等效的函数调用、避免参数错误)
使用背景:
函数定义中可能包含多个实参,而向函数传递实参的方式有很多,位置实参和关键字实参等。
3.1、位置实参
调用函数时,必须将函数调用中的每个实参都关联到函数定义中的一个形参。关联方式是基于实参的顺序,这被称作位置实参
#位置实参 def describe_pet(animal_type,pet_name): """显示宠物信息""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name.title() + ".") describe_pet('dog','harry') 执行结果: I have a dog. My dog's name is Harry.
3.2、关键字参数
关键字实参 是传递给函数的名称:值对。直接将形参与实参关联起来,这样就不存在顺序问题(不会像上一个例子一样出现搞笑的结果)。
示例:
# 关键字实参 def describe_pet(animal_type,pet_name): """显示宠物信息""" print("\n关键字实参示例:") print("I have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name.title() + ".") describe_pet(animal_type="dog",pet_name="harry") 执行结果: 关键字实参示例: I have a dog. My dog's name is Ha
3.3、默认值参数
在编写函数时,可以给每个形参设定一个固定值,即为默认值。
在调用函数给形参提供实参时,就使用实参值,否则,使用实参的默认值,因此,给形参指定默认值后,在函数调用中省略相应的实参。
#默认值参数 def describe_pet(pet_name,animal_type = 'dog'): """显示宠物信息""" print("\n关键字实参示例:") print("I have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name.title() + ".") describe_pet(pet_name="harry")
执行结果:
1默认值实参示例:
I have a dog. My dog's name is Harry.
注意点:这里把pet_name 放在了前面,原因是在这里还是把它当做是位置参数,如果形参与实参的位置不对应,还是会报错
如果不想使用默认值参数,也可以在调用函数时,将形参定义一个值,这样函数名中的形参默认值就会被忽略。
describe_pet(animal_type="cat",pet_name="harry")
3.4 可以多次调用函数
def describe_pet(animal_type,pet_name): """显示宠物信息""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name.title() + ".") describe_pet('dog','harry') #可以多次调用 describe_pet("cat",'coo') describe_pet('pig','echo') 执行结果: I have a dog. My dog's name is Harry. I have a cat. My cat's name is Coo. I have a pig. My pig's name is Echo.
匿名函数
python 使用 lambda 来创建匿名函数。
- lambda只是一个表达式,函数体比def简单很多。
- lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
- lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
- 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
语法
lambda函数的语法只包含一个语句,如下:
lambda [parameter_list]:表达式
sum = lambda arg1, arg2: arg1 + arg2 #调用sum函数 print (sum( 20, 20 )) print (sum( 30, 20 )) # 以上实例输出结果: 40 50
return语句
意义:其实说白了,函数就是个你招来的工人。你给他一些材料,告诉他怎么用这些材料拼装,然后他负责把拼装好的成品交给你。材料就是函数的参数,成品是函数的输出,而怎么拼装就是你写的函数体代码了。比如这段代码
def worker(a, b, c): x = a + b y = x * c
这个工人worker
在你的指导下,用a b c
三个材料,装配出了x
和y
两个成品。但是程序里的装配和工厂不同,用过的材料不会消失。这样,这个工人手里就有了a b c x y
五样物品。他怎么知道你要的是哪个呢?所以return
的作用就是,在这种时候告诉工人你到底想要什么东西,是一个iPhone
手机壳还是整台iPhone
。例如
def worker(a, b, c): x = a + b y = x * c return y
这样工人就会把y
交给你。当你让这个工人帮你干活(调用函数的时候)result = worker(1, 2, 3)
你就会得到对应的结果((1+2)*3)
。这就是return
的作用。
变量和局部变量
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。如下实例:
total = 0; # 这是全局变量 # 可写函数说明 def sum( arg1, arg2 ): #返回2个参数的和." total = arg1 + arg2; # total在这里是局部变量. print ("在函数内部局部total : ", total) return total; #调用sum函数 sum( 10, 20 ); print ("函数外部的全局total : ", total) # 以上实例输出结果: 在函数内部局部total : 30 函数外部的全局total : 0
END
岁月有你,惜惜相处