Python基础-Day06 函数(要点)

目录

1. 函数语法

2. 要点

2.1 def 定义函数

2.2 参数列表

2.3. return 返回值

2.4 文档字符串(函数的注释)

3. 变量作用域

3.1 全局变量

3.2 局部变量

4. 参数传递

4.1 传递可变对象的引用

4.2 传递不可变对象的引用

5. 浅拷贝 & 深拷贝

6. 不可变对象包含可变子对象

7. 参数类型

7.1 位置参数

7.2 默认值参数

7.3 命名参数

7.4 可变参数

8. lambda 表达式

8.1 定义

8.2 基本语法

9. 嵌套函数

10. nonlocal 关键字

11. LEGB 规则


1. 函数语法

def 函数名([参数列表]) :
        '''文档字符串'''
        函数体/若干语句

2. 要点

2.1 def 定义函数

Python 执行 def 时,会创建一个函数对象,并绑定到函数名变量上。

:函数也是对象,执行def 定义函数后,系统就创建了相应的函数对象。

def print_star(n):
    print("*"*n)

print(print_star)
print(id(print_star))

c = print_star

c(3)

'''
输出结果:
<function print_star at 0x000001E32AC7BA68>
2075186936424
***

注:
变量 c 和 print_star 都指向同一个函数对象。
因此,执行c(3)和执行print_star(3)的效果完全一致。
Python中,圆括号意味着调用函数;
若无圆括号,Python 则会将函数当做普通对象。
'''

2.2 参数列表

1. 圆括号内为形式参数列表,若有多个参数则使用逗号隔开;

2. 形式参数不需声明类型,也不需指定函数返回值类型;

3. 即使无参数,也必须保留空的圆括号;

4. 实参列表必须与形参列表一一对应。

2.3. return 返回值

1. 若函数体中包含 return 语句,则结束函数执行并返回值;

2. 若函数体中不包含 return 语句,则返回None 值;

3. 若需返回多个返回值,可使用列表、元组、字典、集合将多个值“存起来”。

2.4 文档字符串(函数的注释)

可在函数体内最开始的部分附上函数定义说明,通过三个单引号或三个双引号实现,中间可以加入多行文字进行说明。

3. 变量作用域

3.1 全局变量

1. 全局变量在函数和类定义之外声明,作用域为定义的模块,从定义位置开始直到模块结束;

2. 全局变量降低了函数的通用性和可读性,应尽量避免使用;

3. 全局变量一般做常量使用;

4. 若要在函数内改变全局变量的值,需使用 global 声明。

3.2 局部变量

1. 局部变量在函数体中(包含形式参数)声明;

2. 局部变量的引用比全局变量快,应优先考虑使用;

3. 若局部变量与全局变量同名,则在函数内隐藏全局变量,只使用同名的局部变量。

a = 100  #全局变量

def f1():
    global a
    print(a)
    a = 300     #修改全局变量a

f1()
print(a)

def f2():
    a = 3     #同名的局部变量
    print(a)

f2()
print(a)


'''
输出结果:
100
300
3
300
'''

4. 参数传递

:函数的参数传递,本质上是从实参到形参的赋值操作。Python 中参数的传递均为“引用传递”,而非“值传递”。

4.1 传递可变对象的引用

可变对象包括:字典、列表、集合、自定义的对象 等,对“可变对象”进行“写操作”,直接作用于原对象本身。

#传递可变对象的引用

a = [34,56]

def f2(m):
    print("m:",m)
    print("m的地址:",id(m))
    m.append(375)

f2(a)
print("a:",a)
print("a的地址:",id(a))

'''
输出结果:
m: [34, 56]
m的地址: 2004856033672
a: [34, 56, 375]
a的地址: 2004856033672
'''

4.2 传递不可变对象的引用

不可变对象包括:数字、字符串、元组、函数 等,对“不可变对象”进行“写操作”,会产生一个新的“对象空间”,并用新的值填充这块空间。

#传递不可变对象的引用

a = 100
print("a的地址:",id(a))

def f3(n):
    print("n的地址:",id(n))
    n = n + 100
    print("n的地址:",id(n))
    print("n =",n)

f3(a)

'''
输出传递:
a的地址: 140726444731888
n的地址: 140726444731888
n的地址: 140726444735088
n = 200
'''

5. 浅拷贝 & 深拷贝

浅拷贝:不拷贝子对象的内容,只拷贝子对象的引用;

深拷贝:将子对象的内存也全部拷贝,对子对象的修改不会影响源对象。

#测试浅拷贝、深拷贝

import copy

def testCopy():
    '''测试浅拷贝'''
    a = [10,20,[5,6]]
    b = copy.copy(a)

    print("a:",a)
    print("b:",b)
    b.append(30)
    b[2].append(7)
    print("**************浅拷贝****************")
    print("a:", a)
    print("b:", b)

def testDeepCopy():
    '''测试深拷贝'''
    a = [10,20,[5,6]]
    b = copy.deepcopy(a)

    print("a:",a)
    print("b:",b)
    b.append(30)
    b[2].append(7)
    print("**************深拷贝****************")
    print("a:", a)
    print("b:", b)

testCopy()
print("**********************************")
testDeepCopy()

'''
输出结果:
a: [10, 20, [5, 6]]
b: [10, 20, [5, 6]]
**************浅拷贝****************
a: [10, 20, [5, 6, 7]]
b: [10, 20, [5, 6, 7], 30]
**********************************
a: [10, 20, [5, 6]]
b: [10, 20, [5, 6]]
**************深拷贝****************
a: [10, 20, [5, 6]]
b: [10, 20, [5, 6, 7], 30]
'''

6. 不可变对象包含可变子对象

在函数中,若修改传递的不可变对象中包含的可变子对象,源对象也发生变化。

a = (10,20,[5,6])
print("a:",id(a))

def test01(m):
    print("m:",id(m))
    m[2][0] = 888
    print(m)
    print("m:", id(m))

test01(a)
print(a)

'''
输出结果:
a: 2203840772440
m: 2203840772440
(10, 20, [888, 6])
m: 2203840772440
(10, 20, [888, 6])
'''

7. 参数类型

7.1 位置参数

函数调用时,实参默认按位置顺序传递,需要个数和形参匹配。

7.2 默认值参数

可以为某些参数设置默认值,这些参数在传递赋值时可选。默认值参数必须放到位置参数后面

7.3 命名参数

可以按照形参的名称传递参数。

#测试参数的类型:位置参数、命名参数、默认值参数

def test01(a,b,c,d):
    print("a:{0}-b:{1}-c:{2}-d:{3}".format(a,b,c,d))

def test02(a,b,c=10,d=20):     #默认值参数
    print("a:{0}-b:{1}-c:{2}-d:{3}".format(a,b,c,d))

test01(1,2,3,4)   #位置参数

test01(b=5,c=6,a=7,d=8)   #命名参数

test02(15,5)
test02(15,5,35)


'''
输出结果:
a:1-b:2-c:3-d:4
a:7-b:5-c:6-d:8
a:15-b:5-c:10-d:20
a:15-b:5-c:35-d:20
'''

7.4 可变参数

即“可变数量的参数”:

1. *param(一个星号),将多个参数收集到一个“元组”对象中;

2. **param(两个星号),将多个参数收集到一个“字典”对象中。

3. 若在带星号的“可变参数”后面增加新的参数,则必须在调用的时候“强制命名参数”。

#测试可变参数、强制命名参数

def f1(a,b,*c,**d):
    print(a,b,c,d)

f1(13,24,20,30,40,name='老白',age=26,job='waiter')


def f2(*a,b,c):
    print(a,b,c)

f2(2,3,b=4,c=5)


'''
输出结果:
13 24 (20, 30, 40) {'name': '老白', 'age': 26, 'job': 'waiter'}
(2, 3) 4 5
'''

8. lambda 表达式

8.1 定义

lambda 表达式可以用来声明匿名函数,是一种简单的、在同一行中定义函数的方法,实际生成了一个函数对象

lambda 表达式只允许包含一个表达式,不能包含复杂语句,该表达式的计算结果就是函数的返回值。

8.2 基本语法

lambda arg1,arg2,arg3... : <表达式>

其中:arg1/arg2/arg3 为函数的参数;<表达式>相当于函数体;运算结果为表达式的运算结果。

#测试lambda表达式

f = lambda a,b,c: a+b+c
print(f(4,5,6))

#效果相当于
def test01(a,b,c):
    return a+b+c


g = [lambda a:a**2, lambda b:b**3, lambda c:c**4]      #函数也是对象
print(g[0](2),g[1](3),g[2](4))

h = [test01,g]      #函数也是对象
print(h[0](4,5,6),h[1][0](2))


'''
输出结果:
15
4 27 256
15 4
'''

9. 嵌套函数

即在函数体内部定义的函数(内部函数)。

#测试嵌套函数

def printName(isChinese,name,familyName):
    def inner_print(a,b):
        print("{0} {1}".format(a,b))

    if isChinese:
        inner_print(familyName,name)
    else:
        inner_print(name,familyName)

printName(True,"蘸糖","白")
printName(False,"George","Orwell")


'''
输出结果:
白 蘸糖
George Orwell
'''

10. nonlocal 关键字

作用类似于全局变量的 global 关键字,用来声明外层的局部变量。

#测试global、nonlocal关键字

a = 100

def outer():
    b = 10
    def inner():
        nonlocal b
        print("original nonlocal b:",b)
        b = 20
        global a
        print("original global a:",a)
        a = 200

    inner()
    print("updated nonlocal b:",b)

outer()
print("updated global a:",a)


'''
输出结果:
original nonlocal b: 10
original global a: 100
updated nonlocal b: 20
updated global a: 200
'''

11. LEGB 规则

Python 在查找“名称”时,按照 LEGB 顺序进行查找:Local-->Enclosed-->Global-->Built in

Local:函数或者类的方法内部;

Enclosed:嵌套函数;

Global:模块中的全局变量;

Built in:Python 保留的特殊名称;

如果一个名称在所有命名空间中都没有找到,则会产生一个NameError。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值