Python-函数

阅读目录:

  1、函数

  2、函数定义,调用

  3、函数参数

  4、函数参数默认值

  5、可变参数

  6、函数参数

  7、参数解构

 

 

内容:

 

 

 

1、函数

  函数:

    数学定义:y = f(x) ,y 是 x 的函数,x  是自变量。 y = f(x0,x1...,xn).

    Python 函数:

      • 由若干语句组成的语句块、函数名称、参数列表构成,他是组织代码的最小单元。
      • 完成一定的功能

  函数的作用:

      • 结构化编程对代码的最基本的封装,一般按照功能组织一端代码。
      • 封装的目的为了服用,减少冗余代码
      • 代码更加简洁美观,可读易懂

  函数的分类:

      • 内建函数,如max()
      • 库函数,如 math.ceil()  使用需要到入库 math

2、函数定义,调用

  def 语句定义函数:

    def  函数名(参数列表):

       函数体(代码块)

       [ return 返回值 ]

        • 函数名就是标识符,命名要求一样
        • 语句块必须缩进,约定4个空格
        • Python的函数没有return 语句,隐式会返回一个None 值
        • 定义中的参数列表成为形式参数,只是一种符号表达式,简称 形参

    函数调用:

      函数定义,只是声明了一个函数,它不会被执行,需要调用

      调用方式:就是函数名加上小括号,括号内写上参数

      条用时,写的参数是实际参数,是实实在在传入的值,简称 实参

    函数举例

      def add(x, y):

        result = x + y

        return result

      out = add(4, 5)

      print(out)

        • 上面只是一个函数的定义,有一个函数叫做add,接受2 个参数
        • 计算的结果,通过返回值返回
        • 调用通过函数名 add加 2 个参数,返回值可使用变量接受
        • 定义需要在调用前,也就是说调用时,已经被定义过,否则抛 NameError 异常
        • 函数是可调用的对象,用 callable() ----callable(函数名)返回True 就是可悲调用的
        • print() 本身是没有 返回值 return
            • print(print(type(3)))
            • In [28]: print(print(type(3)))
              <class 'int'>
              None

        • 先定义 后调用

3、函数参数

    参数调用时 传入 的参数 要和定义的个数相匹配(可变参数例外)

    ***位置参数:

      def f( x, y, z) 调用 f( 1, 2, 3)

      按照参数定义顺序传入实参

    ***关键字参数

      def f( x, y, z) 调用使用 f( x=1, y=2, z=3)

      使用形参的名字来出入实参的方式,如果使用了形参 名字,那么传参顺序就可和定义顺序 不同  

    传参:

      f(z = None, y=10, z=[1] )

      f((1,) , z=6,y = 4.2)

      f(y=4,z=7, 2) : 错误的传参,位置参数,不能放在关键字参数之后

      要求位置参数 必须放在关键字参数之前传入,位置参数是按照位置对应的

4、函数参数默认值:

    参数默认值(缺省值)

        定义时,在形参后跟上一个值

        def add(x=4, y=5):

          return x + y        

 1 def  add(x=4, y=5):
 2     return x + y
 3 
 4 add(6,9) # 15
 5 add(6, y=7) # 13
 6 add(x=5) # 10
 7 add() # 9
 8 add(y=7) # 11
 9 add(x=5, 6) # 语法错误
10 add(y=9, x=3)# 12
11 add(x=1, y=2)# 3
test def add(x=4, y=5)

 

 1 def  add(x=4, y): # non-default argument follows default argument
 2     return x + y
 3 
 4 # add(6,9) # 15
 5 # add(6, y=7) # 13
 6 # add(x=5) # 10
 7 # add() # 9
 8 # add(y=7) # 11
 9 # add(x=5, 6) # 语法错误
10 # add(y=9, x=3)# 12
11 # add(x=1, y=2)# 3
test def add(x=4, y):

 

  注:  def  add(x=4, y) 定义时错误的,缺省参数不能放在非缺省参数之前

    作用:

      参数的默认值可以在未传入足够的实参的时候,对没有给定 的参数赋值为默认值

      参数非常多的时候,并不需要用户每次都输入所有的参数,简化函数调用

    举例:

def login(host='localhost',username='jacke',password='ssss'):
    pass

 

 

5、可变参数

  有多个数,需要累加求和

1 def add(nums):
2     sum = 0
3     for x in nums:
4         sum += x
5     return sum
6 
7 add([1,2,3]) # 6
8 add((2,3,4))# 9

 

      传入一个可迭代对象,迭代元素求和

 

  可变参数:

    一个形参可以匹配任意个参数

    ***位置参数的可变参数:

 1 def add(*nums):
 2     sum = 0
 3     print(type(nums))
 4     for x in nums:
 5         sum += x
 6     print(sum)
 7 
 8 add(3,4,6)
 9 
10 # <class 'tuple'>
11 # 13

 

      注:        

        在形参前面使用* 表示该形参是可变参数,可以接受多个实参

        收集多个实参为一个tuple

 

    ***关键字参数的可变参数: 只收集 关键字参数            

 1 def showconfig(**kwargs):
 2     for k,v in kwargs.items():
 3         print(k,v)
 4     print(kwargs)
 5     kwargs['a'] = 0
 6     print(kwargs)
 7 showconfig(a=1, b=3, c=5)
 8 
 9 # a 1
10 # b 3
11 # c 5
12 # {'a': 1, 'b': 3, 'c': 5}
13 # {'a': 0, 'b': 3, 'c': 5}
**kwargs

 

       注:

         形参前面使用** 符号,表示可以接受多个关键字参数

         收集的实参名称和值 组成一个字典 ,这个字典可以修改

 

    ***可变参数混用:

        配置信息打印

1 def showconfig(username, password, **kwargs):
2     
3 def showconfig(username, *args, **kwargs):
4     
5 def showconfig(username, password, **kwargs, *args): # 错误,可变关键字参数只能在可变位置参数之后

 

    总结:

      • 有位置可变参数和关键字参数可变参数
      • 位置可变参数在形参前使用一个 星号 *
      • 关键字可变参数在形参前使用两个星号**
      • 位置可变参数和关键字可变参数都可以收集若干个实参,位置可变参数收集形成一个 元组,关键字可变参数收集形成一个 字典
      • 混合使用参数的时候,可变参数要放到单数列表的最后,普通参数需要放在参数列表前面,位置可变参数需要在关键字可变参数之前

练习:

 1 def fn(x, y, *args, **kwargs):
 2     print(x)
 3     print(y)
 4     print(args)
 5     print(kwargs)
 6    
 7 # fn(3, 5, 7, 9, 10, a=1, b='python')# 正确
 8 
 9 # # 因为之前位置参数已经给了,然后在给值就重复了
10 # fn(7, 9, x=1, a=1, b='python') # fn() got multiple values for argument 'x'
11 
12 
13 fn(2, a=1, b=2, y=1)# 正确
test 混合使用
 1 def fn(*args, x, y,  **kwargs):
 2     print(x)
 3     print(y)
 4     print(args)
 5     print(kwargs)
 6     
 7 fn(3,2,5) #keyword_only meiyou 给定
 8 fn(3,5,a=1,b=3) #keyword_only meiyou 给定
 9 fn(3,4,x=2,y=3,a=1) # 正确
10 
11 # 2
12 # 3
13 # (3, 4)
14 # {'a': 1}
test 混合使用

 

    *** keyword-only 参数 (python 3 加入的)

      如果 在一个 星号* 参数后,或者一个位置可变参数后,出现的普通参数,实际上已经不是普通参数了,而是keyword-only 参数

      举例:只能通过关键字传参,要不就给缺省值

 1 def fn(*args, x):
 2     print(x)
 3     print(args)
 4 
 5 # fn(3,5)
 6 # fn(3,4,5)
 7 fn(3,4,x=2)
 8 
 9 # 2
10 # (3, 4)
举例

 

      def fn( **kwargs,  x):  直接报语法错误,可以理解为开挖如果是,会截获所有的关键字参数,就算写了 x=5, 也会被 可变关键字参数接受,所以x 永远得不到这个值。

      def fn(*args, x, y=100):正确

      

      keyword-only 参数的另一种形式:

1 def fn(*, x, y):# 逗号不能少!!!!
2     print(x, y)
3 
4 fn(x=3, y=5)

 

      注: *  之后,普通形参都变成了必须给出的keyword-only 参数

 

    

    可变参数和参数默认值:    

 1 def fn(*args, x=5):
 2     print(x)
 3     print(args)
 4     
 5 fn() # 等价fn(x=5)
 6 fn(5) # 5 给了前者
 7 # 5
 8 # (5,)
 9 fn(x=6)
10 # 6
11 # ()
12 fn(1,2,3,x=10)
13 
14 
15 
16 
17 def fn(y ,*args, x=5):
18     pass
19 fn()# y没有
20 fn(y=17,2,3,x=1)# 位置参数要放在关键字参数之前  y=17,2,3 ----2,3,y=12 但是还是不对,因为y已经给了2,重复了
举例

 

6、函数参数

  参数规则:

    参数列表参数 一般顺序是:普通参数,缺省参数,可变位置参数,keyword_only (可带缺省值),可变关键字参数。

    def f(x, y, z=3, *arg, m=4,n,**kwargs):

        pass

    注意:

      代码应该易读易懂,按照书写习惯定义函数参数

   参数规则举例:

     参数列表参数 一般顺序是:普通参数,缺省参数,可变位置参数,keyword_only (可带缺省值),可变关键字参数。   

 1 def connect(host='localhost', port='3306', user='admin',password='admin',**kwargs):
 2     print(host, port)
 3     print(user,password)
 4     print(kwargs)
 5     
 6 connect(db='cmdb')
 7 connect(host='192.168.12.1', db='cmdb')
 8 connect(host='192.168.12.1', db='cmdb', password='dasda')
 9 '''
10 localhost 3306
11 admin admin
12 {'db': 'cmdb'}
13 192.168.12.1 3306
14 admin admin
15 {'db': 'cmdb'}
16 192.168.12.1 3306
17 admin dasda
18 {'db': 'cmdb'}
19 '''
test

 

 

7、参数解构 :只能用在函数传参中,区别 普通的解构

1 def add(x, y):
2     return x + y
3 add(4,5)
4 add([4,5][1],(1,2)[1])
5 add(*[4,5])
6 add(*(4,5))
7 add(*{4,5})
8 add(*'45')
9 add(*range(100, 102))
test-解构
1 def add(x, y):
2     return x + y
3 
4 add(*{'a':1,'b':2}) #'ab'
5 # add(**{'a':1,'b':2}) # 报错
6 add(*{'x':1,'y':2}) #'xy'
7 add(**{'x':1,'y':2}) # 3
字典参数解构

 

 

    参数解构:

      • 给函数提供实参的时候,可以在结合类型前 使用* 或者** ,把集合类型的结构 解开,提出所有的元素作为函数的实参。
      • 非字典类型使用* 解构成位置参数
      • 字典类型使用** 解构成关键字参数,不过要注意解构出来的 标识符 要一致
      • 提取出来的元素数目要和参数的要求匹配,也要和参数的类型匹配

    参数解构 和可变 参数

      给函数提供实参的时候,可以再集合类型前使用* 或 **

 1 def add(*iterable):# 注意,别犯傻,这个是 *args
 2     print(iterable )
 3     result = 0
 4     for x in iterable:
 5         result += x
 6     return result
 7 
 8 # add(1,2,3)
 9 
10 # add(*[1,3,4])
11 
12 # add(*range(10 ))
13 
14 add(range(10)) # 报错,将range(10)给了 iterable这个元组 (range(0, 10),)
15     # 虽然这个元组可迭代,但是就一个元素,x + 0 是什么鬼?
test

 

posted @ 2018-08-21 22:09  JerryZao  阅读(291)  评论(0编辑  收藏  举报