百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

第四章:Python之函数

off999 2024-11-21 19:25 16 浏览 0 评论

第一节:函数入门与定义函数

  • 理解函数
    • 所谓函数,就是为一段实现特定功能的代码“取”个名字,以后即可通过该名字来执行(调用)这段代码
    • 从逻辑上看,函数相当于一个黑匣子
  • 定义函数的语法
    • 定义函数的三条铁律
      • 函数需要几个关键的、需要动态变换的数据,这些数据就应该定义成函数的参数
      • 函数需要传出去几个重要的数据(就是调用该函数的人希望得到的数据),这些数据应该定义成返回值
      • 函数内部的实现过程
    • 函数的语法:
# 定义函数,无参数
def first():
    # 之前学习的定义变量、赋值、运算、分支、循环等全部都可以写在函数里面
    print('first 函数')
    for i in range(5):
        print(i)
first()
# 只要执行函数,函数体的代码就可以被重复的调用(复用)
first()
first()

# 函数定义,有一个参数 name
def hello(name):
    print('hello 函数')
    print('您好,' + name)
hello('python')
hello('java')

# 函数定义,有2个参数 name, age
def info(name, age):
    print('info函数')
    print('name参数', name)
    print('age参数', age)
info(python, 90)
info(java, 70)

# 定义函数,有返回值
def max(a, b):
    r = a if a > b else b
    # 返回值
    return r
# 返回值的意思,当程序调用函数之后,会得到N个值
x = max(10, 20)
print(x)
x = max(30, 20)
print(x)

# print也是个函数,函数的嵌套
print(max(20, 50))
  • 为函数提供文档
    • 只要把一段字符串放在函数声明之后、函数体之前,这段字符串就是函数的说明文档
    • Python内置的help()函数查看其它函数的帮助文档
    • 通过函数的_doc_属性来查看函数的说明文档
# 自定义说明文档
def test(a):
    '''
    test 函数的说明,这是一个简单的函数
    a-代表什么意义
    return- 代表什么意义
    '''
    # 空语句
    pass
print(test.__doc__)
help(test)

第二节:多返回值函数与递归函数

  • 多返回函数
    • 多返回值,本质就是返回元组
    • 程序即可返回元组,也可直接返回多个值(系统会自动将其封装成元组)
    • 获取多返回值函数的返回值时
      • 既可以用单个变量(元组)来获取
      • 也可以用多个变量获取(元组解包)
import random
# 希望该函数返回三个随机的大写字符
def test():
    # 生成三个随机的大写字符
    c1 = chr(random.randint(65,90))
    c2 = chr(random.randint(65,90))
    c3 = chr(random.randint(65,90))
    
    # 以元组的形式返回
    return(c1, c2, c3)
    # 程序自动封装成元组
    return c1, c2, c3
# r就是一个元组
r = test()
print(r)

print(test())

# 多返回值函数,即可用多个变量来接收返回值,也可用单独变量来接收返回值
c1, c2, c3 = test()
print(c1)
print(c2)
print(c3)
  • 递归函数
    • 函数体内调用它自身,被称为函数的递归
    • 函数递归包含了一种隐式的循环,它会重复执行某段代码,但是这种重复执行无需循环控制
    • 递归函数的注意点
      • 向已知的方向递归
      • 让递归有结束的时候,不要无限递归
# 无限递归的例子
def foo():
    print('111')
    print('222')
    foo()
foo()

# 计算N的阶乘
def frac(n):
    if n < 1:
        print("n不能小于1")
        return
    elif n == 1:
        return 1
    else:
        # n的阶乘总是等于上一个阶乘*n
        # 函数调用自身
        return frac(n-1) * n
        
# 该函数的结束点是n==1,因此要向n==1方向递归        
print(frac(5))
print(frac(6))

第三节:关键字参数与参数默认值

  • 关键字参数
    • Python函数的参数名不是无意义的,Python允许调用函数时通过名字来传入参数值
    • 调用函数时支持两种方式为参数指定值
      • 位置参数:必须按照顺序为每个参数指定参数值
      • 关键字参数(命名参数):按参数名为参数指定参数值
def info(name, age, height):
    print("name:", name)
    print("age:", age)
    print("height:", height)
    
# 位置参数,按照顺序传递参数
info('fkjava', 24, 183)

# 关键字参数(命名参数)
# 关键字参数的优势是 1:不需要按照顺序 2:可读性更高
info(age=34, name='java', height=179)

# 混合使用
info('python', height=178, age=45)

# 混合使用错误:关键字参数必须位于位置参数的后面
info(name='python', 178, 45)
  • 参数的默认值
    • 程序需要在定义函数的时候为一个或者多个形参指定默认值,这样调用函数时就可以省略该形参传入参数值,而是直接使用该形参的默认值
    • 为形参指定默认值的语法格式如下:形参名 = 默认值
# 定义带默认值的参数(一个参数有默认值)
def info(age, name='python'):
    print('age参数为:', age)
    print('name参数为:', name)  
    
# 为参数指定默认值之后,调用时候可省略指定的参数值,该参数使用默认值    
info(23)

info(45, 'abc')
info(11, 'Java')
# 混合方式
info(19, name='bcd')


# 定义带默认值的参数(两个参数有默认值)
def info(age=19, name='python'):
    print('age参数为:', age)
    print('name参数为:', name)
    
info()
info(20)
# 如果你希望省略前面的参数指定参数值,后面的参数应该用关键字参数来传入参数
info(name='go')

第四节:参数搜集和逆向参数收集

  • 参数收集
    • 普通参数收集
      • 在形参前面加上一个星号(*),这样就意味着该参数可接收多个参数值,多个参数值被当成元组传入
      • 参数收集的本质就是一个元组:Python会将传给带*参数的多个值收集成一个元组
      • Python允许个数可变的参数可以处于形参列表的任意位置,但是最多只能带一个支持“普通”参数收集的参数
      • 如果支持“普通”参数收集的形参位于前面,后面参数则需要使用关键字参数传值
# books参数支持收集,它可接受多个参数值
def test(num, *books):
    print("num:", num)
    print("books:", books)
# 将多个值自动封装成一个元组
test(5, "go", "python", "java")

def info(*names, msg):
    for name in names:
        print("%s, %s" % (name, msg))
# 如果你要为参数收集后的参数传入参数值,需要用关键字参数 
info("孙悟空", "猪八戒", "牛魔王", msg="欢迎大家") 
# 否则所有参数都会被参数收集成元组 
info("孙悟空", "猪八戒", "牛魔王", "欢迎大家")
    • 关键字参数收集
      • 在参数前面添加两个星号“**”,该参数支持关键字参数收集,收集的参数被当做dict处理
      • 一个函数可同时支持普通参数收集和关键字参数收集
# books参数支持普通参数收集,它可接受多个参数值,socres支持关键字参数收集
def test(num, *books, **socres):
    print("num:", num)
    print("books:", books)
    print("socres:", socres)
test(20, 'fkjava', 'python', 'swift', 语文=89, 数学=93)

def info(*names, msg, **socres):
    for name in names:
        print("%s, %s" % (name, msg))
    print(socres)
# 程序知道msg参数将是传给msg的,因此socres参数不会收集它
# dict的参数收集,它只收集不能明确传入的关键字参数
info("孙悟空", "猪八戒", "牛魔王", msg="欢迎大家", 语文=89, 数学=93) 
  • 逆向参数收集
    • 在列表、元组前添加*,在字典之前添加**
def test(a, b):
    print(a)
    print(b)

# 元组的逆向参数收集,以普通参数的形式为参数传入参数值
vals = (20, 40)
# 调用函数时,元组不能自动解包
# 默认情况下,元组是一个整体
test(vals)# 这个语句是错误的

# *对元组自动解包(逆向参数收集)
test(*vals)

# 列表的逆向参数收集,以普通参数的形式为参数传入参数值
msgs = ['aa', 'bb']
test(*msgs)

# 字典的逆向参数收集,以关键字参数的形式为参数传入参数值
# 简单来说,**是将字典解析成关键字参数
vals = {'a': 89, 'b': 93}
test(**vals)

第五节:变量作用域

  • 理解变量作用域
    • 根据定义变量的位置,变量的作用域分为两种:
      • 局部变量:在函数中定义的变量包括参数,都被成为局部变量
      • 全局变量:在函数外面、全局范围内定义的变量,被称为全局变量
# 全局变量
a = 35

def info():
    # 局部变量
    b = 'fkjava'
    # 正确,局部变量只能在当前函数内访问
    print(b)
    # 正确,全局变量可以在任何函数内访问
    print(a)
    
def info1():
    # 局部变量
    c = 'java'
    print(c)
    # 正确,全局变量可以在任何函数内访问
    print(a)
    # 错误,局部变量只能在定义局部变量的函数中使用
    #print(b)
    
info()
info1()
  • 变量字典
    • 获取变量字典
      • globals():该函数返回全局范围内搜所有变量组成的“变量字典”
      • locals():该函数返回当前局部范围内搜所有变量组成的“变量字典”
      • vars(object):获取指定对象的范围内所有变量组成的“变量字典”,如果不传入object参数,vars()和locals()作用完全相同
# 全局变量
a = 35
name = 'java'

def info():
    # 局部变量
    b = 'fkjava'
    # 正确,局部变量只能在当前函数内访问
    print(b)
    # 正确,全局变量可以在任何函数内访问
    print(a)
    
    # 局部变量组成的数组
    print(locals())
    
def info1():
    # 局部变量
    c = 'java'
    print(c)
    # 正确,全局变量可以在任何函数内访问
    print(a)
    # 错误,局部变量只能在定义局部变量的函数中使用
    #print(b)
    
    # 局部变量组成的数组
    print(locals())

# 全局变量组成的数组
print(globals())  

# locals获取当前范围内的所有局部变量
# 因此你在全局范围调用locals函数的时候,它返回全部的全局变量
# 简单来说,你在全局范围内,用globals和locals函数效果是一样的
print(locals()) 
  
info()
info1()
  • 处理局部变量遮蔽全局变量
    • 全局变量默认可以在所有函数内访问
    • 如果在函数中定义了与全局变量同名的变量,此时就会发生局部变量的遮蔽(hide)全局变量的情形
# 解决方法一
name = 'java'

def info():
    # 依然访问全局变量name
    print(globals()['name'])
    # 在函数内对变量赋值,变成了定义新的name变量
    name = 'python'
    print(name)
    
info()
# 全局变量name没有改变
print(name)


# 解决方法二
name = 'java'

def info():
    # 声明作用:该函数中的name始终使用全局变量
    global name
    # 依然访问全局变量name
    print(name)
    # 前面已经声明了name始终是全局变量
    # 因此此处不是重新定义局部变量
    name = 'python'
    print(name)
    
info()
# 全局变量name会被改变
print(name)

第六节:局部函数

  • 理解局部函数
    • 放在函数体内的函数称为局部函数
    • 在默认情况下,局部函数对外部是隐藏的,局部函数只能在其封闭(enclosing)函数内使用
  • 定义、使用局部函数
def foo():
    print('foo函数')
    # 嵌套函数:在其他函数内定义的函数
    def bar():
        for i in range(5):
            print('bar函数')
    # 只能在foo函数内调用bar函数
    bar()
# 在此处调用bar函数出错,局部函数只在它所在的封闭函数内有效
# bar()

foo()
  • 封闭函数返回局部函数
    • 封闭函数可以返回局部函数,以便程序在其他作用域中使用局部函数
    • 如果封闭函数没有将局部函数返回出来,那么局部函数将只能在封闭函数内部调用
def foo():
    print('foo函数')
    # 嵌套函数:在其他函数内定义的函数
    def bar():
        for i in range(5):
            print('bar函数')
    # bar表示返回函数本身(函数也相当于一个值,是function类型的值)
    # bar()表示调用(执行)函数
    return bar
    
# foo函数的返回值时bar函数,因此此处是用变量r来保存bar函数
r = foo()

print(r)
# 此时R引用bar函数本身,r的类型是function
print(type(r))

print('-' * 60)
# 由于r是函数,因此程序可以调用它
r()

# 下面代码看上去有点诡异
# foo函数调用之后返回bar函数,bar函数也可调用
foo()()
  • 局部函数的变量遮蔽
    • 局部函数内的变量也会遮蔽它所在的封闭函数的局部变量
    • 避免方法:可用nonlocal进行声明
def test():
    name = 'fkjava'
    def  info():
        print('info 函数')
        
        # 声明后面的name变量不是声明新的局部变量,而是引用所在封闭函数的局部变量
        nonlocal name
        print('name:', name)
        # 默认情况下,下面代码是为info这个局部函数再次定义name局部变量
        # 此时name局部变量就会遮蔽test函数的name变量
        name = 'crazyit'
        # 在没有用nonlocal声明之前,此时打印会出错,用nonlocal声明之后,程序正常
        print('name:', name)
    info()
    print(name)
test()
    • global与nonlocal总结
      • 作用大致相同,都是用来避免变量遮蔽
      • 区别:global用于声明访问全局变量。nonlocal用于声明访问局部函数所在封闭函数内的局部变量

第七节:案例实操-定义计算N的阶乘的函数

  • 实现方法
    • 方法一:使用循环计算阶乘
      • 控制循环计数器从1循环到N
      • 让循环计数器与前一个结果相乘,直到循环计数器等于N就得到了N的阶乘
def fract():
    r = 1
    if n < 1:
        print('n不能小于1')
        return
     else:
         for i in range(1, n + 1):
             r *= i
         return r
print(fract(5))
    • 方法二:运用递归计算阶乘
      • 经研究发现:N的阶乘等于N乘以N-1的阶乘,因此可借助于递归来实现
      • N为1时,N的阶乘是1,保证递归有结束点
def fract():
    if n < 1:
        print('n不能小于1')
        return
     # 对于递归函数来说,必须保证在某个条件下,函数不再调用自身,递归结束
     elif n == 1:
         return 1
     else:
         # 递归:就是函数里面调用自身
         return fract(n - 1) * n
         
print(fract(5))
    • 方法三:调用reduce函数计算阶乘
      • Python在functools模块提供了reduce()函数,该函数使用指定函数对序列对象进行积累
      • 可通过help(reduce)查看该函数的用法:reduce(function, sequence[, initial])



import functools
def fn(x, y):
    return x * y
    
def fract():
    if n < 1:
        print('n不能小于1')
        return
    else:
        '''
        # fn(ele1, ele2)->r
        # fn(r,ele3)->r
        # fn(r,ele4)->r
        '''
        # 方法一:
        return functools.reduce(fn, range(1, n + 1))
        
        # 方法二:
        # lambda x ,y: x * y 的本质就是一个函数
        return functools.reduce(lambda x ,y : x * y, range(1, n + 1))
print(fract(5))

第八节:案例实操-定义计算矩阵转置的函数

  • 使用循环进行转置
    • 首先创建一个长度与原矩阵第一个元素长度相等的新列表
    • 使用遍历原矩阵的每个元素,再使用嵌套循环遍历每个元素,将列表中的元素添加到新列表对应的列表元素中
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
'''
# 转置就是行变列 列变行
# 转置之前
1  2  3  4
5  6  7  8
9 10 11 12

# 转置之后
1  5  9
2  6 10
3  7 11
4  8 12
'''
def printmatrix(m):
    # 列表嵌套列表,因此ele也是列表
    for ele in m:
        # 打印一行
        for e in ele:
            print('%2d' % e, end=' ')
     print(' ')
     
def transformmatrix(m) :
    # m[0]有几个元素,说明原矩阵有多少列
    # 列转成行
    rt = [[] for i in m[0]]
    for ele in m:
        for i in range(len(ele)):
            # rt[i]代表新矩阵的第i行
            # ele[i]代表原矩阵当前行的第i列
            rt[i].append(ele[i])
     return rt
printmatrix(matrix)
print('-' * 60)
printmatrix(ransformmatrix(matrix))
  • 使用zip()函数转置
    • zip函数的作用正是合并多个序列:多个序列第一个元素合并成第一个元素,多个序列第二个元素合并成第二个元素......
    • 运用逆向函数收集即可


matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
def printmatrix(m):
    # 列表嵌套列表,因此ele也是列表
    for ele in m:
        # 打印一行
        for e in ele:
            print('%2d' % e, end=' ')
     print(' ')
     
def transformmatrix(m) :
    # 逆向参数收集,将矩阵中多个列表转换成多个参数,传给zip
    return list(zip(*m))
printmatrix(matrix)
print('-' * 60)
printmatrix(ransformmatrix(matrix))
  • 使用numpy模块转置
    • numpy模块提供transpose函数执行转置,该函数的返回值是numpy的内置类型:array
    • 调用array的tolist()方法可将array转换成list列表
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
def printmatrix(m):
    # 列表嵌套列表,因此ele也是列表
    for ele in m:
        # 打印一行
        for e in ele:
            print('%2d' % e, end=' ')
     print(' ')
     
def transformmatrix(m) :
    # 使用numpy模块的transpose函数进行转置
    import numpy
    return numpy.transpose(m).tolist()

printmatrix(matrix)
print('-' * 60)
printmatrix(ransformmatrix(matrix))

相关推荐

推荐一款Python的GUI可视化工具(python 可视化工具)

在Python基础语法学习完成后,进一步开发应用界面时,就需要涉及到GUI了,GUI全称是图形用户界面(GraphicalUserInterface,又称图形用户接口),采用图形方式显示的计算机操...

教你用Python绘制谷歌浏览器的3种图标

前两天在浏览matplotlib官方网站时,笔者无意中看到一个挺有意思的图片,就是用matplotlib制作的火狐浏览器的logo,也就是下面这个东东(网页地址是https://matplotlib....

小白学Python笔记:第二章 Python安装

Windows操作系统的python安装:Python提供Windows、Linux/UNIX、macOS及其他操作系统的安装包版本,结合自己的使用情况,此处仅记录windows操作系统的python...

Python程序开发之简单小程序实例(9)利用Canvas绘制图形和文字

Python程序开发之简单小程序实例(9)利用Canvas绘制图形和文字一、项目功能利用Tkinter组件中的Canvas绘制图形和文字。二、项目分析要在窗体中绘制图形和文字,需先导入Tkinter组...

一文吃透Python虚拟环境(python虚拟环境安装和配置)

摘要在Python开发中,虚拟环境是一种重要的工具,用于隔离不同项目的依赖关系和环境配置。本文将基于windows平台介绍四种常用的Python虚拟环境创建工具:venv、virtualenv、pip...

小白也可以玩的Python爬虫库,收藏一下

最近,微软开源了一个项目叫「playwright-python」,作为一个兴起项目,出现后受到了大家热烈的欢迎,那它到底是什么样的存在呢?今天为你介绍一下这个传说中的小白神器。Playwright是...

python环境安装+配置教程(python安装后怎么配置环境变量)

安装python双击以下软件:弹出一下窗口需选择一些特定的选项默认选项不需要更改,点击next勾选以上选项,点击install进度条安装完毕即可。到以下界面,证明安装成功。接下来安装库文件返回电脑桌面...

colorama,一个超好用的 Python 库!

大家好,今天为大家分享一个超好用的Python库-colorama。Github地址:https://github.com/tartley/coloramaPythoncolorama库是一...

python制作仪表盘图(python绘制仪表盘)

今天教大家用pyecharts画仪表盘仪表盘(Gauge)是一种拟物化的图表,刻度表示度量,指针表示维度,指针角度表示数值。仪表盘图表就像汽车的速度表一样,有一个圆形的表盘及相应的刻度,有一个指针...

总结90条写Python程序的建议(python写作)

  1.首先  建议1、理解Pythonic概念—-详见Python中的《Python之禅》  建议2、编写Pythonic代码  (1)避免不规范代码,比如只用大小写区分变量、使用容易...

[oeasy]python0137_相加运算_python之禅_import_this_显式转化

变量类型相加运算回忆上次内容上次讲了是从键盘输入变量input函数可以有提示字符串需要有具体的变量接收输入的字符串输入单个变量没有问题但是输入两个变量之后一相加就非常离谱添加图片注释,不超过1...

Python入门学习记录之一:变量(python中变量的规则)

写这个,主要是对自己学习python知识的一个总结,也是加深自己的印象。变量(英文:variable),也叫标识符。在python中,变量的命名规则有以下三点:>变量名只能包含字母、数字和下划线...

掌握Python的&quot;魔法&quot;:特殊方法与属性完全指南

在Python的世界里,以双下划线开头和结尾的"魔法成员"(如__init__、__str__)是面向对象编程的核心。它们赋予开发者定制类行为的超能力,让自定义对象像内置类型一样优雅工...

11个Python技巧 不Pythonic 实用大于纯粹

虽然Python有一套强大的设计哲学(体现在“Python之禅”中),但总有一些情况需要我们“打破规则”来解决特定问题。这触及了Python哲学中一个非常核心的理念:“实用主义胜于纯粹主义”...

Python 从入门到精通 第三课 诗意的Python之禅

导言:Python之禅,英文名是TheZenOfPython。最早由TimPeters在Python邮件列表中发表,它包含了影响Python编程语言设计的20条软件编写原则。它作为复活节彩蛋...

取消回复欢迎 发表评论: