PythonDay4Advance

PythonDay4Advance

函数

引言:比如植物大战僵尸,这个游戏本身也是由代码编写,现在假设有一种豌豆射手,每发射一次

炮弹会执行100行逻辑代码

如果我在程序,每当需要发射炮弹的时候,都要编写100行逻辑代码,就会觉得该程序过于冗余,

代码重复度较高。

解决方案:

如果我将这100行代码放到一个区域中,然后给这个区域起一个名字,今后在需要发射炮弹的代码

逻辑中,通过这个名字就可以调用起这100行代码。这个区域【代码段】在python中称之为函

数,先将函数定义出来,并对该函数起一个名字,将来在合适的地方通过函数名调用该函数,执行

该函数的内部逻辑。

函数的定义

  • 语句定义格式:

    # 使用python中的关键字 def 
    def 函数名(...): 
        函数代码逻辑
    

函数使用特点

  • 函数不调用不执行
  • 定义函数必须在调用之前出现

函数的参数

  • 参数种类

    • 形式参数:指的是函数定义时,小括号中定义的参数
    • 实际参数:指的是将来调用函数时,实际传入进去的具体的值
    def fun1(hhs, zcy): # hhs zcy是形式参数,名字自定义 
        print(hhs + zcy) 
        a1 = int(input("请输入第一个数值:")) 
        b1 = int(input("请输入第二个数值:")) 
        fun1(a1,b1) # a1 b1 是实际参数,可以是变量,也可以是具体的值本身
    
  • 参数的传值方式

    • 位置传参
    def show1(a, b, c): 
        print(f"a:{a},b:{b},c:{c}") # a:11,b:22,c:33 
    
    show1(11, 22, 33)
    
    • 关键字传参 【通过形参的名字传参】
    def show1(a, b, c): 
        print(f"a:{a},b:{b},c:{c}") 
        
    show1(b=100, c=200, a=300)
    
    • 混合传参
    def show1(a, b, c): 
        print(f"a:{a},b:{b},c:{c}") 
        
    show1(100, c=200, b=300)
    

    注意: 混合传参的时候,前面没有关键字的实参是会按照形参的位置来的,后面关键字传参可

    以顺序不一样。

    函数传参的场景【扩展知识】

    # 未使用函数 
    ''' 
    编写登录时的逻辑代码 
    ''' 
    编写发送邮件的代码 50行 
    ''' 
    编写注册时的逻辑代码 
    ''' 
    编写发送邮件的代码 50行
    
    # 使用函数 
    def send_email(xxx,xxx): 
        编写发送邮件的代码 
        ''' 
        编写登录时的逻辑代码 
        ''' 
        send_email(xxx,xxx) 
        ''' 
        编写注册时的逻辑代码 
        ''' 
        send_email(xxx,xxx)
    
    def send_email(msg_to, send_info): 
        import smtplib from email.mime.text 
        import MIMEText from email.header 
        import Header 
        msg_from = '1165872335@qq.com' # 发送方邮箱 
        passwd = 'owbciardnivafija' # 填入发送方邮箱的授权码(填入自己的授权码,相当于 邮箱密码) 
        # msg_to = ['','',''] 
        subject = "33期邮件信息" # 主题 
        # 生成一个MIMEText对象(还有一些其它参数) 
        msg = MIMEText(send_info) # 放入邮件主题
        msg['Subject'] = subject 
        # 也可以这样传参 
        # msg['Subject'] = Header(subject, 'utf-8') 
        # 放入发件人 
        msg['From'] = msg_from # 放入收件人 
        # 通过ssl方式发送,服务器地址,端口 
        s = smtplib.SMTP_SSL("smtp.qq.com", 465) # 登录到邮箱 
        s.login(msg_from, passwd) # 发送邮件:发送方,收件方,要发送的消息 
        s.sendmail(msg_from, msg_to, msg.as_string()) 
        print('成功') 
    p = input("请输入要接收邮件的qq邮箱地址:") 
    info = input("请输入要发送的内容:") 
    send_email(p, info)
    
    • 默认值传参

    需求:调用一个函数,传入一个大字符串和一个小字符串,查找小字符串在大字符串中出现

    的次数,调用函数的时候,可以不传小字串,默认查找字符'a'在大字符串中的出现次数。

    def str_number(big_str, small_str='a'): # 定义函数时,可以设置形式参数的值,作为默 认值 
        # dadqwwfwqfjwqaoiaiosijpoaospjfqwasaapjosaja 
        list1 = list(big_str) 
        counts = list1.count(small_str) 
        print(f"{small_str}在大字符串中总共出现了{counts}次。。。") str_number('dadqwwfwqfjwqaoiaiosijpoaospjfqwasaapjosaja') # 调用时若不传入第二个 参数,使用的就是定义时的默认值 
        
    str_number('dadqwwfwqfjwqaoiaiosijpoaospjfqwasaapjosaja','f') # 若传入第二个参 数,使用的就是实际传入的值
    
    • 动态传参

    未使用动态参数时,解决需求,比较麻烦,参数需要另外定义一个函数

    # 需求1:定义一个函数,将来传入两个int类型的值求和 
    def sum1(a, b): 
        print(a + b) 
        sum1(10, 20) 
        def sum2(a, b, c): 
            print(a + b + c) # 需求2:定义一个函数,将来传入三个int类型的值求和 
            sum2(10, 20, 30)
    

    使用动态参数,只需要定义一个函数就可以了

    def sum1(*num): # 这里的num 是一个元组,接收若干个将来调用时传入的实参 
        n = 0 
        for i in num: 
            n = n + i 
            print(f"总和为:{n}") 
            sum1(10, 20) # (10, 20) 
            sum1(10, 20, 30) # (10, 20, 30) 
            sum1(10, 20, 30, 40) # (10, 20, 30, 40)
    

    使用动态参数时的注意事项

    • 传参的内容,多个参数的类型可以是不一样的
    def sum1(*num): # 这里的num 是一个元组,接收若干个将来调用时传入的实参 
       # n = 0 
       # for i in num: 
       # n = n + i 
       # print(f"总和为:{n}") 
       print(num, type(num))
       # sum1(10, 20) # (10, 20) 
       # sum1(10, 20, 30) # (10, 20, 30) 
       # sum1(10, 20, 30, 40) # (10, 20, 30, 40) 
       # sum1(11) # (11,) 
       # sum1(11, '小虎', [11, 22, 33]) # (11, '小虎', [11, 22, 33]) 
       sum1((11,22,33)) # ((11, 22, 33),)
    

    传入两个**的动态参数

    def sum1(**num): 
       print(num, type(num)) 
       sum1(name='小虎', age=18)
    

    结论:

    * : 表示传入的每一个单独的元素都被封装成一个元组 
    ** : 表示传入的是一个一个的键值对,所有的键值对会被封装成一个字典 
    我们今后开发的时候,定义动态参数时,起名字是固定的,若一个*的动态参数,名字起为 *args, 若**的动态参数,名字起为**kwargs
    
    def show1(a, b, *args, **kwargs): 
        print(args, type(args)) 
        print(kwargs, type(kwargs)) 
    # show1(11,22,33,44,name='小虎',address='合肥') 
    show1(11, 22, 33, 44, name='小虎', address='合肥')
    

函数的返回值

有些函数,我们调用完之后,是能够得到结果的,理论上来说,python中所有的函数都有返回值

python中提供了一个关键字给我们在函数中使用,表示调用完后返回的值,这个关键字叫做

return

  • 例子
def sum1(a, b): 
    c = a + b 
    return c 
res1 = sum1(10, 20) 
print(res1) 
print(res1+20)
  • 函数返回值的特点

    • 一个函数中如果没有写return, 默认情况下,这个函数最后一句话会有一个return None
    • return 和print的区别?
      • return是调用完函数时,可以返回一个值给调用者
      • print就直接输出了,没有返回值
    • 一个函数中,如果遇到了return,那么这个函数就结束了,函数中的后续代码不执行
    def fun1(a, b): 
        print("今天是星期二") 
        c = a + b 
        return c 
    print("明天自习") # 不执行 
    res1 = fun1(10, 20) 
    print(res1)
    
    • 一个函数中只能有一个return
    def fun1(a, b): 
        print("今天是星期二") 
        c = a + b 
        return c 
    	print("明天自习") # 不执行 
    		return 100 # 无效代码
    res1 = fun1(10, 20) 
    print(res1)
    def fun1(): 
        for i in range(1,11): 
            return i 
    res1 = fun1() 
    print(res1) # 1
    
    • 函数返回值return后面,要返回的类型可以是任意的类型
  • 函数参数和返回值的练习

    • 定义 两个函数,第一个函数用户循环输入要累加的数值,函数内部将用户输入的值封装成一

      个列表返回;第二个函数将第一个函数返回的列表当作参数传入,返回列表中所有数据之和的

      结果。

      def get_list(): 
          list1 = [] 
          while True: 
              n = int(input("请输入一个数值:")) 
              if n == -1: 
                  break 
              list1.append(n) 
       	return list1 
              
              
      def sum_list(l2): 
      	n = 0 
      	for i in l2: 
      		n += i 
      	return n 
      
      
      
      l1 = get_list() 
      print(l1) 
      res2 = sum_list(l1) 
      print(res2)
      
  • 函数返回值的的一些进阶用法

    • 直接返回多个值,多个值之间使用英文逗号分隔,实际返回的内容是一个元组
    def show1(): 
        return 11, 22, 33 
    res1 = show1() 
    print(res1, type(res1))
    
    • 分别接收每个返回元素的值
    def show1(): 
        return 11, 22, 33 
    a1, a2, a3 = show1() 
    print(f"a1:{a1}") 
    print(f"a2:{a2}") 
    print(f"a3:{a3}")
    def show1(): 
        return 11, ['hello','world','python'], 33 
    a1, a2, a3 = show1() 
    print(f"a1:{a1}") # a1:11 
    print(f"a2:{a2}") # a2:['hello', 'world', 'python'] 
    print(f"a3:{a3}") # a3:33
    

函数的分类

  • 无参无返回值
def login(): 
    # 登录的操作逻辑 
login()
  • 无参有返回值
def get_number(): # 随机生成一个数 
    return num 
n = get_number() 
print(n)
  • 有参无返回值
def sum1(a,b):
    print(a+b) 
sum1(10,20)
  • 有参有返回值
def fun1(s1): 
    return "shujia:" + s1 
res1 = fun1('hello')

函数可以进行嵌套

  • 嵌套调用
def fun1(): 
    print("hello world 1") 
def fun2(): 
    return 100 
def fun3(a1, b1): 
    fun1() # 调用fun1函数 
    res1 = fun2() # 调用fun2函数 
    return a1 + b1 + res1 
res2 = fun3(11,22) 
print(res2)
  • 嵌套定义
def fun1(): 
    a = 10 
def fun2(): 
    print("hello world") 
    print(a) 
    fun2() # 不调用 不执行 
    
    
fun1() 
fun2() # 报错,调用不了函数内部定义的函数
  • 函数练习2:定义一个函数,传入一个文本路径,和一个关键词,将文本中包含关键词的那一句话

    拿出来放在一个列表中返回该列表

import os 
def get_word_list(file_os, word): 
    res_list = [] 
    if os.path.exists(file_os): 
        f = open(file_os, 'r', encoding='UTF-8') 
        line_list = f.readlines() 
        for line in line_list: 
            if word in line: 
                res_list.append(line.strip()) 
            else:print("该路径不存在!!") 
                return res_list 
            
            
list1 = get_word_list('data/words.txt', 'shujia') 
print(list1)
def get_word_list(file_os, word): 
    res_list = [] 
    if not os.path.exists(file_os): 
        print("该路径不存在!!") 
        return res_list 
    f = open(file_os, 'r', encoding='UTF-8') 
    line_list = f.readlines()
    for line in line_list: 
        if word in line: 
            res_list.append(line.strip()) 
    return res_list 

list1 = get_word_list('data/words.txt', 'shujia') 
print(list1)

函数的传值问题

在python中,调用函数时,传入的是对象的引用。

  • 不可变对象【str, int, float, bool】
def fun1(x, y): 
    print(f"x:{x}, y:{y}") # x:hello, y:world 
    x = y 
    x = x + x 
    print(f"x:{x}, y:{y}") # x:worldworld, y:world 
    
    
s1 = "hello" s2 = "world" 
print(f"s1:{s1}, s2:{s2}") # s1:hello, s2:world   
fun1(s1,s2) 
print(f"s1:{s1}, s2:{s2}") # s1:hello, s2:world

不可变对象的调用,仅在函数内生效,而不会通过地址影响到函数外的值

  • 可变对象【list, tuple, dict, set, 类】
def fun1(x, y): 
    print(f"x:{x}, y:{y}") # x:['hello'], y:['world'] 
    x = y 
    x.append('java') 
    print(f"x:{x}, y:{y}") # x:['world','java'], y:['world','java'] 
    
s1 = ['hello'] 
s2 = ['world'] 
print(f"s1:{s1}, s2:{s2}") # s1:['hello'] , s2:['world'] 
fun1(s1,s2)
print(f"s1:{s1}, s2:{s2}") # s1:['hello'], s2:['world', 'java']

可变对象函数内部可以进行操作,改变可变对象中存储的值,间接影响到函数外变量的引用

作用于与变量

  • 在python中,作用域分为两个区域

    • 函数外是一个作用域
    • 函数内部是一个作用域
  • 全局变量:将变量定义在函数外

  • 局部变量:将变量定义在函数内部

  • 全局变量和局部变量使用特点

    • 局部作用域中可以使用到全局变量【可以使用函数外部定义的变量】
    • 函数与函数内部的作用域是相互独立的,不能互相调用函数内部创建的局部变量
    if 1==1: 
        a=10 
    print(f"a:{a}") 
        
    for i in range(11): 
    	pass 
    print(f"i:{i}")
    
  • python中提供了一个关键字 global, 在函数内部定义一个全局变量,出了函数也是可以被访问到

    的。

    def fun1(): 
        global a 
        a = 100 
        
    fun1() 
    print(a)
    

    注意:如果函数内部有变量被global修饰,需要先调用该函数,让内存中出现这个变量,后

    续才能去使用。

进阶:函数名也可当一个变量使用

  • 用法场景1:
def fun1(): 
    print("好好学习,天天向上!") 
    
fun2 = fun1 

fun2()

赋值的时候,注意有没有小括号,方法名直接赋值,相当于给函数另起了一个名字;如果加了小括

号,相当于调用函数的结果赋值。

  • 用法场景2:
def fun1(): 
    print("鹅鹅鹅")

def fun2(): 
    print("曲项向天歌") 
def fun3(): 
    print("白毛浮绿水")
def fun4(): 
    print("红掌拨清波") 

fun_list = [fun1, fun2, fun3, fun4] 


flag = input("请输入开始:") 
for i in fun_list: 
    i()
  • 用法场景3:将函数作为返回值使用
def fun1(): 
    print("鹅鹅鹅") 
def fun2(): 
    print("曲项向天歌")
def fun3(): 
    print("白毛浮绿水") 
def fun4(): 
    print("红掌拨清波") 
    
    fun_list = [fun1, fun2, fun3, fun4] 
    
    def show1():
        for i in fun_list: 
            i() 
def function1(): 
    return show1 

res1 = function1() 
res1()
  • 用法场景4:将函数作为参数传递
def fun1(): 
    print("鹅鹅鹅") 
def fun2(): 
    print("曲项向天歌") 
def fun3(): 
    print("白毛浮绿水") 
def fun4(): 
    print("红掌拨清波") 
    
    fun_list = [fun1, fun2, fun3, fun4] 
    
def show1(): 
    for i in fun_list: 
        i() 
        
        
def function1(s): 
    s()

function1(show1)
posted @ 2024-11-26 22:00  Roxan  阅读(1)  评论(0编辑  收藏  举报