函数

一、函数的基本使用

1.函数简介

  函数就类似于是一个工具,是提前定义好的一个功能,以后想用,就调用函数使用。

2.函数的语法结构  

def my_len(a,b):
    '''函数注释'''
    print(123)
    return

"""

  1. def 定义函数的关键字,不能省略

  2. my_len

    函数名,不能省略,必须要写;函数名的命名遵循变量名的命名

  3. def my_len(参数1,参数2):

    参数是可有可无的,参数就是在执行函数的时候要提前满足的条件

  4. 函数注释

    可有可无,一般情况函数注释是用来介绍函数的功能、参数代表的意思,以及返回值的情况等信息

  5. 函数体

    函数体也是可以可无的,一个函数只能有一个return返回值

"""

3. 函数的定义与调用

  

##########################################
    1.函数必须先定义后调用
    2.函数在定义阶段只检测语法错误,不执行函数体代码
    3.只有在函数调用阶段,才会执行函数体代码
    4.如何调用函数:
            函数名加括号,如果有参数,在调用的时候也要把参数一起传过去
##########################################

函数在定义阶段和调用阶段的底层原理:

  1.在内存空间中申请一块地址,来存储函数体代码

  2.把函数体代码所在的空间地址绑定给函数名

  3.通过调用函数来执行函数体代码

4.函数的分类

  4.1 内置函数

    内置函数:Python解释器自带的函数,可以直接拿来使用,比如 print、len等

  4.2 自定义函数

    无参函数:没有参数的函数,括号里面没有参数的函数

    def index():
        pass

    有参函数:有参数的函数就叫有参函数,括号里面有参的函数

            def index(a,b):
                print(a+b)
            index(1,2)

    空函数:就是没有函数体的代码,空函数可以帮助我们梳理代码思路

        def register():
            pass

        def login():
            pass
         
        def order():
            pass

        def car_shopping():
            pass

        def address():
            pass

5. 函数的返回值

  返回值的关键字是return。

"""

  1.函数内如果没有return关键字,那么,函数的返回结果就是None

  2.函数内如果只有return关键字,那么函数的返回结果仍是None

  3. 函数内有了return关键字,return后面写什么就返回什么,谁调用,返回结果就给谁

  4.函数内遇到了return关键字就直接终止函数的运行

  5.一个函数内只能有一个return结果

  6.return后面也可以返回多个值,如果使用逗号隔开,那就以元组的形式返回,也可以直接返回列表、字典等类型

二、函数的参数

1.参数的分类

  1.1 形式参数

    在‘函数定义阶段’括号内依次写入的变量名就是形式参数,简称‘形参’

        def index(a,b,c):
            pass
        # a,b 就称之为是函数的形参

  1.2实际参数

    在‘函数调用阶段’括号内依次传入的变量值就叫实际参数,简称‘实参’

    def index(a,b,c):
        print(a+b+c)
    index(1,2,3)
    #1,2,3就称之为函数的实参

'''

形式参数和实际参数之间的关系:

  把实际参数传递给形式参数,以形参=实参的形式传入,即以变量名=变量值的形式传入。

  形参就相当于是变量名,实参相当于变量值。

  形参和实参在函数调用阶段临时绑定,在函数调用结束后,结束绑定。

'''

   函数的形参形式其实只有一种,那就是变量名

   函数的实参有很多种方式,但是抓住本质就是数据值

2.位置参数和关键字参数(重点)

  2.1 位置参数

    在函数括号内依次写入的参数就是位置参数

    位置形参:在函数定义阶段括号内从左往右依次写入的变量名就是位置形参

        def index(a,b,c,d):
            pass
        # a,b,c d就是位置形参

    位置实参:在函数调用阶段括号内从左往右依次写入的数据值就是位置实参

      index(1,2,3,4)
      # 1,2,3,4就是位置实参

  2.2 关键字实参:可以打破原来的顺序传递,就是传递参数不按顺序传递

register(age=18, name='kevin', gender='female')
register('kevin', age=18, 'female') # 不行,位置参数不能跟在关键字的后面
register('kevin', age=18, gender='female') #
register(age=18, 'kevin', gender='female') # 不行
register('kevin', name=18, gender='female') # 不行
'''位置参数不能写在关键字的后面,越简单的参数越靠前'''

3.默认参数

  前提是默认的形参

  在函数定义阶段就可以给参数赋值了

    1.如果你在函数调用阶段,没有给形参传值,那就是要默认的

    2.如果你在函数调用阶段,给形参传值了。就是要你传的值

# 练习1:如果默认值是列表的话,比较特殊:以后所有调用该函数的时候,hobby用的都是同一个
def register(name, age, hobby=[]):
    hobby.append(age)
    print('%s:%s:%s' % (name, age, hobby))
register('kevin', 18,)   # kevin:18:[18]
register('jason', 19,)    # jason:19:[18, 19]
register('tank', 20,)     # tank:20:[18, 19, 20]
# 练习题2:(笔试题)
m = 100
def func(a,b,c=m):
    print(a,b,c)   # 1 2 100

m = 400
func(1,2)
"""
两个角度理解
    角度1:
        在函数定义阶段,参数的值就已经固定死了,不能修改
    角度2:
        根据变量名和变量值在内存中关系来判断
"""

4. 可变长参数

1. 在调用函数的时候,传入多少个位置参数,都能正常运行

def index(name, password, x, y, *a):
    print(name, password, a, x, y)
    # print(a[0])
    # print(a[1])
    # print(a[2])


# print(a, b, c, d)
'''*号在形参中的使用:会接收多余的位置参数'''
# index('kevin', 123, 1, 2, 3, 4, 5, 6)  # kevin 123 (1, 2, 3, 4, 5, 6)
# index('kevin', 123)  # kevin 123 ()
# index('kevin', 123, 3, 4, 5, 6, 7, y=2, x=1, )  # kevin 123 () 1 2
# index('kevin', 123, y=2, x=1, 3, 4, 5, 6, 7, )  # kevin 123 () 1 2

2. 不管我们在调用函数的时候,传入多少个关键字参数,都能正常运行
"""
  **号在形参中的使用:
    接收多余的关键字参数
"""

def index(username, age, gender, hobby, **a):
    print(username, age, gender, a )# kevin 18 {'gender': 'male', 'hobby': 'read', 'a': 1, 'b': 2, 'c': 3}
    # {'hobby': 'read', 'a': 1, 'b': 2, 'c': 3}

# index(1,2)
# index(a=1,b=2)
# 关键字传参就是指名道姓的传递
# index(b=1,a=1)

d = {'username': 'kevin', 'age': 18}
# index(username='kevin', age=18)# 可行
# index(d.get('username'), d.get('age'))# 可行
# index(username=d.get('username'), age=d.get('age')) # 可行
# index(username=d.get('username'), age=d.get('age'),gender='male', hobby='read',a=1,b=2,c=3)
index(username=d.get('username'), age=d.get('age'),gender='male', hobby='read',a=1,b=2,c=3)

3. 不管我传入多少个位置参数和关键字参数,函数都能正常运行

def index(*a, **b):
    print(a, b)

# (1, 2, 3)  {'x': 1, 'y': 2, 'z': 3, 'm': 10, 'n': 20}
index(1, 2, 3, 4, k=10, x=1, y=2, z=3, m=10, n=20, )

"""
注意:
*号和**号后面的变量可以任意起名,遵循变量的命名即可
在python中,推荐使用
*args: arguments 位置参数
**kwargs: keyword arguments 关键字参数
以后在定义函数的时候,如果我们不知道要传递多少个参数,我们就可以如下定义
def index(*args, **kwargs):
pass
"""

# *号和**号在实参中的使用

def index(*args):
    print(args)


# index(1,2,3,4,)

# l = [1, 2, 3, 4, 5, 6, 7, 8, 9, ]
t = (1, 2, 3, 4, 5, 6, 7, 8, 9, )
# index(l[0], l[1], l[2], l[4], l[4],)  # index(1,2,3,4,5)

'''
*在实参中的使用,就是把列表、元组中的一个一个元素打散,然后以位置参数的形式传递
'''
# 针对列表这种里面肯能存放多个元素的时候,我们利用*打散成一个个的元
# *l 就把列表中的元素,挨个打散

 index(*l)  # (1, 2, 3, 4, 5, 6, 7, 8, 9)-----------> index(1,2,3,4,5,6,7,8,9)
index(*t)  # (1, 2, 3, 4, 5, 6, 7, 8, 9)-----------> index(1,2,3,4,5,6,7,8,9)

"""
**号在实参中的使用:把字典打散成关键字的形式进行传递
"""

def func(**kwargs):
    print(kwargs)  # {'username': 'kevin', 'age': 18, 'gender': 'male'}\
    # print(kwargs.get('username'))
    # print(kwargs.get('age'))
    # print(kwargs.get('gender'))


# func(username='kevin', age=18, gender='male')

d = {'a':1, 'b':2, 'c':3, 'd':4,'e':5}

# func(a=d.get('a'), b=d.get('b'))

# func(a=1,b=2,c=3,d=4,e=5)
func(**d)  # {'a': 1, 'b': 2, 'c': 3, 'd': 4}

5.名称空间

  5.1 什么是名称空间?

  就是绑定变量名与变量值关系的地方

  5.2 名称空间的分类

    1.内置名称空间:# python内置的,可以直接拿来使用的, len,print

    2.全局名称空间:# 在py文件中,顶格写的变量都是在全局名称空间中

            name ='jason' # name就是全局变量,它就在全局名称空间中存着

    3.局部名称空间:在函数中存在的都是局部的

6.名字的查找顺序

# len = 'helloworld'

# print(len) # helloworld

name = 'tank'

def index():
    # name = 'kevin'
    print(name)

index()

"""
  名字的查找:
    在全局:先看你自己再哪个位置
      全局 >>> 内置

      在局部:先看你自己再哪个位置
      局部 >>> 全局 >>> 内置
"""

验证变量的查找顺序: 局部 >>> 全局 >>> 内置

 名称空间的作用域

作用域:变量能够作用的范围

 global和nonlocal关键字的使用

1.global

在函数的内部不能直接修改外部的变量:

  在函数的内部修改外部的不可变的数据类型需要使用global关键字声明

age = 18
def index():
    if age == 10:
        print('from index')
index()


#########################################
# 可变类型

name_list = ['kevin', 'jason', 'tank']


def index():
    name_list.append('tony')


index()

2.nonlocal(很少使用)

 在函数内部的局部修改外部的局部的不可变类型的数据使用关键字nonlocal关键字声明

函数对象(函数名)

函数对象的四种使用方法:

1、函数名可以当做变量名来使用

def index():  # index它是属于全局的
     print('index')

"""函数名就是函数的内存地址"""
# print(globals())  # 'index': <function index at 0x00000123F32BE310> value值就是函数的内存地址
# print(index)
# index() # 直接调用函数
a = index
a()  # index()

 

2、函数名也可以当成函数的实参

# def index():
#     print('from index')
#
#
# def func(func_name):
#     # func_name----->index
#     print('from func')
#     func_name() # 相当于是index()
#
#
# func(index)

 

3、函数名也可以当成函数的返回值

# def index():
#     print('from index')
#
#
# def func():
#     print('from func')
#     # return index()  # None
#     return index
#
# res=func()  # res是函数的内存地址
# res()  # index()
# print(res)

 

4、函数名也可以当成容器类型的元素

def index():
    print('from index')


# l = [1, 2, 3, index()]
l = [1, 2, 3, index] # [1, 2, 3, <function index at 0x0000021226FCE310>]
print(l)
l[3]()  # 调用index函数

 

posted @ 2023-05-26 21:21  Maverick-Lucky  阅读(55)  评论(0)    收藏  举报