python怎么创建函数_Python中如何创建函数以及详细的使用教程 各种常用函数总结...

函数的定义和调用

函数能提高应用的模块性,和代码的重复利用率,学习了函数,你就可以让你的代码不在那么死板,更加结构化和过程化。那么如何创建一个函数呢?这是函数的语法格式:

def 函数名(参数列表):

函数体

在使用函数的时候你需要遵守以下几点:

函数代码块以def 关键词开头,后接函数标识符名称(函数名字)和圆括号 ()。

任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。

函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。

函数必须调用才能执行,方法:函数名(参数列表)。

return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

我们创建一个简单的函数:

def fun():

"""

在pycharm中这是自动生成的,用来解释函数的说明

:return:

"""

pass

上面的就是一个简单的空函数且没有return表达式,返回值就是None。我们运行这个程序也不会报错,什么也没有做,显然它没有什么用处而言。我们往下接着学习更有趣的东西。我们重新定义一个函数,它接受一个参数并且有return表达式:

#定义一个函数

def Function(name):

print('hello world! %s '% name)

return 'Welcome to www.e1yu.com'

#运行函数

Function('鳄鱼君'+'\n----')

print(Function('鳄鱼君'))

# hello world! 鳄鱼君

# ----

# hello world! 鳄鱼君

# Welcome to www.e1yu.com

函数必须调用才能执行,调用方法就是函数名字+(参数列表),定义函数的时候有几个参数,调用的时候就需要传入对应值的参数,否则就会抛出TypeError。我们可以看到上面的代码单单执行函数是不会打印return语句的内容的,使用print方法打印函数,两者都会打印出来。那么return表达式的存在就是为了给函数加上返回值的,关于返回值你需要知道:

返回值数=0,就是没有return,返回None

返回值数=1,return一个值,返回object

返回值数>1,return多个值,返回tuple元组

返回值可以是函数,return function

函数的返回值是为了让我们更清楚函数的执行结果

函数的实参和形参

对于函数来说,形式参数简称形参,不是实际存在的,是虚拟变量。在定义函数和函数体的时候使用形参,目的是在函数调用时接受实际参数,实参与形参是一一对应的。

对于函数来说,实际参数简称实参。是指在调用函数时传入的实际的数据,这会被绑定到函数的形参上,可以是常量、变量、表达式、函数。

形参和实参两者的区别:形参是虚拟的,不占用内存空间,形参变量只有在被调用时才分配内存单元;实参是一个变量,占用内存空间,数据传送单向,实参传给形参,不能形参传给实参。简单一句话理解:定义函数时的参数为形参,调用函数时的参数为实参。我们看一个简单的例子:

def fun(a,b): #形参

"返回多个值,结果以元组形式表示"

return a,b,a+b

fun(1,2)#实参

#实参和形参必须一一对应

函数的位置参数

基于实参的顺序,调用函数时的参数,是按照先后顺序依次赋值给函数的:

#计算x的n次方

def fun(x,n):

s=1

while n>0:

n=n-1

s=s*x

return s

print(fun(2,3)) #2d3次方

print(fun(3,2)) #3的2次方

函数的默认参数

定义函数时的形参有默认值,你如过看到过Python的一些模块的话,会经常看到函数这样定义:def func(x, maxsize=0, loop=None),这就是默认参数,我们来看一个具体的列子:

#计算x的2次方 或者x的n次方

def fun(x,n=2): #n默认值=2

s=1

while n>0:

n=n-1

s=s*x

return s

print(fun(2)) #2的2次方 n有默认值为2,可以不传入n值

print(fun(2,3)) #2d3次方 #如果传入n值,就更新

默认参数必须指向不变对象!列表不能用作默认参数!

函数的可变参数

可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个,可变参数在函数调用时自动组装为一个元组tuple。我们来看一个列子:

def fun(*num):

sum=0

print(num) #是一个元组

print(type(num))

for i in num:

sum=sum+i*i

return sum

print(fun(1,2,3))

在函数内部,参数num接收到的是一个tuple,Python允许在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去:

tu=(1,2,3)

print(fun(*tu))

或者

tu=[1,2,3]

print(fun(*tu))

如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后。python先匹配位置实参和关键字实参,再将剩下的实参都收集到最后一个形参中:

def func(n,*args):

print('接收的位置参数为:%s'% n)

print('接收的可变参数为:', args)

func('eyujun','18','gender')

# 接收的位置参数为:eyujun

# 接收的可变参数为: ('18', 'gender')

函数的关键字实参

关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。它可以扩展函数的功能,让函数可以接受任意个参数!例子:

def fun(name,gender,**kwargs):

return {"name":name,"gender":gender,"other":kwargs}

print(fun('鳄鱼君','男'))

print(fun('鳄鱼君','男',age='18',city='河南'))

和可变参数一样,也可以先定义一个dict,然后,把该dict转换为关键字参数传进去:

def fun(name,gender,**kwargs):

return {"name":name,"gender":gender,"other":kwargs}

dic={'hobby':'Ball','weight':'120kg'}

print(fun('鳄鱼君','男',**dic))

**dic表示把dic所有key-value用关键字参数传入到函数的**kwargs参数,kwargs将获得一个dict,注意kwargs获得的dict是dic的一份拷贝,对kwargs的改动不会影响到函数外的dic。

def build_profile(name, age, **user_info):

"""创建一个字典,其中包含我们知道的有关用户的一切"""

profile = {}

profile['name'] = name

profile['age'] = age

for key, value in user_info.items():

profile[key] = value

return profile

user_profile = build_profile('eyujun', '18',

location='henan',

field='python')

print(user_profile)

函数的命名关键字参数

对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和job作为关键字参数。这种方式定义的函数如下:

def fun(name,gender,*,hobby,weight):

return (name,gender,hobby,weight)

dic={'hobby':'Ball','weight':'120kg'}

print(fun('鳄鱼君','男',hobby='Ball',weight='120kg'))

和关键字参数**kwargs不同,命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命名关键字参数。如果单独出现星号, * 后的参数必须用关键字传入。错误的代码不在进行演示

函数的参数组合

在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。但是需要注意参数的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数,否则就会报错!

def fun(name,age=18,**kwargs): #关键字参数必须要放到参数组前面,否则报错

print(name,age,kwargs)

fun3('zjj',salary=12000)

fun3('zjj',33,salary=12000,age=18) #会报错,age的值给了两个

#给默认参数赋值,可以使用位置参数,关键字参数赋值

def fun2(name,age=18,*args,**kwargs):

print(name,age,args,kwargs)

fun4('zjj',19,salary=120000) #这样传值会保存,*args接受位置参数,第三个为关键字参数,它不会接收,返回空tuple

函数的强制位置参数

/用来指明函数形参必须使用指定位置参数,不能使用关键字参数的形式,可以结合命名关键字参数理解。

def f(a, b, /, c, d, *, e, f): #前面说过*单独出现,e,f为关键字参数

print(a, b, c, d, e, f)

#调用函数

f(10, 20, 30, d=40, e=50, f=60)

#形参 a 和 b 必须使用指定位置参数,c 或 d 可以是位置形参或关键字形参

f(10, b=20, c=30, d=40, e=50, f=60) # b 不能使用关键字参数的形式

f(10, 20, 30, 40, 50, f=60) # e 必须使用关键字参数的形式

全局变量和局部变量

在子程序(函数)中定义的变量是局部变量,在程序的一开始定义的变量称为全局变量。全局变量的作用域是整个程序,局部变量的作用域是定义该变量的子程序。当全局变量与局部变量重名:在定义局部变量的子程序内,局部变量起作用,在其它地方全局变量起作用

你可以简单理解为,函数内部定义的变量为局部变量,在函数外部定义的变量就是全局变量;全局变量在函数内部修改值,它只会在函数内部修改,在函数外部,也就是全局中,不会被改变。所以说在很多的函数中,我们可以定义相同的变量名字,他不会影响其他函数中的变量,也不会影响全局中的变量。

def fun1():

a=1

return a

def fun2():

a=2

return a

print(fun1())

print(fun2())

对于变量作用域,变量的访问以 L(Local) –> E(Enclosing) –> G(Global) –>B(Built-in) 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。

x = int(3.3) #. 内建作用域

g = 0 #全局作用域

def outer():

o = 1 #闭包函数外的函数中

def inner():

i = 2 #局部作用域

print(x)

inner()

outer()

#局部打印x,会从里向外找,有就打印,没有再往外找

函数内可以访问全局变量,但不能更新(修改)其值!

a = 10

def sum ( n ) :

n += a

a = 11 #不能更新(修改)其值,会报错

print ('a = ', a, end = ' , ' )

print ( 'n = ', n )

sum(3)

a = 10

def sum ( n ) :

global a #加上 global 引用以更新变量值

n += a

a = 11

print ('a = ', a, end = ' , ' )

print ( 'n = ', n )

sum ( 3 )

print ( '外 a = ', a ) #a值更新为11

def fun1(name):

print('名字改变前:',name)

name='ZJJ' #我在函数内部修改了name值:局部变量

print('名字改变后:',name) #函数内部打印改变的值,是修改过的

name='zjj'

fun1(name)

print(name) #我们在函数调用后打印名字,是没有修改过的

在函数内部修改外部的全局变量,可以采用下面的方法:

school='清华大学'

def fun1(name='zjj'):

global school #定义变量为全局变量

school='北京大学' #这样就直接把全局变量修改了

return school

f=fun1()

print(f)

特殊情况

name=['zjj','wff','xxk']

def name_change():

name[0]='zgp' #在函数里面修改name

print('name is change:%s'% name) #返回结果是修改完之后的

name_change()

print(name)

注意:

全局变量如果是字符串、数字,在函数内部是不可修改的

全局变量如果是列表(List)、字典(Dict)、集合(Set)、类(Class),在函数内部是可以修改的

元组(Tuple)是不可改变的,不管在哪都是的

一般情况下,我们是在函数内部把变量修改为全局变量,这就存在一种情况,我们创建函数是因为它可以多次调用,假设函数很多,而我们在调用一个函数时,你已经把局部变量修改为全局变量,如果过程出了错误,你就可能找不到错误的原因,程序非常乱,所以尽量不要乱用。

递归函数介绍

在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。在高中的时候我们接触到过阶乘:n! = 1 x 2 x 3 x ... x n,我们来定义一个函数处理任意数的阶乘:

def fun1(n):

if n==1:

return 1

return n * fun1(n-1)

print(fun1(5))

递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。

使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。

解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。

尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

def fun1(num,):

return fun2(num,1)

def fun2(num,prodect):

if num==1:

return prodect

return fun2(num-1,num*prodect)

print(fun1(5))

可以看到,return fun2(num – 1, num * product)仅返回递归函数本身,num – 1和num * product在函数调用前就会被计算,不影响函数调用。如果不理解两个函数之间的计算方式,可以使用断点调试一步一步查看具体的效果。

尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fun1(n)函数改成尾递归方式,也会导致栈溢出。

– END –

未经允许不得转载:作者:鳄鱼君,

转载或复制请以 超链接形式 并注明出处 鳄鱼君。

原文地址:《Python中如何创建函数以及详细的使用教程 各种常用函数总结》 发布于2019-11-08

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值