0
点赞
收藏
分享

微信扫一扫

日常分享,Python必备技能点-函数

生活当中有许多一些重复且有规律的事情,比如计算圆的面积:S=πr2,这时公式是固定的,我们来看一段代码:

#计算3个圆的面积
r1 = 11.3
r2 = 5.6
r3 = 9.4

s1 = 3.14*r1*r1
s2 = 3.14*r2*r2
s3 = 3.14*r3*r3

如果有一千个圆,一万个圆呢?难道这样去写一千次一万计算吗?这个时候就要用到函数了,函数是一个实现特定功能的代码模块。

'''
计算圆的面积
'''
def get_area_of_circle(r):
    print('circle\'s area:',3.14*r*r)

我准备了一些爬虫案例,还有一些小游戏源码,你们自取:

点击蓝色字体,直接拿

在这里插入图片描述

​ 在python中,函数分为两种,一种是内置函数,一种是自定义函数:

内置函数:python解释器内定义完成,调用即可。如:print(),int()等

自定义函数:自己根据特定功能定义的函数

无参函数

#无参函数
def welcome():
    print('欢迎来到python世界!')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JFoUBDJp-1650009117985)(C:\Users\图灵python学院\Desktop\课件\1,python\images\6\6-1.png)]

有参函数

无参函数内部代码功能比较固定,当函数需要更加灵活的配置时候,可以定义有参函数来解决问题。

形参与实参

形参:在函数定义阶段定义的参数为形参,声明传入变量的含义,等于变量名

实参:在调用函数阶段传入的值,等于变量的值

在定义阶段,形参跟实参没有任何关系。调用时,实参会绑定复制给形参,且在函数体内生效。函数调用结束后接触绑定关系。

位置参数

​ 从左到右按顺序定义的参数叫位置参数,实参的传值必须跟形参一一对应。

#位置参数
def show_info(name,age):
    print('my name is %s,i\'m %s years old!'%(name,age))
    
#函数调用
show_info('张三',18)

关键字参数

除了位置参数以外,也可以按照key-value形式传值。

位置参数可以跟关键字参数混用,但是注意两点:1,位置参数必须在关键字参数之前 2,不能为同一个形参重复传值

#关键字传参
show_info(name='张三',age=18)

#混合传参
show_info('李四',age=18)

默认参数

默认形参:在定义函数阶段就对形参进行赋值,调用时可以不赋值

注意:默认形参推荐使用不可变类型!

#默认形参
def show_info(name,age,country='中国'):
    print('我叫%s,我今年%s岁,我的祖国是%s!'%(name,age,country))

show_info('张三',18)

#结果
我叫张三,我今年18,我的祖国是中国!

可变长参数

当函数在调用时不确定传入的实参个数时,就可以使用可变长参数来定义形参。

函数在调用时有位置参数与关键字参数两种形式,因此可变长参数也分别提供了对应的解决方案。

*args:溢出的关键字以元组的形式保存,用于接受溢出的位置实参

#可变长参数
#需求:定义一个求和的函数,但是传入的数字个数不确定
#格式:*args 星号后可跟任意名字,约定俗成为args,溢出实参以元组形式保存赋值
def count_num(*args):
    res = 0
    #迭代元组元素并相加
    for item in args:
        res+=item
    print('和为:%s'%res)

count_num(1,2,3,4,5)

实参在传值时也能使用*,*后的值会被拆分成对应的位置实参

#实参带*
def print_num(x,y,z):
    print(x,y,z)

print_num(*[1,23])

形参实参都使用*

#形参实参都带*
def print_num(x,y,*args):
    print(x,y,args)

print_num(1,2,3,4,5,6)
print_num(1,2,*[3,4,5,6])

**kwargs:溢出的关键字以字典的形式保存,用于接受溢出的关键字实参

#**kwargs 接收溢出的关键字实参
#接收学员信息的函数
def student_info(name,age,**kwargs):
    print(name,age,kwargs)

student_info('张三',18,gender=3,country='chinese')

#实参使用**
student_info(**{'name':'李四','age':18,'gender':6,'country':'chinese'})

混用*与**,*args必须在**kwargs之前

#能够接收任意函数
def func(*args,**kwargs):
    print(args,kwargs)

func(1,2,3,4,name='王五',gender=6)

函数返回值

在调用函数需要结果时,可以使用return关键字返回运算结果

#return 返回函数运算结果
def count_num(*args):
    res = 0
    #迭代元组元素并相加
    for item in args:
        res+=item
    #返回运算结果
    return res

#接收函数返回值
num = count_num(1,2,3,4,5)

如果需要声明一个函数,但是留待后续开发,可以使用关键字pass

#pass关键字 声明空函数
def func(name,age):
    pass

命名空间与作用域

A namespace is a mapping from names to objects. Most namespaces are currently implemented as Python dictionaries

程序内部的代码生效范围有层级,层级范围叫做命名空间,不同空间内的变量生效范围大小不一

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K08RikID-1650009117987)(C:\Users\图灵python学院\Desktop\课件\1,python\images\6\6-2.png)]

内置命名空间

​ 范围最大,python解释器启动时产生,关闭时销毁。内置函数与异常都属于这个范围,如print,input等,任何模块都可访问它,

#内置名称空间 <built-in function print>
print(print)

全局命名空间

​ 模块的全局命名空间在模块定义被读入时创建;通常,模块命名空间也会持续到解释器退出。 模块内所有代码(类,函数,变量,常量)与其它模块内导入所有代码都属于这个范围

局部命名空间

​ 一个函数的局部命名空间在这个函数被调用时创建,并在函数返回或抛出一个不在函数内部处理的错误时被删除。每次递归调用都会有它自己的本地命名空间。

当程序去寻找一个变量 x 时,它的寻找顺序如下:

​ 1,局部命名空间:当前函数或类的方法内,如果找到该变量则停止搜索

​ 2,全局命名空间:当前模块内,如果找到了名字为x的类,函数,变量则停止搜索

​ 3,内置命名空间:如果上述都没有找到,则会在内置函数或变量寻找

​ 4,以上都没找到则会报错: NameError: name ‘xx’ is not defined。

#命名空间1
x = 1

def func1():
    print(x)

def func2():
    x = 2
    print(x)
    func1()

func1()
func2()

#命名空间2
input=111
def func3():
    input = 222
    print(input)

func3()

#命名空间3
x = 111
def func4():
    print(x)
    x = 222

func4()

global与nonlocal关键字

locals():查看所有局部命名空间

globals():查看所有全局命名空间

global:在函数内声明该变量为全局对应变量

nonlocal:修改函数外层函数内对应变量

#global关键字
x = 111
def func():
    global x
    x = 222
    print(x)

func()

#nonlocal关键字
x = 111
def func1():
    x = 222
    def func2():
        nonlocal x
        x = 333
        print('func2的x:',x)
    func2()
    print('func1的x:',x)

func1()

函数的引用

函数的引用本质是一个存储函数地址的变量,同样也可以对它做变量相同的操作。

'''
@AUTHOR:小帅
@FILE:2_函数引用操作.py
@DATE:2022/2/18
'''

#函数引用赋值
def func1():
    print('hello world!')

f = func1
print(f,func1)
func1()


#函数引用传参
def func2(func):
    print(func)

func2(func1)


#函数引用作为容器元素
def func3():
    print('i\'m func3!')

def func4():
    print('i\'m func4!')

def func5():
    print('i\'m func5!')

func_dict = {'f3':func3,'f4':func4,'f5':func5}
#调用
func_dict['f3']()

闭包函数

**闭包:在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。**

​ 闭指内部函数是封闭的,定义好以后外部不能直接访问与修改。包则指的是包裹内部函数的外部函数。

注意: 返回闭包中不要引用任何循环变量,或者后续会发生变化的变量。

#闭包函数
#外部函数
def outer():
    #局部变量
    name = '张三'
    #内部函数
    def inner():
        print(name)
    #返回内部函数地址
    return inner
#闭包错误使用
def func1(*args):
    ls = []
    for i in range(0,4):
        def func2():
            return i*i
        ls.append(func2)
    return ls

func3 = func1()
print(func3[0]())
print(func3[1]())
print(func3[2]())

装饰器

装饰器就是用于拓展原有函数功能的一种函数,在不修改原有函数代码的前提上给原有函数加上新的功能。

开闭原则:对功能拓展部分是开放的,对源代码的修改是封闭的

'''
@AUTHOR:小帅
@FILE:3_装饰器.py
@DATE:2022/2/18
'''
import time

#计算数字之和
def count(num):
    res = 0
    for i in range(0,num+1):
        res+=i
    print(res)

#需求:给上述函数加上计算函数运行功能
#思考:如何去设计一种合理方便的方式
def decorator(func):
    #内部函数添加功能
    def wrapper(*args,**kwargs):
        start = time.time()
        #调用传入函数
        func(*args,**kwargs)
        #睡眠3秒,模拟执行时间
        time.sleep(3)
        end = time.time()
        print('执行时间:',(end-start))
    return wrapper

# count = decorator(count)
# count(100)

#语法糖调用方式
@decorator
def show():
    print('hello world!')

show()

有参装饰器

#需要对用户实名制进行验证
def check_name(bool):
    def deco(func):
        def wrapper(*args,**kwargs):
            if bool==True:
                print('您已经实名制,可以发言!')
                res = func(*args,**kwargs)
                return res
            else:
                print('您没有实名制,不能评论!')
        return wrapper
    return deco

#评论函数
@check_name(False)
def comments():
    comm = input('请输入您的评论:')
    print(comm)

comments()
↓ ↓ ↓ 加下方名片找我,直接拿源码还有案例 ↓ ↓ ↓
举报

相关推荐

0 条评论