大数据技术之_23_Python核心基础学习_03_函数 + 对象(12.5小时)

本文详细讲解了Python中的函数和对象概念。涵盖了函数的定义、参数、返回值、递归、高阶函数、闭包以及装饰器。在对象部分,介绍了面向对象编程,包括类的定义、属性和方法、封装、继承、多态,以及模块化和标准库的使用。适合Python初学者和进阶者学习。
摘要由CSDN通过智能技术生成

第五章 函数

5.1 函数的简介

- 函数也是一个对象
-   对象是内存中专门用来存储数据的一块区域
-   函数可以用来保存一些可执行的代码,并且可以在需要时,对这些语句进行多次的调用
- 创建函数(定义函数):
    def 函数名([形参1, 形参2, ..., 形参n]) :
        代码块
        
    - 函数名必须要符和标识符的规范
        (可以包含字母、数字、下划线、但是不能以数字开头)    
- 函数中保存的代码不会立即执行,需要调用函数代码才会执行
- 调用函数:
    函数对象()
- 定义函数一般都是要实现某种功能的

函数的简介–示例代码:

# 比如有如下三行代码,这三行代码是一个完整的功能:
# print('hello')
# print('你好')
# print('再见')

# 定义一个函数
def fn() :
    print('这是我的第一个函数!')
    print('hello')
    print('今天天气真不错!')

# 打印 fn
# print(fn)         # <function fn at 0x03D2B618>
# print(type(fn))   # <class 'function'>

# fn 是函数对象  fn() 是调用函数
# print 是函数对象 print() 是调用函数
# fn()

# 定义一个函数,可以用来求任意两个数的和
# def sum() :
#     a = 123
#     b = 456
#     print(a + b)

# sum()

# 定义函数时指定形参
def fn2(a, b) :
    # print('a =', a)
    # print('b =', b)
    print(a, "+", b, "=", a + b)

# 调用函数时,来传递实参
fn2(10, 20)
fn2(123, 456)

5.2 函数的参数

- 在定义函数时,可以在函数名后的()中定义数量不等的形参。
    多个形参之间使用,隔开
- 形参(形式参数),定义形参就相当于在函数内部声明了变量,但是并不赋值
- 实参(实际参数)
    - 如果函数定义时,指定了形参,那么在调用函数时也必须传递实参,实参将会赋值给对应的形参,简单来说,有几个形参就得传几个实参。

练习1:
  定义一个函数,可以用来求任意三个数的乘积。
练习2:
  定义一个函数,可以根据不同的用户名显示不同的欢迎信息。

示例代码:

# 求任意三个数的乘积
def mul(a, b, c) :
    print(a * b * c)

# 根据不同的用户名显示不同的欢迎信息   
def welcome(username) :
    print('欢迎', username, '光临')

# mul(1, 2, 3)
# welcome('孙悟空')

5.3 函数参数传递的方式

# 定义一个函数
#   定义形参时,可以为形参指定默认值
#   指定了默认值以后,如果用户传递了参数则形参默认值没有任何作用,如果用户没有传递参数,则形参默认值就会生效。
def fn(a = 5, b = 10, c = 20) :
    print('a =', a)
    print('b =', b)
    print('c =', c)

# fn(1, 2, 3)
# fn(1, 2)
# fn()

# 实参的传递方式
# 位置参数
#   位置参数:就是将对应位置的实参赋值给对应位置的形参
#   第一个实参赋值给第一个形参,第二个实参赋值给第二个形参,......
# fn(1, 2, 3)

# 关键字参数
#   关键字参数:可以不按照形参定义的顺序去传递,而直接根据参数名去传递参数
# fn(b=1, c=2, a=3)
# print('hello', end='')    # end 就是关键字参数

#   位置参数和关键字参数可以混合使用
#   混合使用位置参数和关键字参数时,必须将位置参数写到前面,且位置参数和关键字参数指定的位置不能相同。
# fn(1, c=30)   # a = 1, b = 10, c = 30

# fn(1, a=30)   # 报错

def fn2(a) :
    print('a =', a)

# 函数在调用时,解析器不会检查实参的类型
# 实参可以传递任意类型的对象
b = 123
b = True
b = 'hello'
b = None
b = [1, 2, 3]

# fn2(b)    
# fn2(fn)   # 没问题,实参可以是函数对象

def fn3(a , b) :
    print(a + b)
# fn3(123, "456")   # 报错

def fn4(a) :
    # 在函数中对形参进行重新赋值,不会影响其他的变量
    # a = 20
    # a 是一个列表,我们尝试修改列表中的元素
    # 如果形参执行的是一个对象,当我们通过形参去修改对象的值时,会影响到所有指向该对象的变量。
    a[0] = 30
    print('a =', a, id(a))

c = 10   
c = [1, 2, 3] 

# fn4(c)
# fn4(c.copy()) # 列表副本,新的对象
# fn4(c[:])     # 列表副本,新的对象

# print('c =', c, id(c))

5.4 函数的不定长参数

# 不定长的参数
# 定义一个函数,可以求任意个数字的和
def sum(*nums) :
    # 定义一个变量,来保存结果
    result = 0
    # 遍历元组,并将元组中的数进行累加
    for n in nums :
        result += n
    print(result)

# sum(123, 456, 789, 10, 20, 30, 40)

# 在定义函数时,可以在形参前边加上一个*,这样这个形参将会获取到所有的实参
# 它将会将所有的实参保存到一个元组中
# a, b, *c = (1, 2, 3, 4, 5, 6)     # 元组的解包(解构)

# *a 会接受所有的位置实参,并且会将这些实参统一保存到一个元组中(参数的装包)
def fn(*a) :
    print("a =", a, type(a))    # a = (1, 2, 3, 4, 5) <class 'tuple'>
fn(1, 2, 3, 4, 5)

# 带星号的形参只能有一个
# 带星号的参数,可以和其他参数配合使用
# 第一个参数给 a,第二个参数给 b,剩下的都保存到 c 的元组中
def fn2(a, b, *c) :
    print('a =', a)   # a = 1
    print('b =', b)   # b = 2
    print('c =', c)   # c = (3, 4, 5)
fn2(1, 2, 3, 4, 5)

# 可变参数不是必须写在最后,但是注意,带*的参数后的所有参数,必须以关键字参数的形式传递
# 第一个参数给 a,剩下的位置参数给 b 的元组,c 必须使用关键字参数
def fn2(a, *b, c) :
    print('a =', a)   # a = 1
    print('b =', b)   # b = (2, 3, 4)
    print('c =', c)   # c = 5
fn2(1, 2, 3, 4, c=5)

# 所有的位置参数都给a,b 和 c 必须使用关键字参数
def fn2(*a, b, c) :
    print('a =',a)    # a = (1, 2, 3)
    print('b =',b)    # b = 4
    print('c =',c)    # c = 5
fn2(1, 2, 3, b=4, c=5)

# 如果在形参的开头直接写一个*,则要求我们的所有的参数必须以关键字参数的形式传递
def fn2(*, a, b, c) :
    print('a =', a)     # a = 3
    print('b =', b)     # b = 4
    print('c =', c)     # c = 5
fn2(a=3, b=4, c=5)

# *形参只能接收位置参数,而不能接收关键字参数
def fn3(*a) :
    print('a =', a)   # a = (1, 2, 3, 4, 5)
fn3(1, 2, 3, 4, 5)

# **形参可以接收其他的关键字参数,它会将这些参数统一保存到一个字典中
#   字典的 key 就是参数的名字,字典的 value 就是参数的值
# **形参只能有一个,并且必须写在所有参数的最后
def fn3(b, c, **a) :
    print('a =', a, type(a))    # a = {'d': 2, 'e': 10, 'f': 20} <class 'dict'>
    print('b =', b)     # b = 1
    print('c =', c)     # c = 3
fn3(b=1, d=2, c=3, e=10, f=20)

# 参数的解包(拆包)
def fn4(a, b, c) :
    print('a =', a)
    print('b =', b)
    print('c =', c)

# 创建一个元组
t = (10, 20, 30)
# 创建一个列表
# t = [10, 20, 30]

# 传递实参时,也可以在序列类型的参数前添加星号,这样它会自动将序列中的元素依次作为参数传递
# 这里要求序列中元素的个数必须和形参的个数的一致
# fn4(t[0], t[1], t[2])     # 此种方式太麻烦了
fn4(*t)     # 解包的方式

# 创建一个字典
d = {
   'a':100, 'b':200, 'c':300}
# 通过 ** 来对一个字典进行解包操作
fn4(**d)

5.5 函数的返回值

# 返回值,返回值就是函数执行以后返回的结果
# 可以通过 return 来指定函数的返回值
# 可以直接使用函数的返回值,也可以通过一个变量来接收函数的返回值

def sum(*nums) :
    # 定义一个变量,来保存结果
    result = 0
    # 遍历元组,并将元组中的数进行累加
    for n in nums :
        result += n
    print(result)

# sum(123, 456, 789)
 
# return 后边跟什么值,函数就会返回什么值
# return 后边可以跟任意的对象,返回值甚至可以是一个函数
def fn() :
    # return 'hello'
    # return [1, 2, 3]
    # return {'k':'v'}
    def fn2() :
        print('hello')
    return fn2      # 返回值也可以是一个函数

r = fn()    # 这个函数的执行结果就是它的返回值
# r()
# print(fn())
# print(r)

# 如果仅仅写一个 return 或者不写 return,则相当于 return None 
def fn2() :
    a = 10
    return 

# 在函数中,return 后的代码都不会执行,return 一旦执行,则函数自动结束
def fn3():
    print('hello')
    return
    print('abc')
# r = fn3()
# print(r)

def fn4() :
    for i in range(5) :     # 生成一个这样的自然数序列:[0, 1, 2, 3, 4]
        if i == 3 :
            # break 用来退出当前循环
            # continue 用来跳过当次循环
            return # 用来结束函数
        print(i)
    print('循环执行完毕!')

# fn4()

def sum(*nums) :
    # 定义一个变量,来保存结果
    result = 0
    # 遍历元组,并将元组中的数进行累加
    for n in nums :
        result += n
    return result
    
r = sum(123, 456, 789)

# print(r + 778)

def fn5():
    return 10

# fn5 和 fn5() 的区别
print(fn5)      # fn5 是函数对象,打印 fn5 实际是在打印函数对象:<function fn5 at 0x05771BB8>
print(fn5())    # fn5() 是在调用函数,打印 fn5() 实际上是在打印 fn5() 函数的返回值:10

5.6 函数的文档字符串–函数的说明

# help() 是 Python 中的内置函数
#   通过 help() 函数可以查询 python 中的函数的用法
#   语法:help(函数对象)
#   help(print)     # 获取 print() 函数的使用说明

# 文档字符串(doc str)
#   在自定义函数时,可以在函数内部编写文档字符串,文档字符串就是【函数的说明】,建议使用英文编写,哈哈!
#   当我们编写了文档字符串时,就可以通过 help() 函数来查看自定义函数的说明
#   文档字符串非常简单,其实直接在函数的第一行写一个字符串就是文档字符串,单引号和双引号均可,但是一般使用 三重引号,因为三重引号可以换行,并且会保留字符串中的格式。
def fn(a: int, b: bool, c: str='hello') -> int :
    '''
        这是一个文档字符串的示例
    
        函数的作用:......
        函数的参数:
            a,作用,类型,默认值......
            b,作用,类型,默认值......
            c,作用,类型,默认值......
    '''
    return 10

help(fn)

5.7 变量的作用域与命名空间

# 作用域(scope)
#   作用域指的是变量生效的区域
b = 20  # 全局变量

def fn() :
    a = 10  # a定义在了函数内部,所以它的作用域就是函数内部,函数外部无法访问
    print('函数内部:', 'a =', a)
    print('函数内部:', 'b =', b)

# fn()    
  
print('函数外部:', 'a =', a)
print('函数外部:', 'b =', b)

# 在 Python 中一共有两种作用域:
#  全局作用域
#   - 全局作用域在程序执行时创建,在程序执行结束时销毁
#   - 所有函数以外的区域都是全局作用域
#   - 在全局作用域中定义的变量,都属于全局变量,全局变量可以在程序的任意位置被访问
#  函数作用域
#   - 函数作用域在函数调用时创建,在调用结束时销毁
#   - 函数每调用一次就会产生一个新的函数作用域
#   - 在函数作用域中定义的变量,都是局部变量,它只能在函数内部被访问
#   
#  变量的查找--就近原则
#   - 当我们使用变量时,会优先在当前作用域中寻找该变量,如果有则使用,
#       如果没有,则继续去上一级作用域中寻找,如果有则使用,
#       如果依然没有,则继续去上一级作用域中寻找,以此类推
#       直到找到全局作用域,依然没有找到,则会抛出异常:NameError: name 'a' is not defined

def fn2() :
    def fn3() :
        print('fn3中:', 'a =', a)
    fn3()

# fn2()    


a = 20
def fn3() :
    # a = 10    # 在函数中为变量赋值时,默认都是为局部变量赋值
    # 如果希望在函数内部修改全局变量,则需要使用 global 关键字,来声明变量
    global a    # 声明在函数内部使用的 a 是全局变量,此时再去修改 a 时,就是在修改全局的 a
    a = 10      # 修改全局变量
    print('函数内部:', 'a =', a)

# fn3()
# print('函数外部:', 'a =', a)

-------------------------------------------------------------------------------------

# 命名空间(namespace)
#   命名空间指的是变量存储的位置,每一个变量都需要存储到指定的命名空间当中
#   每一个作用域都会有一个它对应的命名空间
#   全局的命名空间,用来保存全局变量
#   函数的命名空间,用来保存函数中的变量(局部变量)
#   命名空间实际上就是一个字典,是一个专门用来存储变量的字典

# locals() 用来获取当前作用域的命名空间
#   如果在全局作用域中调用 locals(),则获取的是全局命名空间
#   如果在函数作用域中调用 locals(),则获取的是函数的命名空间
#   返回的是一个字典
a = 10
scope = locals()    # 获取当前命名空间
print(scope)
print(type(scope))  # <class 'dict'>

# print(a)          # 10
# print(scope['a']) # 10

# 向 scope 中添加一个 key-value
scope['c'] = 1000   # 向字典中添加 key-value 就相当于在全局中创建了一个全局变量(一般不建议这么做)
print(c)

def fn4() :
    a = 
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值