python-函数

函数

1.函数介绍

如果在开发程序时,需要某块代码多次,但是为了提高编写的效率以及代码的重用,所以把具有独立功能的代码块组织为一个小模块,这就是函数

2.函数定义和调用

def demo():  # demo 函数名
    pass

demo() # 调用函数
每次调用函数时,函数都会从头开始执行,当这个函数中的代码执行完毕后,意味着调用结束了
当然了如果函数中执行到了return也会结束函数

3.函数的文档说明

def demo(a, b):
    """求a + b 的和"""
    print(a + b)


demo(10, 20)
help(demo)  # 能够看到demo函数的相关说明

30
Help on function demo in module __main__:

demo(a, b)
    求a + b 的和

4.函数的参数(一)

def add_num(a, b):
    print(a + b)


add_num(10, 20)  # 调用带有参数的函数时,需要在小括号中,传递数据

# 调用函数时参数的顺序
add_num(b=100, a=200)  # 如果使用关键字,必须都使用。否则按顺序传。
定义时小括号中的参数,用来接收参数用的,称为 “形参”
调用时小括号中的参数,用来传递给函数用的,称为 “实参”

5.函数的返回值(一)

def add_num(a, b):
    return a + b


result = add_num(100, 200)
print(result)  

print(add_num(10, 20))  # 函数的返回值必须要打印

6.函数的嵌套调用

def test_a():
    print(f"函数{test_a.__name__}开始")
    print(f"我是{test_a.__name__}函数")
    print(f"函数{test_a.__name__}结束")


def test_b():
    print(f"函数{test_b.__name__}开始")
    test_a()
    print(f"函数{test_b.__name__}结束")


test_b()

函数test_b开始
函数test_a开始
我是test_a函数
函数test_a结束
函数test_b结束
一个函数里面又调用了另外一个函数,这就是所谓的函数嵌套调用

7.局部变量

g = 1000  # 全局变量


def test1():
    a = 300  # 局部变量
    print(f"test1修改前a={a}")
    a = 200
    print(f"test1修改后a={a}")
    print(g - a)


def test2():
    a = 400  # 局部变量
    print(f"test2a={a}")
    print(g - a)


test1()
test2()


test1修改前a=300
test1修改后a=200
800
test2a=400
600
局部变量,就是在函数内部定义的变量
其作用范围是这个函数内部,即只能在这个函数中使用,在函数的外部是不能使用的
因为其作用范围只是在自己的函数内部,所以不同的函数可以定义相同名字的局部变量
局部变量的作用,为了临时保存数据需要在函数中定义变量来进行存储
当函数调用时,局部变量被创建,当函数调用完成后这个变量就不能够使用了

8.全局变量

01.什么是全局变量
# 定义全局变量
a = 100

def test1():
    print(a)  # 虽然没有定义变量a但是依然可以获取其数据

def test2():
    print(a)  # 虽然没有定义变量a但是依然可以获取其数据

# 调用函数
test1()
test2()
在函数外边定义的变量叫做全局变量
全局变量能够在所有的函数中进行访问
02.全局变量和局部变量名字相同问题
a = 100  # 全局变量


def test1():
    a = 300  # 局部变量
    print(f"test1修改前a={a}")
    a = 200
    print(f"test1修改后a={a}")


def test2():
    print(f"test2a={a}")


test1()
test2()


test1修改前a=300
test1修改后a=200
test2a=100
当函数内出现局部变量和全局变量相同名字时,函数内部中的 变量名 = 数据 此时理解为定义了一个局部变量,而不是修改全局变量的值
03.函数中修改全局变量
a = 100  # 全局变量


def test1():
    global a
    print(f"test1修改前a={a}")
    a = 200
    print(f"test1修改后a={a}")


def test2():
    print(f"test2a={a}")


test1()
test2()

test1修改前a=100
test1修改后a=200
test2a=200
如果在函数中出现global 全局变量的名字 那么这个函数中即使出现和全局变量名相同的变量名 = 数据 也理解为对全局变量进行修改,而不是定义局部变量
如果在一个函数中需要对多个全局变量进行修改,那么可以使用
# 可以使用一次global对多个全局变量进行声明 global a, b # 还可以用多次global声明都是可以的 # global a # global b

9.多函数程序的基本执行流程

一般在实际开发过程中,一个程序往往由多个函数(后面知识中会讲解类)组成,并且多个函数共享某些数据,这种场景是经常出现的,因此下面来总结下,多个函数中共享数据的几种方式
01.使用全局变量
g_num = 0


def test1():
    global g_num
    g_num = 100


def test2():
    print(g_num)


test1()
test2()

100
02.使用函数的返回值、参数
def test1():
    return 50


def test2(num):
    print(num)


result = test1()
test2(result)

50
03.函数嵌套调用
def test1():
    return 20


def test2():
    result = test1()
    print(result)


test2()

20

10.函数的参数(二)

01.多个return
def test1():
    print('111111')
    return 1
    print('22222')
    return 2
    print('3333')


print(test1())

111111
1
一个函数中可以有多个return语句,但是只要有一个return语句被执行到,那么这个函数就会结束了,因此后面的return没有什么用处
如果程序设计为如下,是可以的因为不同的场景下执行不同的return
def test1(a):
    if a > 10:
        return a + 10
    else:
        return -1


print(test1(1))
02.一个函数返回多个数据的方式
def divid(a, b):
    shang = a // b
    yushu = a % b
    return shang, yushu


result = divid(10, 5)
print(result)  # 默认是元组

(2, 0)
return后面可以是元组,列表、字典等,只要是能够存储多个数据的类型,就可以一次性返回多个数据
def function(): # return [1, 2, 3] # return (1, 2, 3) return {"num1": 1, "num2": 2, "num3": 3}
如果return后面有多个数据,那么默认是元组
In [1]: a = 1, 2 In [2]: a Out[2]: (1, 2) In [3]: In [3]: b = (1, 2) In [4]: b Out[4]: (1, 2) In [5]:

11.函数的返回值(二)

01.缺省参数
调用函数时,缺省参数的值如果没有传入,则取默认值。
下例会打印默认的age,如果age没有被传入:
def test(name, age=35):
    print(f'name={name}')
    print(f'age={age}')


test('ruiwen')
test('ruiwen', 20)


name=ruiwen
age=35
name=ruiwen
age=20
在形参中默认有值的参数,称之为缺省参数
注意:带有默认值的参数一定要位于参数列表的最后面
def test(name, age=35, sex, ):
    print(f'name={name}')
    print(f'age={age}')


test('ruiwen', 'nan')
test('ruiwen', 20, 'nan')

# SyntaxError: non-default argument follows default argument
02.不定长参数
有时可能需要一个函数能处理比当初声明时更多的参数, 这些参数叫做不定长参数,声明时不会命名。
# 基本语法

def functionname([formal_args,] *args, **kwargs):
   """函数_文档字符串"""
   function_suite
   return [expression]
加了星号(*)的变量args会存放所有未命名的变量参数,args为元组
而加**的变量kwargs会存放命名参数,即形如key=value的参数, kwargs为字典.
def fun(a, b, *args, **kwargs):
    """可变参数演示实例"""
    print(f'a={a}')
    print(f'b={b}')
    print(f'args={args}')
    for k, v in kwargs.items():
        print(f'kwargs: k={k},v={v}')


fun(10, 20, 30, 40, 50, x=3, y=4, z=5)


a=10
b=20
args=(30, 40, 50)
kwargs: k=x,v=3
kwargs: k=y,v=4
kwargs: k=z,v=5


c = (3, 4, 5)
d = dict(m=6, n=7, p=8)
fun(1, 2, *c, **d)

a=1
b=2
args=(3, 4, 5)
kwargs: k=m,v=6
kwargs: k=n,v=7
kwargs: k=p,v=8


c = (3, 4, 5)
d = dict(m=6, n=7, p=8)
fun(1, 2, c, d, [1, 2, 3], (1, 2, 3), "123", {"a": 1})

a=1
b=2
args=((3, 4, 5), {'m': 6, 'n': 7, 'p': 8}, [1, 2, 3], (1, 2, 3), '123', {'a': 1})
03.缺省参数在*args后面
def test(a, *args, b=22, c=23, **kwargs):
    print(a)
    print(args)
    print(b)
    print(c)
    print(kwargs)


test(100, 200, 300, 400, 500, 600, 700, b=1, c=2, mm=800, nn=900)


100
(200, 300, 400, 500, 600, 700)
1
2
{'mm': 800, 'nn': 900}
如果很多个值都是不定长参数,那么这种情况下,可以将缺省参数放到 *args的后面, 但如果有 kwargs的话,kwargs必须是最后的

12.拆包、交换俩个变量的值

01.返回的数据直接拆包
def test():
    a = 1
    b = 2
    c = 3
    return a, b, c


x, y, z = test()
print(x, y, z)

print(test())
for i in test():  # 元组可以遍历
    print(i)
拆包时要注意,需要拆的数据的个数要与变量的个数相同,否则程序会异常
除了对元组拆包之外,还可以对列表、字典等拆包
  In [17]: a, b = (11, 22)
  In [18]: a
  Out[18]: 11
  In [19]: b
  Out[19]: 22

  In [20]: a, b = [11, 22]
  In [21]: a
  Out[21]: 11
  In [22]: b
  Out[22]: 22

  In [23]: a, b = {"m":11, "n":22}  # 取出来的是key,而不是键值对
  In [24]: a
  Out[24]: 'm'
  In [25]: b
  Out[25]: 'n'
02.交换2个变量的值
a, b = 10, 20
print(a, b)
a, b = b, a
print(a, b)

13.引用(一)

a = 1
b = a
print(b)

a = 2
print(a)

1
2
a = [1,2]
b = a
print(b)

a.append(3)
print(a)

[1, 2]
[1, 2, 3]
在python中,值是靠引用来传递来的。
我们可以用id()来判断两个变量是否为同一个值的引用。
我们可以将id值理解为那块内存的地址标示。
>>> a = 1
>>> b = a
>>> id(a) 
13033816
>>> id(b)   # 注意两个变量的id值相同
13033816
>>> a = 2
>>> id(a)   # 注意a的id值已经变了
13033792
>>> id(b)   # b的id值依旧
13033816
>>> a = [1, 2]
>>> b = a
>>> id(a)
139935018544808
>>> id(b)
139935018544808
>>> a.append(3)
>>> a
[1, 2, 3]
>>> id(a)
139935018544808
>>> id(b)       # 注意a与b始终指向同一个地址
139935018544808
之前为了更好的理解变量,咱们可以把a=100理解为变量a中存放了100,事实上变量a存储是100的引用(可理解为在内存中的一个编号)

14.可变、不可变类型

所谓可变类型与不可变类型是指:数据能够直接进行修改,如果能直接修改那么就是可变,否则是不可变
可变类型有: 列表、字典、集合
不可变类型有: 数字、字符串、元组

15.引用(二)

引用当做实参
可变类型与不可变类型的变量分别作为函数参数时,会有什么不同吗?
Python有没有类似C语言中的指针传参呢?
def test1(b):  # 变量b一定是一个局部变量,就看它指向的是谁?可变还是不可变
    b += b  # += 是直接对b指向的空间进行修改,而不是让b指向一个新的
    # b = b+b  # xx = xx+yyy 先把=号右边的结果计算出来,然后让b指向这个新的地方,不管原来b指向谁
                # 现在b一定指向这个新的地方

# a = [11, 22]
a = 100
test1(a)
print(a)

100
Python中函数参数是引用传递(注意不是值传递)
对于不可变类型,因变量不能修改,所以运算不会影响到变量自身
而对于可变类型来说,函数体中的运算有可能会更改传入的参数变量

16.函数的注意事项

01.自定义函数
无参数、无返回值
def 函数名():
    语句
无参数、有返回值
def 函数名():
    语句
    return 需要返回的数值
注意:
一个函数到底有没有返回值,就看有没有return,因为只有return才可以返回数据
在开发中往往根据需求来设计函数需不需要返回值
函数中,可以有多个return语句,但是只要执行到一个return语句,那么就意味着这个函数的调用完成
有参数、无返回值
def 函数名(形参列表):
    语句
注意:
在调用函数时,如果需要把一些数据一起传递过去,被调用函数就需要用参数来接收
参数列表中变量的个数根据实际传递的数据的多少来确定
有参数、有返回值
def 函数名(形参列表):
    语句
    return 需要返回的数值
函数名不能重复
如果在同一个程序中出现了多个相同函数名的函数,那么在调用函数时就会出现问题,所以要避免名字相同
还有一点 不仅要避免函数名之间不能相同,还要避免 变量名和函数名相同的,否则都会出现问题
详细的讲解在python就业班中进行学习,此阶段只要注意这些问题即可
02.函数调用方式
调用的方式为:
函数名([实参列表])
调用时,到底写不写 实参
如果调用的函数 在定义时有形参,那么在调用的时候就应该传递参数
调用时,实参的个数和先后顺序应该和定义函数中要求的一致
如果调用的函数有返回值,那么就可以用一个变量来进行保存这个值
03.作用域
在一个函数中定义的变量,只能在本函数中用(局部变量)
在函数外定义的变量,可以在所有的函数中使用(全局变量)

17.递归函数

01.什么是递归函数
一个函数可以调用其他函数。
如果一个函数在内部不调用其它的函数,而是自己本身的话,这个函数就是递归函数。
02.递归函数的作用
计算阶乘
def calNum(num):
    i = 1
    result = 1
    while i <= num:
        result *= i
        i += 1
    return result


ret = calNum(3)
print(ret)
def calNum(num):
    if num >= 1:
        result = num * calNum(num - 1)
    else:
        result = 1
    return result


ret = calNum(3)
print(ret)

18.匿名函数

01.语法格式
定义的函数没有名字,这样的函数叫做 匿名函数.
# lambda [形参1], [形参2], ... : [单行表达式] 或 [函数调用]
使用匿名函数, 上面的函数我们就可以定义为单行的函数.
# 不带参数
fun = lambda: 10 + 20
print(fun())

# 带参数
add = lambda a, b: a + b
print(add(10, 20))
02.和普通函数的区别
def my_function(start, end):

    my_sum = 0

    while start <= end:
        my_sum += start
        start += 1

    return my_sum
匿名函数中 不能使用 if 语句、while 循环、for 循环, 只能编写单行的表达式,或函数调用, 普通函数都可以.
匿名函数中返回结果 不需要使用 return, 表达式的运行结果就是返回结果, 普通函数返回结果必须 return.
匿名函数中也可以不返回结果. 例如: lambda : print('hello world')
03.应用场景
1.定义简单的单行函数
def my_function(a, b):
    return a + b

使用 lambda 定义格式如下:

my_function = lambda a, b: a + b
2.作为函数的参数进行传递(重点、难点)
作为函数的参数进行传递(重点、难点)
def my_function1():

    a = 100
    b = 200
    result = a + b
    print('result:', result)


def my_function2():

    a = 100
    b = 200
    result = a - b
    print('result:', result)


def my_function3():

    a = 100
    b = 200
    result = a * b
    print('result:', result)

上面函数定义的缺点是:
函数名要定义多个, 使用起来不方便. 需要记忆, 那个函数完成什么事情.
上面函数只定义了三种计算方式: a + b、a -b、a * b, 如果用户希望 a 和 b 进行除法运算, 那么显然还需要再写函数.
解决目标: 1、提高函数的通用性 2、减少代码量
可以通过传递给 my_function 一个函数来完成.
def my_function(func):

    a = 100
    b = 200
    # 把 cucalate_rule 当做函数来调用
    result = func(a, b)
    print('result:', result)


def caculate_rule(a, b):
    return a / b


my_function(caculate_rule)
3.匿名函数做为函数参数
def my_function(func):

    a = 100
    b = 200
    # 把 cucalate_rule 当做函数来调用
    result = func(a, b)
    print('result:', result)


def caculate_rule1(a, b):
    return a / b

def caculate_rule2(a, b):
    return a // b

def caculate_rule3(a, b):
    return a % b

my_function(caculate_rule1)
my_function(caculate_rule2)
my_function(caculate_rule3)
我们为了调用 my_function 函数要写很多规则, 整个文件中可能就有很多定义的函数代码, 问题是:
这些函数只会用一次
这些函数也比较简单
就没有必要 py 文件中出现这么多无用的代码. 如何改进:
def my_function(func):

    a = 100
    b = 200
    # 把 cucalate_rule 当做函数来调用
    result = func(a, b)
    print('result:', result)


my_function(lambda a, b: a / b)
my_function(lambda a, b: a // b)
my_function(lambda a, b: a % b)
函数可以做为参数传递给另外一个函数, 可以使得函数的实现更加通用.
匿名函数也可以作为参数传递给另外一个函数, 对于只需要用到一次函数, 可以通过匿名函数减少代码量
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值