学习python第九节课:函数(一)

本文介绍了Python中的函数,包括函数的定义、调用,详细讲解了函数的参数类型,如形参、实参、必传参数、默认参数、关键字参数和不定长参数(*args和**kwargs)。此外,还提到了拆包和引用的概念。
摘要由CSDN通过智能技术生成

一、函数

  • 数就是将一段具有独立功能的代码块 整合到一个整体并命名,在需要的位置调用这个名称即可完成对应的需求。

函数在开发过程中,可以更高效的实现代码重用

二、函数的定义与调用

在python中 ,函数是一个组织好的 ,可以重复使用的代码段 ,函数可以提高代码的重复利用率 ,原则上一个函数只实现一个单一的功能 ,这样能增强程序的模块性, python有许多的内置函数可供你使用, 你也可以自己定义函数,这通常被称之为自定义函数

2.1 函数的定义

函数也是一个对象,函数的对象是function,被<>包裹的就是一个对象。

def 函数名(参数列表):
    函数体

函数名是一个函数对象,函数名()调用函数。

先看几个示例

def fn():
    pass

def fn(a):
    pass

def fn(a, b, c):
    pass

关于上面这段代码,你要记住下面3个结论

  1. 函数可以没有参数
  2. 函数的参数可以是一个,也可以是多个
  3. pass的作用相当于占位符,没有实际作用

2.2 函数的调用

函数名(参数)

注意:

  1. 不同的需求,参数可有可无。
  2. 在Python中,函数必须先定义后使用
  • 示例1, 定义并调用没有参数的函数
def fn():
    print('hello world')

fn()  # hello world
  • 示例2, 定义并调用有一个参数的函数
def fn(a):
    """
    输出菱形
    """
    for i in range(a):
        if i <=a//2:
            print(" "*(a//2-i)  + "*"*(2*i + 1))
        else:
            print(" "*(i - a//2)  + "*"*((a-i)*2-1))

fn(11)
'''
输出:
     *
    ***
   *****
  *******
 *********
***********
 *********
  *******
   *****
    ***
     *
'''
  • 示例3, 定义并调用有三个参数的函数
def fn(a, b, c):
    max_number = a
    if b > max_number:
        max_number = b

    if c > max_number:
        max_number = c

    return max_number


max_num = fn(22, 23, 21)
print(max_num)
  • 当你使用def 定义了一个函数后,只有调用这个函数才能让这个函数运行。

三、函数的参数

函数的参数这部分内容的很复杂,很重要。

3.1 形参和实参

  • 函数的参数
  1. 在定义函数的时候,可以在函数名后面的括号中定义数量不等的形参。

  2. 定义多个形参要用逗号隔开。

  3. 所谓形参,就是函数定义中的参数,就是相当于在函数内部声明了变量,不是赋值,形参在函数体内可以使用。

  4. 实参(实际参数) 如果函数定义的时候指定了形参,那么在调用的时候也必须传递实参。

  5. 实参将会赋值给对应的形参,简单来说,有几个形参就得几个实参。

  6. 定义形参的时候,可以为形参指定默认值,指定了默认值以后,如果用户传递了参数则默认值没有任何作用,如果用户没有传递,则默认值会生效。

  7. 实参可以传递任意类型的对象,调用函数的时候,解析器是不会检查实参的类型。

  8. 位置参数和关键字参数可以混合使用,但是关键字产生不能放到位置参数的前面。

def fn(a):
    for i in range(a):
        if i <= a//2:
            print(" "*(a//2-i)  + "*"*(2*i + 1))
        else:
            print(" "*(i - a//2)  + "*"*((a-i)*2-1))

fn(11)
  • 上面的代码中,函数定义中的a就是形参,而最后一行的代码中,11就是实参,形参代表一种形式,实参,是实际的具体的起作用的数据。
def fn(a):
    print('a=',a)
b =123  # 123
b = Ture  # Ture
b = 'abc'  # abc
fn(b)
  • 实参可以传递任意类型的对象

3.2 必传参数(位置参数)

位置参数:调用函数时根据函数定义的参数位置来传递参数。

def user_info(name, age, gender):
    print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')


user_info('TOM', 20, '男')

注意:传递和定义参数的顺序及个数必须一致。

def fn(a, b):
    for i in range(b):
        print(a)

fn('ok', 2)
  • 上面定义的fn函数里有两个参数,a 和b,他们都是必传参数,在调用函数时,你必须传入两个值,否则就会报错,下面演示一种错误的调用方法
def fn(a, bt):
    for i in range(b):
        print(a)

fn('ok')
  • 报错内容为
Traceback (most recent call last):
  File "/Users/kwsy/kwsy/coolpython/test.py", line 5, in <module>
    fn('ok')
TypeError: fn() missing 1 required positional argument: 'count'
  • 从最后的TypeError的内容来看,缺失了一个位置参数(positional argument),我想,必传参数更能准确的描述这个参数的性质。 在函数fn内部,用到了b这个形参,可是调用函数时,只传了a, 却没有传b,最终报错。
def fn(a):
    a = 20
    print('a=',a)
c = 10
fn(c)  # a= 20
print('c=',c)  # c= 10

在函数中重新给形参赋值,不会影响其他的变量。

def fn(a):
    a[0]= 20
    print('a=',a,id(a))
c = [10,20,30,40]
fn(c)  # a = [30, 20, 30] 3036669602560
print('c=',c,id(c))  # c = [30, 20, 30] 3036669602560

如果现在的形参执行的是一个对象,当我们通过形参去修改对象时,会影响到所有指向该对象的变量

def fn(a):
    a[0]= 20
    print('a=',a,id(a))
c = [10,20,30,40]
# fn(c.copy())  # a= [20, 20, 30, 40] 1623071716352
# print('c=',c,id(c))  # c= [10, 20, 30, 40] 1623071714048

fn(c[:])  # a= [20, 20, 30, 40] 2947320509440
print('c=',c,id(c))  # c= [10, 20, 30, 40] 2947320507136

3.3 默认参数

  • fn函数根据b参数输出指定次数的a,我希望在两次输出的空档可以暂停一段时间,因此增加一个sleep参数
import time


def fn(a, b, sleep=1):
    for i in range(b):
        print(a)
        time.sleep(1)

fn('ok', 2)
  • 在调用函数时,我并没有传sleep这个形参,程序并没有报错,这是因为在定义函数的时候,给了sleep形参默认值1,这意味着,如果调用函数时没有传这个参数,python会用默认值来执行函数。默认值参数非常用有用,假设你在系统里的很多地方都使用最开始定义的fn函数
def fn(a, b):
    pass
  • 开始某一天,你需要增加一个参数sleep, 如果你将sleep定义为必传参数,那么所有用到函数fn的地方都必须修改调用时的代码来增加这个入参,但如果你把sleep定义为默认参数,sleep已经默认等于1,除非必须传入其他的数值,否则就不需要这么做,之前的代码仍然可以使用。

  • 定义函数是时,如果有多个默认参数,他们必须放置在参数列表的最后,不允许在中间放置一个必传参数。

3.4 关键字参数

关键字参数不是一个出现在函数定义时的概念,而是一个出现在函数调用时的概念。

import time


def fn(a, b, sleep=1):
    for i in range(b):
        print(a)
        time.sleep(1)

fn(bt=2, a='关键字参数', sleep=2)
  • 在调用函数时,使用key=value的形式来传递参数,不仅如此,还打乱了顺序,先传入了b,后传入了a,关键字参数允许你以任何顺序传递参数,只要必传参数都以key=value的形式传值即可。现在,对于关键字参数是出现在函数调用时的概念应该有了清楚的概念。

  • 使用关键字参数,可以让参数传递更加明确,让调用方清楚的知道每个参数的传值情况。

3.5 不定长参数(可变参数)

  • 不定长参数分为两种:

    1. *args 接受任意多个实际参数

    2. **kwargs接收任意多个以关键字参数赋值的实际参数

3.5.1 *args

在定义函数时,有时候你并不希望参数的个数是固定的,这种设计在实际工作中很常见。

def fn(*args):
    print(args, type(args))
    sum_res = 0
    for item in args:
        sum_res += item

    return sum_res

print(fn(2))
print(fn(2, 3, 4))
  • 你可以看到,我在定义fn时,使用args, args只是个名字,也可以直接写成a,你可以随意修改,关键是前面有一个星。有了这个星,函数调用时传递多少个参数就变成了一个很随意的事情,所有传入的参数将被放入到一个元组中,因此args的类型是tuple元组。但是带*的形参只能有一个,可以配合其他参数使用。

  • *形参只能接受位置参数,不能接受关键字参数。

def fn2(a,b,*c):
    print('a =',a)
    print('b =',b)
    print('c =',c)

fn2(1,2,3,4,5)
'''
a = 1
b = 2
c = (3, 4, 5)
'''

def fn2(a,*b,c):
    print('a =',a)
    print('b =',b)
    print('c =',c)

fn2(1,2,3,4,c = 5)
'''
a = 1
b = (2, 3, 4)
c = 5
'''

def fn2(*a,b,c):
    print('a =',a)
    print('b =',b)
    print('c =',c)

fn2(1,2,3,b = 4,c = 5)
'''
a = (1, 2, 3)
b = 4
c = 5
'''

不定长参数不一定非要写在后面,但是要注意,带*号后面的参数,都必须以关键字参数的形式来进行传递

3.5.2 **kwargs

def fn(**kwargs):
    print(kwargs, type(kwargs))
    for course, score in kwargs.items():
        print(course, score)


fn(yuwen=89, shuxue=94)
  • 在调用函数时,以关键字参数的形式进行参数传递,最终这些key-value对将组装成字典,kwargs的类型是dict。个人理解,kwargs就是一种为了偷懒而做的设计,当函数需要传入很多参数(多达10几个)时,使用kwargs定义函数是非常方便的。

  • **形参只能有一个,并且只能写在所有参数的后面

def fn4(b,c,**a):
    print('a =',a)
    print('b =',b)
    print('c =',c)

fn4(b=1,d=2,c=3,e=10,f=50)
'''
a = {'d': 2, 'e': 10, 'f': 50}
b = 1
c = 3
'''

四、拆包和交换变量值

4.1 拆包

  • 拆包:元组
def return_num():
    return 100, 200


num1, num2 = return_num()
print(num1)  # 100
print(num2)  # 200
  • 拆包:字典
dict1 = {'name': 'TOM', 'age': 18}
a, b = dict1

# 对字典进行拆包,取出来的是字典的key
print(a)  # name
print(b)  # age

print(dict1[a])  # TOM
print(dict1[b])  # 18

4.2 交换变量值

需求:有变量a = 10b = 20,交换两个变量的值。

  • 方法一

借助第三变量存储数据。

a = 10
b = 20
# 1. 定义中间变量
c = 0

# 2. 将a的数据存储到c
c = a

# 3. 将b的数据20赋值到a,此时a = 20
a = b

# 4. 将之前c的数据10赋值到b,此时b = 10
b = c

print(a)  # 20
print(b)  # 10
  • 方法二
a, b = 1, 2
a, b = b, a
print(a)  # 2
print(b)  # 1

五、引用

5.1 了解引用

在python中,值是靠引用来传递来的。

我们可以用id()来判断两个变量是否为同一个值的引用。 我们可以将id值理解为那块内存的地址标识。

# 1. int类型
a = 1
b = a

print(b)  # 1

print(id(a))  # 140708464157520
print(id(b))  # 140708464157520

a = 2
print(b)  # 1,说明int类型为不可变类型 

print(id(a))  # 140708464157552,此时得到是的数据2的内存地址
print(id(b))  # 140708464157520


# 2. 列表
aa = [10, 20]
bb = aa

print(id(aa))  # 2325297783432
print(id(bb))  # 2325297783432


aa.append(30)
print(bb)  # [10, 20, 30], 列表为可变类型

print(id(aa))  # 2325297783432
print(id(bb))  # 2325297783432

5.2 引用当做实参

代码如下:

def test1(a):
    print(a)
    print(id(a))

    a += a

    print(a)
    print(id(a))


# int:计算前后id值不同
b = 100
test1(b)

# 列表:计算前后id值相同
c = [11, 22]
test1(c)

输出结果为:

100
140709393736448
200
140709393739648
[11, 22]
2831959059200
[11, 22, 11, 22]
2831959059200

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值