Python-函数编程

Posted Gulibali

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python-函数编程相关的知识,希望对你有一定的参考价值。

             Python-函数编程

1,基本介绍

  定义:函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可。简单一点,命令打包,然后提高了协作性,想在哪里执行就在哪里执行。

  特性:

  • 减少重复代码,增加复用性
  • 使程序变的可拓展性
  • 使程序变得易维护
  • 灵活清晰

  语法:

  

1 def functionname( parameters ): # 函数名
2    "函数_文档字符串"
3    
4 functionname()  #  调用函数,函数名只是指向相应地址,这个括号的作用才是要执行那段代码

  也可以带参数

 1 # 下面这段代码
 2 a,b = 5,8
 3 c = a**b
 4 print(c)
 5  
 6 # 改成用函数写
 7 def calc(x,y):
 8     res = x**y
 9     return res  # 返回函数执行结果
10  
11 c = calc(a,b)  # 结果赋值给c变量
12 print(c)

在定义函数的过程中,需要注意以下几点:

  • 函数代码块以def关键词开头,一个空格之后接函数标识符名称和圆括号(),再接个冒号。
  • 任何传入的参数必须放在圆括号中。
  • 函数的第一行语句后可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始,并且缩进。
  • 使用return结束函数。默认返回None。
  • return语句依然在函数体内部,不能回退缩进。直到函数的所有代码写完,才回退缩进,表示函数体结束。

2,函数参数

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

1.0 形参变量

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

1.1 实参

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

             

2.0 默认参数

 1 def stu_register(name, age, country, course):
 2     print(\'------学生注册信息-------\')
 3     print(\'姓名:\', name)
 4     print(\'age:\', age)
 5     print(\'国籍:\', country)
 6     print(\'课程:\', course)
 7  
 8 stu_register("王山炮",22, \'CN\', \'python_devops\')
 9 stu_register("张角春", 21, \'CN\', \'Linux\')
10 stu_register("刘老根", 25, \'CN\', \'Linux\')

 这里出现了很多的 \'CN\',可以设置默认参数,就可以直接替代 

def stu_register(name, age, course, country = \'CN\'): # 这里的默认参数放在最后面
    print(\'------学生注册信息-------\')
    print(\'姓名:\', name)
    print(\'age:\', age)
    print(\'国籍:\', country)
    print(\'课程:\', course)
 
stu_register("王山炮",22, \'python_devops\', \'UN\')  # 如果不想使用默认参数的值,可以在最后面自定义想要的参数的值
stu_register("张角春", 21, \'Linux\')
stu_register("刘老根", 25,  \'Linux\')

  这里的country默认参数一定要写在最后面,否则会报错,为什么呢?

  因为如果设置默认参数,实际上排序上面就会造成一定的乱序,为了不乱序,python里头设定默认参数就是放在最后面,有这样的设定,就不会出现乱序啦

2.1位置参数

  调用函数时根据函数定义的参数位置来传递参数称为位置参数。

        

2.2关键参数

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

     

    

  关键参数就是位置参数带有参数名,两者结合为关键参数。第二个关键参数不能在位置参数的前面。第三个不能重复赋值

3.1非固定参数 *arg(参数):元组

  如果参数中出现,*users,传递的参数就可以不是固定个数参数,传过来的参数打包成元组

 1 # 报警, 1个运维人员
 2 def send_alert(mgs, user):
 3     pass
 4  
 5 send_alert(\'出现error,请处理\', \'xiong\')
 6 
 7 # 报警,10个运维人员
 8 def send_alert(mgs, *users):  #(\'alex\', \'xxx\', \'ttt\')
 9     for u in users:
10         print(\'%s->%s\'%(mgs,u))
11  
12 send_alert(\'出现error,请处理\', \'xiong, \'xxx\',\'ttt\')
# 运行结果
出现error,请处理->alex
出现error,请处理->xxx
出现error,请处理->ttt

 

3.2如果传过来的是list,会把他作为元组的第一个元素

 

# 报警,10个运维人员
def send_alert(mgs, *users):  # (\'alex\', \'xxx\',\'ttt\')--->  ([\'alex\', \'xxx\', \'ttt\'])
    for u in users:
        print(\'%s->%s\'%(mgs,u))
 

send_alert(\'出现error,请处理\', [\'xiong\', \'xxx\',\'ttt\'])
# 运行结果
出现error,请处理->[\'alex\', \'xxx\', \'ttt\']

  

3.3传入list,使用一个星号

  不光列表,任何序列类型数据对象,比如字符串、元组都可以通过这种方式将内部元素逐一作为参数,传递给函数。而字典,则会将所有的key逐一传递进去。

  

 1 def send_alert(mgs, *users):  # (\'xiong\', \'xxx\',\'ttt\')--->  (\'xiong\', \'xxx\', \'ttt\')
 2     print(users)
 3     for u in users:
 4         print(\'%s->%s\'%(mgs,u))
 5  
 6 send_alert(\'出现error,请处理\', *[\'xiong\', \'xxx\',\'ttt\'])
 7  
 8 # 运行结果
 9 (\'xiong\', \'xxx\', \'ttt\')
10 出现error,请处理->xiong
11 出现error,请处理->xxx
12 出现error,请处理->ttt
 1 def send_alert(mgs, *users, age):
 2     for u in users:
 3         print(\'%s->%s\' % (mgs, u),age)
 4 send_alert(\'出现error,请处理\', \'xiong\', \'rain\', age=22)
 5  
 6 # 如果在第四行age不指定等于22,则会报错,因为此时*users作为非固定参数,可以传多个值进去,而在第一行将age放在*users后面,则传值的时候必须带上参数,否则位置参数只能放在非固定参数的前面。
 7  
 8 # 执行结果
 9 # 出现error,请处理->xiong 22
10 # 出现error,请处理->rain 22

3.4非固定参数,**kwargs 字典

1 def func(name, degree, *args, **kwargs):
2     print(name, degree, args, kwargs)
3 func(\'xiaoqiu\', \'dortor\', \'sichuan\', \'beijing\', addr = \'shanxi\')
4  
5 # 这里*args对应下面的\'sichuan\',\'beijing\'可以变为一个元组
6 # 这里**kwargs对应下面的addr = \'shanxi\' 可以变为一个字典
7  
8 # 执行结果
9 # xiaoqiu dortor (\'sichuan\', \'beijing\') {\'addr\': \'shanxi\'}

4.0 “万能”参数

  当*args**kwargs组合起来使用,理论上能接受任何形式和任意数量的参数,在很多代码中我们都能见到这种定义方式。需要注意的是,*args必须出现在**kwargs之前。

  

 1 def func(*args, **kwargs):
 2     for arg in args:
 3         print(arg)
 4     for kwg in kwargs:
 5         print(kwg, kwargs[kwg])
 6 lis = [1, 2, 3]
 7 dic = {\'k1\': \'v1\', \'k2\': \'v2\'}
 8  
 9 func(*lis, **dic)
10  
11 # 执行结果
12 # 1
13 # 2
14 # 3
15 # k1 v1
16 # k2 v2

5.0 拆包

  • 把元组拆成一个个,当成参数传递
  • 把字典拆成一对对键值对,当成参数传递

  

 1 ###### 拆包之前
 2  def test(a,b,c=33,*args,**kwargs):
 3      print(a)
 4      print(b)
 5      print(c)
 6      print(args)
 7      print(kwargs)
 8   
 9  A = (44,55,66)
10  B = {"name":"alex","age":18}
11   
12  test(11,22,33,A,B)
13  
14 ####  运行结果
15 11 22 33
16 ((44, 55, 66), {\'age\': 18, \'name\': \'alex\'})  #A,B是传递的参数
17 {}                                           #没有传入命名参数
18  
19  
20  
21 ####   拆包之后
22  def test(a,b,c=33,*args,**kwargs):
23      print(a)
24      print(b)
25      print(c)
26      print(args)
27      print(kwargs)
28   
29  A = (44,55,66)
30  B = {"name":"alex","age":18}
31   
32  test(11,22,33,*A,**B)
33  
34  
35 ####  运行结果<br>11
36 22<br>33
37 (44, 55, 66)
38 {\'age\': 18, \'name\': \'alex\'}
View Code

 

3,return,返回值

1,return语句

  函数外部的代码想要获取函数的执行结果,就可以在函数里用return语句把结果或对象返回。并且表示函数执行到此结束。有时候,函数不需要返回任何值,此时可以不需要return语句,它在后台默认给你返回个None,并且不给任何提示

  但是更多的时候我们还是需要return一些东西。一旦函数执行过程遇到return语句,那么之后函数体内的所有代码都会被忽略,直接跳出函数体。哪怕你现在正在一个循环内。

 1 def stu_register(name, age, country, course):
 2     print(\'------学生注册信息-------\')
 3     print(name, age, country, course)
 4  
 5     return None  # 这里的return None可加可不加,后面结果都是返回None
 6     print(\'nihao\')  # 即使这里还有内容没有输出,因为return在这之前,所以到return这里立即终止执行
 7                     #  所以,执行return的时候相当于直接跳出了函数体<br>#  return 1  # 这里也不执行
 8 status = stu_register("王山炮",29, \'CN\', \'python_devops\')
 9 print(status)
10  
11 # 执行结果
12 ------学生注册信息-------
13 王山炮 29 CN python_devops
14 None               

  一旦函数执行过程遇到return语句,那么之后函数体内的所有代码都会被忽略,直接跳出函数体。

 1 def stu_register(name, age, country, course):
 2     print(\'------学生注册信息-------\')
 3     print(name, age, country, course)
 4  
 5     if age > 22:
 6         return False
 7     else:
 8         return True
 9  
10 status = stu_register("王山炮",29, \'CN\', \'python_devops\')
11 print(status)
12  
13 # 执行结果
14 ------学生注册信息-------
15 王山炮 29 CN python_devops
16 False

  函数只能返回一个值,但是在return后面也能返回一个元组或者是一个字典

1 # 接着上面例子
2 return False,age
3 #执行结果
4 (\'False\',24)
5  
6 # 再例如
7 return [False,age]
8 # 执行结果
9 [\'False\',24]

2,return返回值的类型

  return可以返回什么类型的值,看下面顺便总结一下,函数可以return几乎任意python对象

1 什么都不返回,仅仅return:return
2 数字/字符串/任意数据类型: return \'hello\'
3 一个表达式:return 1+2
4 一个判断语句:return 100 > 99
5 一个变量:return a
6 一个函数调用:return func()
7 甚至是返回自己!:return self
8 多个返回值,以逗号分隔:return a, 1+2, "hello"

3,如何接收函数返回值?

我们在调用函数的时候,可以将函数的返回值保存在变量中。

   
1 def func():
2     pass
3     return "something"
4 result = func()

而对于同时返回多个值的函数,需要相应个数的变量来接收,变量之间以逗号分隔:

1 def func():
2     return 1, [2, 3], "haha"
3  
4 a, b, c = func()

 

4,全局变量,局部变量

4.1两者的作用与关系

  全局变量:定义在函数外部一级代码(没有缩进)的变量,这个变量全局都能使用(到那时要注意顺序)

  局部变量:指定义在函数里面的变量,只能在局部生效。

 1 name = \'beauty\'
 2 def change_name():
 3     name = \'这个是里面的美女\'
 4     print(name, id(name))
 5 change_name()
 6 print(name, id(name))
 7  
 8 # 这里第一个name是一个全局变量,而第二个name是一个局部变量,它们作用的范围不一样,局部变量只对函数内部产生了影响,而全局变量对外面这个大的环境产生了影响。
 9  
10 #执行结果
11 这个是里面的美女 2038317628272
12 beauty 2038317363864
13 # 通过输出两个name的id可以看出,他们所指向的地址是不一样的

  如果在函数内部没有定义一个局部变量,则函数会使用全局变量;

  如果局部和全局变量都定义了,则函数内部会优先使用局部变量。所以两者之间存在一个由内而外的使用顺序。但是两个函数内部的局部变量又是不能共同使用的,互不干扰。

 1 name = \'beauty\'
 2 def change_name():
 3     # name = \'这个是里面的美女\'
 4     print(name, id(name))
 5 change_name()
 6 print(name, id(name))
 7  
 8 # 这里直接执行全局变量定义的一个name,函数里面能调用全局变量,但是函数外面不能调用局部变量
 9  
10 # 执行结果
11 beauty 1868336181912
12 beauty 1868336181912

4.2在函数里面修改全局变量

  一般情况下不建议使用这种方法,在函数里面修改以后,如果后面要引用全局变量的话,就不知道这个全局变量是已经被修改过了

 1 name = \'beauty\'
 2 def change_name():
 3     global name  # 引用修改全局变量一定要在局部变量之前
 4     name = \'美女\'
 5     print(name, \'这个是里面打印的\', id(name))
 6 change_name()
 7 print(name, \'这个是外面打印的\', id(name))
 8  
 9 # 注意:这里的指定在函数内部的全局变量一定要在局部变量之前,否则会报错
10 # 所以,在函数里面修改全局变量,以后引用global,就把全局放在上面,不能放在下面<br>
11 #执行结果
12 美女 这个是里面打印的 2114053808040
13 美女 这个是外面打印的 2114053808040

4.3在函数里修改列表数据

   无法整体修改

 1 nums = [11, 22, 33, 44]
 2 def change_num():
 3     nums = [11, 22, 33]
 4     print(nums)
 5 change_num()
 6 print(nums)
 7  
 8 # 执行结果
 9 [11, 22, 33]
10 [11, 22, 33, 44]
11  
12 #相当于创建了一个局部变量nums

  要修改整个列表的,也要用global来修改

 1 # 对列表内单独数据进行修改
 2 nums = [11, 22, 33, 44]
 3 def change_num():
 4     del nums[3]
 5     nums[2] = 99
 6     print(nums)
 7 change_num()
 8 print(nums)
 9  
10 # 执行结果
11 # [11, 22, 99]
12 # [11, 22, 99]
13  
14 # 对于函数外面的nums,每个列表整体都有一个内存地址,列表里面的每个元素又都有一个
15 # 地址相对应,在函数里面调用整体的nums的内存地址是不能够被修改的,只能引用它,相当于给列表整体赋值是不能够改的,单个元素可以修改
17 # 可以修改的类型:列表,字典,集合,对象,类,里面有一串的是可以修改的
18 # 不可以修改的,数字,字符串
19  
  #修改整个列表 20 nums = [11, 22, 33, 44] 21 def change_num(): 22 global nums 23 nums = [\'\', \'\', \'\', \'\', \'\', \'\'] 24 print(nums) 25 change_num() 26 print(nums) 27 28 # 执行结果 29 [\'\', \'\', \'\', \'\', \'\', \'\'] 30 [\'\', \'\', \'\', \'\', \'\', \'\'] 31 32 # 对于修改,通用可以采用global进行修改

 

5,嵌套函数

  嵌套函数(用于先准备一个函数,即外层函数执行完后,内层函数仍可以使用外层函数的变量),装饰器就是这种应用

  注意:①函数内部可以再次定义函数。②执行需要被调用才能执行

    ③执行顺序,由内而外,一层一层往上