目录

函数

1、函数的创建

2、函数的参数传递

3、函数的返回值

4、函数的参数定义

1)函数定义默认值参数

2)个数可变的位置参数

3)个数可变的关键字形参

4)传入多个个数可变的参数

5、函数的参数总结

1)将序列中的每个元素,都转换为位置实参;使用*序列对象

2)将字典中的每个键值对,都转换为关键字实参;使用**字典对象

3)举例

4)函数定义时,参数使用了*,在函数调用时,*之后的参数只能使用关键字实参传递

5)函数定义时的形参的顺序问题

6、变量的作用域

1)局部变量

2)全局变量

7、递归函数

8、斐波那契数列

9、总结


函数

  • 执行特定的任务,和完成特定功能的一段代码;

 

函数的作用:

  • 复用代码;
  • 隐藏实现细节;
  • 提高可维护性;
  • 提高可读性,便于调试;

 

1、函数的创建

1)函数的创建,语法格式:

def 函数名([输入参数]):
    函数体
    [return XXX]

 2、函数的调用,语法格式:

函数名([实际参数])

 

# 函数的创建
# 函数或类定义后,建议间隔2行
def calc(a, b):
    c = a + b
    return c


# 函数的调用
result = calc(10, 20)
print(result)

 

2、函数的参数传递

1)函数调用的参数传递

  • 位置实参,根据形参对应的位置进行实参传递;
  • 关键字实参,根据形参名称进行实参传递;
  • 在函数调用过程中,进行参数的传递:
  • 如果是不可变对象,在函数体的修改,不会影响实参的值;如整数,字符串,元组
  • 如果是可变对象,在函数体的修改,会影响实参的值;如列表,字典,集合
# 函数的创建,函数或类定义后,建议间隔2行
def calc(a, b):   # a,b为形式参数,简称形参,形参的位置是在函数的定义处 
    c = a + b
    print('a=', a)
    print('b=', b)
    print('-------------')
    return c


# 函数的调用
result1 = calc(10, 20)   # 10,20为实际参数的值,简称实参,实参的位置是函数的调用处
print('result1=', result1)
result2 = calc(b=30, a=20)   # 左侧的变量的名称称为 关键字参数,在定义处找到名字相同的参数赋值
print('result2=', result2)

输出结果:

a= 10
b= 20
-------------
result1= 30
a= 20
b= 30
-------------
result2= 50

 

函数调用的参数传递内存分析图:

def fun(arg1, arg2):
    print('arg1=', arg1)
    print('arg2=', arg2)
    arg1 = 100
    arg2.append(55)
    print('--------参数修改后-----------')
    print('arg1=', arg1)
    print('arg2=', arg2)


n1 = 11
n2 = [22, 33, 44]
print('n1=', n1)
print('n2=', n2)
print('------------------')
fun(n1, n2)  # 位置传参,arg1,arg2是函数定义处的形参,n1,n2是函数调用处的实参,即实参和形参的名称可以不一致
print('n1=', n1)
print('n2=', n2)

输出结果:

n1= 11
n2= [22, 33, 44]
------------------
arg1= 11
arg2= [22, 33, 44]
--------参数修改后-----------
arg1= 100
arg2= [22, 33, 44, 55]
n1= 11
n2= [22, 33, 44, 55]

python中的语法 python中的语法和函数_函数定义

 

3、函数的返回值

  • 如果函数没有返回值(函数执行完毕之后,不需要给调用处提供数据),return可以省略不写;
  • 函数的返回值,如果是1个,直接返回类型;
  • 函数的返回值,如果是多个,返回的结果为元组

 

# 1)函数没有返回值,return可以省略不写
def fun1():
    print('没有返回值')

fun1()

# 2)函数的返回值,如果是1个,直接返回类型
def fun2():
    return '只有1个返回值'

result = fun2()
print(result)

# 3)函数的返回值,如果是多个,返回的结果为元组。
def fun3():
    return '第1个返回值', '第2个返回值'

result = fun3()
print(result)

输出结果:

没有返回值
只有1个返回值
('第1个返回值', '第2个返回值')

 

函数返回多个值时,结果为元组

# 函数返回多个值时,结果为元组
def fun(num):
    odd = [] # 存奇数
    even = []  # 存偶数
    for i in num:
        if i%2:
            odd.append(i)
        else:
            even.append(i)
    return odd, even


lst = [1, 2, 3, 4, 5, 6]
res = fun(lst)
print('返回多个值时,结果为元组:', res)  # ([1, 3, 5], [2, 4, 6])

# 访问函数返回的多个值,元组
for i in range(len(res)):
    if i == 0:
        print('-------奇数列表:--------')
    elif i == 1:
        print('-------偶数列表:-------')
    for item in res[i]:
        print(item)

输出结果:

返回多个值时,结果为元组: ([1, 3, 5], [2, 4, 6])
-------奇数列表:--------
1
3
5
-------偶数列表:-------
2
4
6

 

4、函数的参数定义

1)函数定义默认值参数

  • 函数定义时,给形参设置默认值,只有与默认值不符的时候,才需要传递实参;
# 函数定义默认值参数
def fun(a, b=10):  # b为默认值参数
    print('a=', a, 'b=', b)

# 函数的调用
fun(100)    # 只传一个参数,b采用默认值,a= 100 b= 10
fun(20, 30)    # 30将默认值10替换,a= 20 b= 30

# print函数的end为默认值参数,end='\n'
print('hello', end='\t')
print('world')  # hello	world

 

2)个数可变的位置参数

  • 定义函数时,无法事先确定传递的位置实参的个数时,使用可变的位置参数
  • 使用 定义个数可变的位置形参
  • 结果为一个元组;
# 定义个数可变的位置参数,结果是元组
def fun(*args):
    print(args)
    print(args[0])

fun(10)  # (10,)
fun(1, 2, 3, 4)  # (1, 2, 3, 4)

输出结果:

(10,)
10
(1, 2, 3, 4)
1

 

3)个数可变的关键字形参

  • 定义函数时,无法事先确定传递的关键字实参的个数时,使用可变的关键字形参;
  • 使用 ** 定义个数可变的关键字形参
  • 结果为一个字典;
# 定义个数可变的关键字形参,结果是字典
def fun(**args):
    print(args)
    print(args['a'])  # 1

fun(a=1)  # {'a': 1}
fun(a=1, b=2, c=3)  # {'a': 1, 'b': 2, 'c': 3}

输出结果:

{'a': 1}
1
{'a': 1, 'b': 2, 'c': 3}
1

 

4)传入多个个数可变的参数

  • 1)定义多个个数可变的位置参数,报错;个数可变的位置参数,只能是1个;
  • 2)定义多个个数可变的关键字形参,报错;个数可变的关键字形参,只能是1个;
  • 3)定义一个函数,既个数可变的位置参数,又个数可变的关键字形参:
  • 3.1)个数可变的关键字形参在前,报错;
  • 3.2)个数可变的位置参数在前,可运行通过;
  • 即个数可变的位置参数,要在个数可变的关键字形参之前;
     
# 1)定义多个个数可变的位置参数,报错
def fun(*args, *a):  # 报错,SyntaxError: invalid syntax
    pass

# 2)定义多个个数可变的关键字形参,报错
def fun(**args, **a):  # 报错,SyntaxError: invalid syntax
    pass

# 3)定义一个个数可变的位置参数,一个个数可变的关键字形参
# 3.1)个数可变的关键字形参在前,报错
def fun(**args, *a): # 报错,SyntaxError: invalid syntax
    pass

# 3.2)个数可变的位置参数在前,可运行通过
def fun(*args, **a):
    pass

 

5、函数的参数总结

python中的语法 python中的语法和函数_python中的语法_02

 

 

1)将序列中的每个元素,都转换为位置实参;使用*序列对象

# 将序列中的每个元素,都转换为位置实参
def fun(a, b, c):
    print('a=', a)
    print('b=', b)
    print('c=', c)
    print('----------------')

# 函数的调用
fun(1, 2, 3)  # 函数调用时的参数传递,称为位置传参
lst = [4, 5, 6]
# fun(lst)  # 直接传列表,会报错,TypeError: fun() missing 2 required positional arguments: 'b' and 'c'
fun(*lst) # 在函数调用时,将列表的每个元素,都转换为位置实参传入

输出结果:

a= 1
b= 2
c= 3
----------------
a= 4
b= 5
c= 6
---------------- 

 

2)将字典中的每个键值对,都转换为关键字实参;使用**字典对象

# 将字典中的每个键值对,都转换为关键字实参
def fun(a, b, c):
    print('a=', a)
    print('b=', b)
    print('c=', c)
    print('----------------')

# 函数的调用
fun(a=10, b=20, c=30)  # 关键字实参
dic = {'a': 40, 'b': 50, 'c': 60}
# fun(dic)  # 直接传入字典,会报错,TypeError: fun() missing 2 required positional arguments: 'b' and 'c'
fun(**dic)  # 在函数调用时,将字典中的键值对,都转换为关键字实参

输出结果:

a= 10
b= 20
c= 30
----------------
a= 40
b= 50
c= 60
----------------

 

3)举例

# 函数定义和调用
def fun1(a, b=3):  # 函数定义默认值参数
    print(a,b)

def fun2(*args):  # 个数可变的位置参数
    print(args)

def fun3(**args):  # 个数可变的关键字形参
    print(args)

fun1(1, 2)
fun2(10, 20, 30)
fun3(a=100, b=200, c=300, d=400)

输出结果:

1 2
(10, 20, 30)
{'a': 100, 'b': 200, 'c': 300, 'd': 400}

 

# 函数定义和调用
def fun4(a, b, c, d):
    print('a', a)
    print('b', b)
    print('c', c)
    print('d', d)
    print('--------------')

# 调用fun4()函数
fun4(1, 2, 3, 4)  # 位置实参传递
fun4(a=1, b=2, c=3, d=4)  # 关键字实参传递
fun4(1, 2, c=3, d=4)  # 前2个参数,是位置实参传递;而c,d是关键字实参传递

 

4)函数定义时,参数使用了*,在函数调用时,*之后的参数只能使用关键字实参传递

需求:c,d只能使用关键字实参传递

# 函数定义和调用
def fun4(a, b, *, c, d):  # *后面的形参,在函数调用时,c,d只能使用关键字实参传递
    print('a', a)
    print('b', b)
    print('c', c)
    print('d', d)
    print('--------------')

# 调用fun4()函数
# fun4(1, 2, 3, 4)  # 位置实参传递,会报错,TypeError: fun4() takes 2 positional arguments but 4 were given
fun4(a=1, b=2, c=3, d=4)  # 关键字实参传递,运行成功
fun4(1, 2, c=3, d=4)  # 前2个参数,是位置实参传递;而c,d是关键字实参传递,运行成功

 

5)函数定义时的形参的顺序问题

# 函数定义时的形参的顺序问题
def fun5(a, b, *, c, d, **args):
    pass

def fun6(*args1, **args2):
    pass

def fun7(a, b=10, *args1, **args2):
    pass

 

6、变量的作用域

  • 程序代码能访问该变量的区域;
  • 根据变量的有效范围,可分为局部变量,全局变量
  • 局部变量,在函数内定义并使用的变量,只在函数内部有效,局部变量使用global声明,这个变量就会变为全局变量
  • 全局变量,函数体外定义的变量,可作用于函数内外;

 

1)局部变量

# 变量的作用域
# 局部变量
def fun(a, b):  # a,b为函数的形参,作用范围也是函数内部,相当于局部变量;
    c = a + b  # c是局部变量,在函数体内定义的变量;
    print(c)

# print(c)  # 报错,NameError: name 'c' is not defined
# print(a)  # 报错,NameError: name 'a' is not defined

 

2)全局变量

# 全局变量
name = '张老师'  # name是全局变量,作用范围为函数内部和外部都可以使用
print(name)

def fun():
    print(name)

fun()

输出结果:

张老师
张老师

 

函数体内的局部变量,转为全局变量,使用global

# 局部变量转为全局变量
def fun():
    global age  # 局部变量转为全局变量
    age = 10
    print(age)

fun()
print(age)  # age为全局变量,函数体外面也可以使用了

 

7、递归函数

  • 如果一个函数的函数体内调用了该函数本身,这个函数就是递归函数;
  • 递归的组成部分:递归调用,递归终止条件;
  • 递归的调用过程:
  • 每递归调用一次函数,都会在栈内存分配一个栈帧
  • 每执行完一次函数,都会释放相应的空间
  • 递归的优缺点:
  • 缺点:占用内存多,效率低下;
  • 优点:思路和代码简单;

 

使用递归来计算阶乘

fac(6)

6! = 6x5x4x3x2x1

6*fac(5)

6! = 6x5!

5*fac(4))

5! = 5x4!

4*fac(3)

4! = 4x3!

3*fac(2)

3! = 3x2!

2*fac(1)

2! = 2x1!

fac(1)

1! = 1

# 使用递归来计算阶乘
def fac(n):
    if n == 1:
        return 1
    else:
        return n * fac(n-1)

res = fac(6)
print(res)  # 720

 

8、斐波那契数列

数列:0、1、1、2、3、5、8、13、21、34、……

斐波那契数列,以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(≥ 3,∈ N*)

# 斐波那契数列
def fib(n):
    if n == 1:
        return 0
    elif n == 2:
        return 1
    else:
        return fib(n-1) + fib(n-2)

# 输出斐波那契数列第7位上的数字
res = fib(7)
print(res)

# 输出斐波那契数列前7位上的数字
lst = []
for i in range(1, 8, 1):
    lst.append(fib(i))

print(lst)

输出结果:

8
[0, 1, 1, 2, 3, 5, 8]

 

9、总结

python中的语法 python中的语法和函数_全局变量_03