Python_函数

函数

  • 是一段代码的表示
  • 一段具有特定功能的、可重用的语句组
  • 两个作用:降低编程难度和代码的复用

1. def关键字

  • 定义一个函数
  • def关键字,后跟一个空格
    -函数名,自己定义,起名需要遵循便令命名规则,约定俗成,不要使用大驼峰(只给类起名用)
  • 后面括号和冒号不能省,括号内可以有参数,也可以没有
  • 只是定义的话不会执行
  • 注意缩进,形同C语言的{ },如果表示在函数内就不能与def齐平;函数内有赋值计算分支循环等结构,也必须非常注意缩进,缩进表示"语句地位,语句从属"
    例:
   def func():
         print("我是一个函数")
         print("我要完成一定功能")
   print("我结束了")
   func()  
             我结束了     #第三句print,与def齐平,则不在函数内,直接就输出了
         #此时函数调用
        我是一个函数
        我要完成一定功能

2.函数的参数和返回值

  • 参数: 负责给函数传递一些必要的数据或者信息
  • 形参(形式参数): 在函数定义的时候用到的参数没有具体值,只是一个 占位的符号,成为形参
  • 实参(实际参数): 在调用函数的时候输入的值
  • 返回值: 函数的执行结果
    • return保留字用来传递返回值
    • 函数可以有返回值,也可以没有,可以有return,也可以没有
    • return可以传递0个返回值,也可以传递任意多个返回值
    • 如果没有return,默认返回一个None,即空
    • 函数一旦执行return语句,则无条件返回,即结束函数的执行
      例1:
        def hello(person):
             print("{0}, 你肿么咧".format(person))
             print("我上班去了,你照顾好自己,有事call我!")    
             return "我已经说完了,{}bye".format(person)
        p = "Honey"
        hello(p)
            Honey, 你肿么咧
            我上班去了,你照顾好自己,有事call我! 
            我已经说完了,person,bye
                 #调用时给出实际参数(即"honey"),实际参数代替定义中的形式参数(即       "person"),然后运行函数,逐条执行,最后return执行(return语句的基本使用       
 函数打完招呼后返回一句话),即结束函数

    例2:

       def hello(person):
            print("{0}, 你肿么咧".format(person))
            return "肿么这么严重,我今天请了一天假,照顾你"
            print("我上班去了,你照顾好自己,有事call我!")    
            return "我已经说完了,{}bye".format(person)
        p = "Honey"
        hello(p)
        Honey, 你肿么咧
        '肿么这么严重,我今天请了一天假,照顾你'
              #return直接结束函数,不运行下面语句

3.函数参数细分类
1、 普通参数
- 定义的时候直接定义变量名
- 调用的时候直接把变量或者值放入指定位置
def 函数名(参数1, 参数2,…):
    函数体
    函数名(value1, value2,…) #调用函数
    # 调用的时候,具体值参考的是位置,按位置赋值

2、默认参数
- 形参带有默认值
- 调用的时候,如果没有对相应形参赋值,则使用默认值
例1:

      def  func_name(p1=v1, p2=v2..........):
            func_block
      func_name()   #调用形式1,使用默认值
      value1= 100
      value2=200
      func_name(value1,value2)
                         #调用形式2,对相应形参赋值

例2:

      def reg(name, age, gender="male"):
          if gender == "male":
              print("{0} is {1} and he is a good student".format(name, age))
          else:
              print("{0} is {1} and she is a good student".format(name, age))
      reg("xiaoming", 21)
      reg("xiaohong", 20, "female")
        xiaoming is 21 and he is a good student
        xiaohong is 20 and she is a good student
                  #如果不给第三个值即默认为"male"(之前形参带有默认值gender="male"),当第三个值为female时,不同则执行else下的语句

3、关键字参数

  • 调用函数时,直接给形参赋值再调用函数
    def func(p1=v1, p2=v2…):
      func_body
    func(p1=value1, p2=value2…)
    • 比较麻烦,但也有好处:不容易混淆, 一般实参和形参只是按照位置一一对应即可,容易出错使用关键字参数,可以不考虑参数位置
      例:
         def stu_key(name="No name", age=0, addr="No addr"):
             print("I am a student")
             print("我叫 {0}, 我今年 {1}岁了, 我住{2}".format(name, age, addr)) 
         stu_key(age=18, name="小明", addr="中国")
              I am a student
              我叫 小明, 我今年 18岁了, 我住中国

4、收集参数(可变参数)

  • 把没有位置,不能和定义时的参数位置相对应的参数,放入一个特定的数据结构中
    def func(*args):
    func_body
      #按照list使用方式访问args得到传入的参数
    func(p1, p2, p3, …)
    • 参数名args不是必须这么写,但是,我们推荐直接用*args,约定俗成
    • 参数名args前需要有星号
    • 收集参数可以和其他参数共存
      例:
          def stu( *args):
              print("Hello 大家好,我自我介绍以下,简答说两句:")
                    # type函数作用是检测变量的类型
              print(type(args))
              for item in args:
                  print(item)
          stu("小刚", 18, "住北京中关村", "冒出一个名叫小怪的人", "打酱油")  
          stu("小玉")
              Hello 大家好,我自我介绍以下,简答说两句:
              <class 'tuple'>     #检测出为元组类型
              小刚
              18
            住北京中关村
            冒出一个名叫小怪的人
            打酱油
            Hello 大家好,我自我介绍以下,简答说两句:
            <class 'tuple'>
            小玉

5、收集参数之关键字收集参数
- 把关键字参数按字典格式存入收集参数
def func( **kwargs):
  func_body
func(p1=v1, p2=v2, p3=v3…)

  • ** kwargs一般约定俗成
  • 调用的时候,把多余的关键字参数放入kwargs
  • 访问kwargs需要按字典格式访问
    例:
def stu( **kwargs):
    print("Hello 大家好,我先自我介绍一下:")
    print(type(kwargs))
         # 在函数体内对于kwargs的使用不用带星号
    for k,v in kwargs.items():
       print(k,v)
stu(name="小明",age=18 ,addr="北京中关村", lover="you", work="Teacher")
print("*" * 50)
stu(name="小刚")
                 Hello 大家好,我先自我介绍一下:
                 <class 'dict'>
                 name 小明
                 age 18
                 addr 北京中关村
                 lover you
                 work Teacher
                 **************************************************
                 Hello 大家好,我先自我介绍一下:
                 <class 'dict'>
                 name 小刚
                #调用的时候需要使用关键字参数调用,把关键字参数按字典格式存入收集参数,在遍历其中两个元素时,也成对字符的形式被遍历出来,当遍历其中“一个元素”时,以元组(还是成对的)的形式被遍历出来

6、收集参数混合调用的顺序问题

  • 收集参数,关键字参数,普通参数可以混合使用
  • 使用规则就是,普通参数和关键字参数优先
  • 定义的时候一般找普通参数,关键字参数,收集参数tuple,收集参数dict
    例:
          def stu(name, age, *args, hobby="没有", **kwargs):
              print("Hello 大家好")
              print("我叫 {0}, 我今年{1}了。".format(name, age))
              if hobby == "没有":
                  print("我没有爱好, so sorry")
              else:
                  print("我的爱好是{0}".format(hobby))    
              print("*" * 20)   
              for i in args:
                  print(i)
              print("#" * 30)
              for k,v in kwargs.items():
                  print(k, "---", v)
          name = "xiaoyu"
          age = 19
          stu(name, age, "爱好多", "扔石头", hobby="游泳", hobby2="烹饪",\
          hobby3="跟不同女生聊天")
                #当代码句子过长时,可以加 \ 然后换下行继续写就行了
             Hello 大家好
             我叫 xiaoyu, 我今年19了。
             我的爱好是游泳
             ********************
             爱好多
             扔石头
             ##############################
             hobby2 --- 烹饪
             hobby3 --- 跟不同女生聊天

7、收集参数的解包问题

  • 把参数放入list或者字典中,直接把list/dict中的值放入收集参数中
  • 语法:参看案例
    例:
           def stu(*args):
               print("**********")
               n = 0
               for i in args:
                   print("第{}次解包".format(n))
                   n += 1
                   print(i)
                   d = type(i)
                   print("类型是{}".format(d))
                   print("           ")
          l = ["xiaohong", 19, 23, "xiaodong"]
 
             # 此时,args的表示形式是字典内一个list类型的元素,即 arg = (["xiaohong", 19, 23, "xiaodong"],) ,很显然跟我们最初的想法违背
             # 此时的调用,我们就需要解包符号,即调用的时候前面加一个星号
          stu(*l)
                            **********
                            第0次解包
                            xiaohong
                            类型是<class 'str'>
                           
                            第1次解包 
                            19
                            类型是<class 'int'>
                            
                            第2次解包 
                            23
                            类型是<class 'int'>

                            第3次解包 
                            xiaodong
                            类型是<class 'str'>
           
           ## 同理,dict类型收集参数一样可以解包,但是
                - 对dict类型进行解包
             - 需要用两个星号进行解包

8、函数文档

  • 函数的文档的作用是对当前函数提供使用相关的参考信息,方便其他人查看检验,相当于给他人提供函数说明书
    -文档的写法:
    • 在函数内部开始的第一行使用三引号字符串定义符
    • 一般具有特定格式
      -文档查看:
    • 使用help函数,形如 help(func)
    • 使用__doc__,(doc仅仅是函数的一个属性,所以比help显示简洁得多)
      例:
              def stu(name, age ,*args):
                  # '这是一个文档现在就介绍一下函数作用等'
                  print("This is hanshu stu")
              help(stu)
              stu.__doc__
               Help on function stu in module __main__:
               stu(name, age, *args)
               这是一个文档现在就介绍一下函数作用等
               '这是一个文档现在就介绍一下函数作用等'
                      #一行介绍可以使用一对单引号或双引号

规范标准案例:

            def stu(name, age):
                '''
                这是文档的文字内容
                :param name: 表示学生的姓名
                :param age: 表示学生的年龄
                :return: 此函数没有返回值
                '''
                pass
             print(help(stu))
             print("*" * 20)
             print(stu.__doc__)
                 Help on function stu in module __main__:
                 stu(name, age)
                     这是文档的文字内容
                     :param name: 表示学生的姓名
                     :param age: 表示学生的年龄
                     :return: 此函数没有返回值
            None
            ********************

                 这是文档的文字内容
                 :param name: 表示学生的姓名
                 :param age: 表示学生的年龄
                 :return: 此函数没有返回值

4.变量作用域
-变量由作用范围限制
-分类:按照作用域分类

  • 全局(global): 在函数外部定义
  • 局部(local):在函数内部定义
    -变量的作用范围:
    • 全局变量:在整个全局范围都有效
    • 全局变量在局部可以使用
    • 局部变量在局部范围可以使用
    • 局部变量在全局范围无法使用
  • LEGB原则
    • L(Local)局部作用域
    • E(Enclosing function locale)外部嵌套函数作用域(外围空间)
    • G(Global module)函数定义所在模块(全局)作用域
    • B(Buildin): python内置的作用域
      详解: https://blog.csdn.net/geekcome/article/details/9072285###
  • 局部变量和全局变量是不同变量
    • 局部变量是函数内部的占位符,与全局变量可能重名但不同
    • 函数韵运算结束后,局部变量被释放("被释放"即在函数完成,局部变量将被删除,局部变量只用于函数内部)
      例:
        n, s =10, 100        #n和s是全局变量
        def fact(n) :
            s = 1          #fact()函数中的n和s是局部变量
            for i in range(1, n+1):
                s *= i
            return s
        print(fact(n), s)   #n和s是全局变量
             3628800 100
  • 可以使用global保留字在函数内部使用全局变量
    例:

           n, s =10, 100
           def fact(n) :
               global s     #fact()函数中使用global保留走声明此处s是全局变量s
               for i in range(1, n+1):
                   s *= i
               return s      #此处s指全局变量s
           print(fact(n), s)       #此处全局变量s被函数修改
              362880000 362880000
    

5.eval()函数

  • 把一个字符串当成一个表达式来执行, 返回表达式执行后的结果

  • 语法:

         eval(string_code, globals=None, locals=None)
    

6.exec()函数

  • 跟eval功能类似, 但是,不返回结果
  • 语法:
    exec(string_code, globals=None, locals=None)
    例:
           x = 100
           y = 200
           z1 = x + y
           z2 = eval("x+y")
           print(z1)
           print(z2)
                      300
                      300

例:

           x = 100
           y = 200
           z1 = x + y
           z2 = exec("x+y")
           print(z1)
           print(z2)
                       300
                       None

6.递归
-定义

  • 类似数学归纳法
  • 证明当n取第一个值n0时命题成立
  • 假设当nk时命题成立,证明当n=nk时命题成立
  • 递归是数学归纳法思维的编程体现
    -递归的实现
  • 递归本身是一个函数,需要函数定义方法描述
  • 函数内部,采用分支语句对输入参数进行判断
  • 基例和链条,分别编写对应代码
  • 基本通过调用自身来实现
    - 计算n!
    - 当n=0时,结果为1,
    -其他情况时n! = n*(n-1)!
    例:
               def fact(n):
                   if n == 0:
                       return 1
                   else :
                       return n*fact(n-1)
               n = eval(input("请输入一个数<int类型>:"))
               fact(n)

-斐波那契数列
例:

                 def fun(n):
                     if n == 1 or n == 2:
                         return 1
                     else :
                         return fun(n-1) + fun(n-2)
                 n = eval(input("请输入一个数<int类型>:"))
                 fun(n) 

-汉诺塔问题

  • 规则:
  • 每次移动一个盘子
  • 任何时候大盘子在下面,小盘子在上面
    • 方法:
      1. n=1: 直接把A上的一个盘子移动到C上, A->C
      2. n=2:
        • 把小盘子从A放到B上, A->B
        • 把大盘子从A放到C上, A->C
        • 把小盘子从B放到C上, B->C
      3. n=3:
        • 把A上的两个盘子,通过C移动到B上去, 调用递归实现
        • 把A上剩下的一个最大盘子移动到C上, A->C
        • 把B上两个盘子,借助于A,挪到C上去, 调用递归
      4. n = n:
        • 把A上的n-1个盘子,借助于C,移动到B上去,调用递归
        • 把A上的最大盘子,也是唯一一个,移动到C上,A->C
        • 把B上n-1个盘子,借助于A,移动到C上, 调用递归

例:

              def hano(n, src, mid, dst):
              '''
              汉诺塔的递归实现
              n:代表几个盘子
             src:代表第一个塔,开始的塔
             mid:代表第二个塔,中间过渡的塔
             dst:代表第三个塔, 目标塔
             '''
             if n == 1:
                 print(src, "-->", dst)
                 return None
             hano(n-1, src, dst, mid)      # 把n-1个盘子,从A塔借助于C塔,挪到B塔
             print(a, "-->", c)    
             hano(n-1,mid, src, dst)    # 把n-1个盘子,从B塔,借助于A塔,挪到C塔

             n = eval(input("请输入圆盘个数:"))         #调用函数
             src = "A"
             mid = "B"
             dst = "C"     
             hano(n, scr, mid, dst)

7.lambda函数
-一种匿名函数,即没有名字的函数
-使用lambda保留字定义,函数名是返回结果

  • lambda函数用于定义简单的,能够在一行内表示的函数

  • 形式:

     <函数名> = lambda<参数>:<表达式>
    

    等价于

        def <函数名>(<参数>):
           <函数体>
           return <返回值>
    

例1:

 f = lambda x, y :x + y
f(10,15)
25

例2:

f = lambda : "lambda函数"
print(f()
lambda函数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值