欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

函数基础

程序员文章站 2022-03-19 12:04:16
...

介绍

  • 什么是函数

在编程的过程中,会出现代码冗余,可读性差,不易修改,所以出现了函数,函数类似一个工具,这个工具可以拿过来直接使用

  • 定义一个函数

当python遇到 def 语句时候 ,会在内存中生成一个函数对象,并且这个函数是靠将函数名来引用,但是这个函数体
内部的语句只有在函数的调用的时候才会被执行,而函数调用结束了,就是函数返回时,函数执行完后内部变量将会被回收

def 函数名(形参1,形参2...):
  '''函数的注释,描述函数的作用以及参数的类型'''
  代码块
  ...
  return   # return可以获取函数执行后的返回值,也可以结束函数的运行

1.函数名的定义类似变量名
2.函数名加括号立即执行函数体代码 优先级最高
3.函数必须先定义再调用

func(10,20)  # 报错,因为函数必须先 定义 在 引用(调用)
def func(x,y):  # 定义函数
    if x > y:
        print(x)  # return x  返回值 x
    else:
        print(y)  # return y  返回值 y
func(2,5)  # >>> 5  函数名加括号立即执行函数体代码
res = func(2,5)
print(res)   # 返回值 None
print(func)  # <function func at 0x0000027893BE2EA0> func 对应的是函数的内存地址

函数的返回值 return

  • 不写 return 返回值 None

def func():
    print('waller')
func()  # >>> waller
res = func()  # 定义变量接收给返回值
print(res)  # >>> None
  • 只写 return 返回值 None 除此之外还可以结束函数的运行

def func():
    l = [1,2,3]
    while True:
        for i in l:
            if i == 2:  # 当 i == 2 时结束整个循环需要两个break,分别结束for和while
                #break
                return  # 函数里的return可以结束整个函数,之后的代码永远不执行
            print(i)
            # else:
            #     print(i)
        # break

res = func()
print(res)  # >>> None
  • 只写 return None

def func():
    return None
res = func()
print(res)  # >>> None
return 返回一个值,这个值可以是任意类型
def func1():
    return 123
def func2():
    return 'waller'
def func3():
    return [1,'age']
def func4():
    return (1,)
def func5():
    return {'hubby':'read'}
def func6():
    return {1,}
def func7():
    return True
print(func1(),func2(),func3(),func4(),func5(),func6(),func7())
# >>> 123 waller [1, 'age'] (1,) {'hubby': 'read'} {1} True
return 返回多个值 返回的时一个元组,函数处理的结果不想被修改
def func1():
    return 1,2,3,'a','b'
res1 = func1()
print(res1)  # >>> (1, 2, 3, 'a', 'b')

def func2():
    return [1,2],['a',1]
res2 = func2()
print(res2)  # >>> ([1, 2], ['a', 1])

def func3():
    return {'name':'waller'},{'age':20}
res3 = func3()
print(res3)  # >>> ({'name': 'waller'}, {'age': 20})

# 返回多个值,不想函数处理成元组,可以自己动手加上数据类型符号,使多个值变成一个值
def func4():
    return [{'name':'waller'},{'age':20}]  # 利用return打印一个值的特点
res4 = func4()
print(res4)  # [{'name': 'waller'}, {'age': 20}]

注意:

1.所有的函数都有返回值
2.只写return 或return None 不是为了返回值,是为了结束函数的运行

参数

形参:在函数定义阶段括号内的参数,这个形参相当于变量名,简称 形参
实参:在函数调用截断括号内的参数,这个参数相当于变量值,简称 实参
  • 形参与实参的关系:

形参相当于变量名,实参相当于变量值

函数调用传参的阶段,就是实参变量值给形参变量名赋值的过程

注意:

形参和实参的绑定关系只有在函数调用阶段生效,函数运行完自动解除绑定关系

只有在函数内部有效,函数外部无影响

def func(x,y):
    '''
    函数的作用以及参数的类型
    :param x:
    :param y:
    :return:
    '''
    print('waller')
    return  'wong'
print(help(func))  # 打印出函数的注释
  • 位置传参:

位置形参:在函数定义阶段,括号内从左到右依次写入的变量名较叫位置形参,调用时必须为其传值

位置实参:在函数调用阶段,对应位置形参依次在括号内填入的值,这些值会一一传给形参(类似变量名赋值)

def num_max(x,y):  # x,y 是位置形参,需要传值
    if x > y:
        return x  # 若x > y 返回值是 x
    else:
        return y  # 否则 返回值是 y
res = num_max(2,6)  # 2和6 是位置实参,按照x与y的位置传递参数 x = 2,y = 6
print(res)  # 打印函数的返回值  >>> 6

res = num_max(5)  # 报错 ,位置实参传参个数少于形参数
res = num_max(2,6,7)  # 报错,位置实参传参个数多余形参数
  • 关键字传参:

在函数调用阶段,按照形参的变量名 赋值

def num_max(x,y):  # x,y 是位置形参,需要传值
    if x > y:
        return x  # 若x > y 返回值是 x
    else:
        return y  # 否则 返回值是 y
res = num_max(y=6,x=2)  # 按关键字为形参传参
print(res)  # >>> 6
res = num_max(y=6,x=2,x=1)  # 报错,同一个形参不能被多次传值

res = num_max(2,y=6)  # 位置参数和关键字参数同时使用
res = num_max(y=6,2)  # 报错,关键字参数要在位置参数后面

注意:

位置传参和关键字传参和混合使用,但关键字传参要在位置传参的后面

同一个参数不能被多次赋值

  • 默认参数:

定义:在函数定义阶段,形参(变量名)就已经被赋值了

在调用阶段,可以不为默认形参传值,默认使用定义阶段绑定的值

在调用阶段,如果为默认形参传值,就使用调用阶段传入的值

注意:定义阶段,默认形参要在位置形参的后面

应用场景: 当形参接收的值大多数是相同值的情况下,可以使用默认形参

def num_max(x,y=100):
    if x > y:
        return x
    return y
res = num_max(50)  # x = 50 y = 100  # 传入位置参数 50给形参x,形参y不传值,使用默认参数
print(res)  # >>> 100

res1 = num_max(50,20)  # x = 50 y = 20  # 传入位置参数 50给形参x,20给形参y
print(res)  # >>> 50


def info(name,age,gender = 'male'):  # gender = 'male' 是默认参数
    print('name is {},age is {},gender is {}'.format(name,age,gender))
info('waller',20)  # >>> name is waller,age is 20,gender is male
info('wong',24)  # >>> name is wong,age is 24,gender is male
info('tuan',22,'female')  # >>> name is tuan,age is 22,gender is female
  • 可变长参数

形参中的 * 可以将实参中多余的位置参数组成元组的形式赋值给形参中*后面的变量名,不能接收关键字实参

实参中的 * 可以将实参中除字典的容器类型数据打散,依次赋值给形参

形参中的 ** 可以将实参中多余的key=value的关键字形式实参存成字典的形式 赋值给形参中** 后面的变量名,不能接收其他容器类型的实参(俗称封装)

实参中的 ** 会将实参中的字典类型数据,按照key=value的关键字传参的形式赋值给形参(俗称打散)

python 推荐*和**写法:

def func(*args,**kwargs):  # 调用者按照正确的传参方式无论怎么传都可以接受
    print(args,kwargs)

 

# 形参中的 *
def func(x,y,*z):
    print(x,y,z)
func(1,2,3,4,5,6,)  # >>> 1 2 (3, 4, 5, 6)  z = (3, 4, 5, 6)

 

# 实参中的 *
def func(x,y,z):
    print(x,y,z)
func(*[1,2,3,])  # >>> 1 2 3

def func(x,y,z):
    print(x,y,z)
func(*('a','b',1))  # >>> a b 1

def func(x,y,z):
    print(x,y,z)
func(*{'a',(1,2),5})

def func(x,y,*z):
    print(x,y,z)
func('a',5,*[1,2,3])  # a 5 (1, 2, 3)

 

# 形参中 ** 
def func(x,**y):
    print(x,y)
func(x='a',y='b',z='c',d=1,e=2)  # y = {'y': 'b', 'z': 'c', 'd': 1, 'e': 2}
# >>> a {'y': 'b', 'z': 'c', 'd': 1, 'e': 2}

 

# 实参中的 **
def func(x,y):
    print(x,y)

d = {'x':'waller','y':20}
func(**d)

函数是第一类对象

  • 函数名可以被传递(类似变量)

name = 'waller'
ures_name = name  # 变量名的传递
print(ures_name)  # >>> waller

def func():
    print('name is waller')
print(func)  # 打印的是函数体代码的内存地址  <function func at 0x000002EF3AA02EA0>
print(id(func))  # 打印的是函数名在内存里的地址  3226504015520
f = func  # func对应的函数内存地址也赋值给f
print(f)  # 打印的是函数体代码的内存地址  <function func at 0x000002EF3AA02EA0>

f()  # 调用函数,等价与func()

 

函数基础

  • 函数名可以被当作参数传递给其他函数

def func():
    print('from func')

def info(regs):
    print(regs)  # <function func at 0x000001A378C62EA0>
    regs()  # from func
    print('from info')  # from info
info(func)

函数基础

  • 函数的名可以被当作函数的值被返回

def func():
    print('from func')
def info():
    print('from info')
    return func
info()  # >>> from info 是打印函数运行的结果,并且由返回值可接收
res = info()  # >>> from info # 函数的返回值赋值给变量 res
print(res)  # >>> <function func at 0x000002C27E772EA0> # 等价于 print(func)
res()  # >>> from func # 等价于 func()
  • 函数名可以当作容器类型数据里的元素

def func():
    print('from func')
print(func())  # 优先运行func()函数,运行结果是from func,有返回值None被print打印了出来9
l = [1,2,func,func()]  # 容器类型数据是把func()函数的 返回值 放入其中,而不是函数运行结果
print(l)  # >>> [1, 2, <function func at 0x0000024143502EA0>, None]

函数的嵌套

在函数内部调用其他函数,可以使复杂的逻辑简单化
def my_max(x,y):  # 定义可以比较两个数大小的函数
    if x > y:
        return x
    return y
# print(my_max(2,5))  # >>> 打印出函数运行的返回值

def my_max1(a,b,c,d):
    res1 = my_max(a,b)  # 接收两个数比较后的返回值
    res2 = my_max(res1,c)
    res3 = my_max(res2,d)
    return res3  # 接收最终的返回值
print(my_max1(2,4,6,8))  # >>> 8 # 打印出四个数比较大小的返回值

函数基础

名称空间

存放变量名的地方,存放的使变量名与变量地址绑定关系的地方
要想访问一个值,必须要到名称空间找到变量名才能访问到变量值

函数基础

  • 名称空间分类

内置名称空间:python解释器提前定义好的名字存在了内置名称空间(len,max,print,range...)

全局名称空间:文件级别的代码,一般是程序员按照变量名命名规范所起的变量名

局部名称空间:函数体内创建的变量名都属于局部名称空间

  • 名称空间生命周期

1.内置名称空间:python解释器启动创建,python解释器关闭自动销毁

2.全局名称空间:右键运行py文件创建,py文件运行完毕自动销毁

3.局部名称空间:函数调用时创建,函数运行结束立即销毁(动态创建,动态销毁)

  • 名称空间查找顺序

先确定当前位置(*****):

如当前位置在全局:全局 >>> 内置

如当前位置在局部;局部 >>> 全局 >>> 内置

x=111
def outer():
    def inner():
        print('from inner',x)  # 函数在定义阶段名字的查找顺序就已经确定了
    return inner
f=outer()
def func():
    x=333
    f()  # 不会应为函数的调用位置变化而改变
func()  # >>> from inner 111

函数在定义阶段名字的查找顺序就已经确定了,不会应为函数的调用位置变化而改变(*****)

函数在定义时还没有生产函数的名称空间,只有调用时才会生产

作用域

全局作用域:全局生效

局部作用域:局部生效

global:局部修改全局,如修改多个,用逗号隔开

# 局部修改全局
name = 'waller'
age = 20
def func():
    global age,name  # 声明
    age = 22
    name = 'wong'
    print(name,age)
func()  # wong 22
print(name)  # wong
print(age)  # 22

nonlocal:局部修改局部,如修改多个,用逗号隔开

# 局部修改局部
def func():
    x = 1
    def info():
        nonlocal x
        x = 2
    info()
    print(x)
func()  # >>> 2

 

相关标签: 函数