【Python基础】13-函数基础

一. 创建函数

1.1 定义

函数: 指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可。

语法:

def函数名([形参]): 函数过程函数名([实参])#调用函数

举例:

defsayhi():#函数名

print('hello')sayhi()#如果不加括号只是表示该函数内存地址

1.1.1 函数特性

减少重复代码

使程序变得可扩展

使程序变得易维护

1.2 文档化函数

如果想要给函数写文档,让其他使用该函数的人能理解的话,可以加入注释,方法有2中:

#开头

在def语句后面(以及在模块或者类的开头)直接写上字符串

如果在函数的看透写下字符串,它就会作为函数的一部分进行存储,称为文档字符串

defsquare(x):

'calculates the square of number x'returnx*x

文档字符串可以按如下方式访问:

defsquare(x):

'calculates the square of number x'returnx*xprint(square.__doc__)

#输出

calculates the square of number x

1.3 并非真正函数的函数

python的有些函数并不返回任何东西,但是python的函数就是函数:没有return语句或者虽然有return语句后面没有跟任何值的函数不返回值

其实python所有的函数都返回了东西:当不需要他们返回任何值的时候,他们就返回None

警告

千万不要被默认行为所迷惑。如果在if语句内返回值,那么要确保其他分支也有返回值,这样一来当调用者期待一个序列的时候,就不会意外的返回None

二. 函数参数

参数可以让你的函数更加灵活,不只能做死的动作,还可以根据调用时传参的不同来决定函数内部的执行过程

2.1 形参变量

只有在被调用的时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量。

2.2 实参

可以是常量、变量、表达式、函数、字典、列表等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值。

a,b=5,8defcalc(x,y):#x,y为形参res=x**y

returnresc=calc(a,b)#a,b为实参

print(c)

2.3 关键参数和默认参数

之前所使用的参数都叫位置参数,因为他们的位置很重要,甚至比他们的名字更重要。这里学的内容可以回避位置问题。

例题: 考虑下面两个函数:

defhello_1(greeting,name):

print('%s,%s'%(greeting,name))

defhello_2(name,greeting):

print('%s,%s'%(name,greeting))

两个代码所实现的是完全一样的功能,只是参数顺序反过来了:

hello_1('hello','world')hello,world#输出

hello_2('hello','world')hello,world#输出

有些时候(尤其是参数很多的时候),参数的顺序是很难记住的。为了让事情简单些,可以提供参数的名字:

这样一来,顺序就完全没有影响了,但参数名和值一定要对应

hello_1(name='hello',greeting='world')hello,world#输出

关键字参数

私用参数名提供的参数叫做关键字参数,主要作用在于可以明确每个参数的作用,避免弄乱了参数的顺序。

关键字参数最厉害的地方在于可以在函数中给参数提供默认值

正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可(指定了参数名的参数就叫关键参数),但是记住一个要求就是,关键参数必须放在位置参数(以位置顺序确定的参数)之后

defstu_register(name,age,country,course):

print("----注册学生信息----")

print("姓名:",name)

print("age:",age)

print("国籍:",country)

print("课程:",course)stu_register("王二",22,"CN","python_devops")stu_register("张三",21,"CN","linux")

可以这样调用

stu_register("王二",course="python_devops",age=22,country='JP')

但是不可以这样

stu_register(course="python_devops","王二",age=22,country='JP')

也不可以这样

stu_register("王二",22,age=22,course="python_devops")

默认参数

当参数具有默认值的时候,调用的时候就不用提供参数了!可以不提供、提供一些或提供所有的参数:

注意

默认参数应该在参数的后面

如果要更改默认参数,直接在后面填写需要更改的值

例题:如何将country默认为CN

defstu_register(name,age,course,country="CN"):

print("----注册学生信息----")

print("姓名:",name)

print("age:",age)

print("国籍:",country)

print("课程:",course)stu_register("王二",22,"python_devops")stu_register("张三",21,"linux",'Korean')

2.4 收集参数

收集参数又叫做非固定参数

带* 参数

参数前带*号的参数将所有值放在同一个元组中。讲这些值收集起来,然后使用。

一般用*args

带*的参数不能放在前面

带* 参数举例

单纯重复输入普通参数:

#报警,1个运维人员

defsend_alert(msg,user):

print(msg)

print(user)#报警,10个运维人员

send_alert("请注意,内存过满!","alex")send_alert("请注意,内存过满!","Jack")

带* 参数与普通参数联合使用

带* 参数收集其余的位置参数。如果不提供任何收集元素,收集参数返回的是空元组。

优化代码--方式一

defsend_alert(msg,*user):#users为一个元组print(msg)

print(user)send_alert("请注意,内存过满!","alex","Jack","Junee")

#输出

请注意,内存过满!(alex Jack Junee)

带* 参数与列表联合使用

优化代码--方式二 []-->*[] = ([])-->()

显示出来为列表内的元素按顺序依次执行函数

defsend_alert(msg,*users):#users为一个元组foruinusers:

print(msg,u)send_alert("请注意,内存过满!",*["alex","Jack","Junee"])

#输出

请注意,内存过满! alex请注意,内存过满! Jack请注意,内存过满! Junee

带* 参数与关键字参数联合使用

当带 * 参数与关键字参数联合使用时候,会报错,需要另外一个能处理关键字参数的“收集”操作带的参数**。

defsend_alert(msg,*user):#users为一个元组print(msg)

print(user)send_alert("请注意,内存过满!",todo='请处理')

#输出

TypeError: send_alert() got an unexpected keyword argument'user'

带** 参数

带** 参数输入值为关键字参数

带** 参数返回的是字典而不是元组

defsend_alert(msg,**user):#users为一个元组print(msg)

print(user)send_alert("请注意,内存过满!",todo='请处理')

#输出

请注意,内存过满!{'todo':'请处理'}

带** 参数举例

例题1

deffunc(name,*args,**kwargs):

print(name,args,kwargs)func("Alex",22,"tesla","500W")

#输出

lex (22,'tesla','500W') {}

例题2

deffunc(name,*args,**kwargs):

print(name,args,kwargs)func("Alex",22,"tesla","500W",addr="山东",num=13818)

#输出

Alex (22,'tesla','500W') {'addr':'山东','num':13818}

例题3

deffunc(name,*args,**kwargs):

·print(name,args,kwargs)d={"degree":"primary school"}func("peiqi",d)func("peiqi",*d)func("peiqi",**d)#输出peiqi ({'degree':'primary school'},) {}peiqi ('degree',) {}peiqi () {'degree':'primary school'}

2.5 参数收集的逆过程

如何将参数收集为元组和字典已经讨论过了,但是事实上,如果使用 * 和 ** 的话,也可以执行相反的操作。

带* 参数收集逆过程举例

那么参数收集的逆过程是什么样?假设有如下函数:

defadd(x,y):returnx+y

比如说有个包含由两个要相加的数字组成的元组:

params=(1,2)

这个过程多少有点像我们上一节中介绍的方法的逆过程。不是要收集参数,而是要分配它们在“另一端”。

使用* 运算符就简单了---不过是在调用而不是在定义时使用:

add(*params)

#输出

3

带** 参数收集逆过程举例

defhello_1(greeting,name):

print('%s,%s'%(greeting,name))params={'greeting':"Sir","name":"well met!"}hello_1(**params)

#输出

Sir,well met!

在定义或者调用函数时使用*(或者**)仅传递元祖或字典,所以可能没遇到什么麻烦:

defwith_stars(**kwds):

print(kwds['name'],'is',kwds['age'],'years old.')

defwithout_stars(kwds):

print(kwds['name'],'is',kwds['age'],'years old.')

args={'name':'Mr,Gumby','age':42}

with_stars(**args)without_stars(args)

#输出

Mr,Gumbyis42years old.Mr,Gumbyis42years old.

可以看出,在with_stars中,在定义和调用函数时候都是用了*

但是在without_stars中两处都没有用,但是得到了同样的效果

所以*只在定义函数(允许使用不定数目的参数)或者调用(‘分割’字典或序列)时才有用

  • 发表于:
  • 原文链接:http://kuaibao.qq.com/s/20180125G0ZJ9G00?refer=cp_1026

相关快讯

扫码关注云+社区