python函数基础与变量作用域
最后更新时间:
文章总字数:
预计阅读时间:
一.函数基础知识
- 函数是面向过程编程的最小单位,也是一种数据
- 目的就是封装方便以后复用
- 函数分自定义函数,内置函数(python官方),第三方函数(第三方库)
<class 'function'>
def:用于声明一个函数,告诉 Python 这是一个函数的定义。
function_name:函数名,一个有效的标识符,规则和变量名一致。
parameters:形参,可以是0 ~ n 个,参数之间用逗号分隔。
函数体:定义函数执行的具体操作。
return:指定函数的返回值,没有则默认返回None。
return之后的代码不会执行。
test
10
test
test
1
二.函数调用
- 函数调用是一个表达式,可以参与运算
2.1 位置传参
1 2
2 1
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[21], line 8
6 func(1,2)
7 func(2,1)
----> 8 func(1,2,3)
TypeError: func() takes 2 positional arguments but 3 were given
1
2.2 关键词传参
3 1 2
1 3 2
Cell In[36], line 3
func(1,c = 3,2)
^
SyntaxError: positional argument follows keyword argument
2.3 参数默认值
1 2 1
1 2 3
1 2 3
1 None 3
Cell In[46], line 2
def test(a = 1, b, c = 3):
^
SyntaxError: parameter without a default follows parameter with a default
2.4 可变位置参数
(1, 2, 3)
<class 'tuple'>
()
<class 'tuple'>
1
(2,)
<class 'tuple'>
2.5 可变关键词参数(字典)
{'b': 2, 'c': 3}
<class 'dict'>
b 2
c 3
- 两个可变参数的联合使用
- 实质是剩余参数传递,即普通形参传完后剩余的参数传递给可变参数
1
(2, 3, 4)
{'Name': 'clocky7'}
2.6 多参数解包
2.6.1 解包位置传参
1 2 3
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[68], line 6
3 print(a,b,c)
5 x = (1,2,3,4)
----> 6 test(*x)
TypeError: test() takes 3 positional arguments but 4 were given
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[70], line 5
3 print(a,b,c)
4 x = (1,2)
----> 5 test(*x)
TypeError: test() missing 1 required positional argument: 'c'
2.6.2 解包关键字传参(字典)
1 2 3
注意 : * 本身不是参数,只是一个占位符
1 3
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[83], line 3
1 def test(a,*,b = 3):
2 print(a,b)
----> 3 test(1,3)
TypeError: test() takes 1 positional argument but 2 were given
1 4
三.可变与不可变参数
实质上是传入变量中的数据,但指向一个对象。
10
[20, 2, 3]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[92], line 5
3 a[0] = 20
4 z = (1,2,3)
----> 5 test(z)
6 print(z)
Cell In[92], line 3, in test(a)
2 def test(a):
----> 3 a[0] = 20
TypeError: 'tuple' object does not support item assignment
四.匿名函数
没有名字,可以有任意数量的参数,但只能包含一个表达式,并返回该表达式的结果。用lambda定义匿名函数。
- lambda arguments: expression
2
Even
Odd
五.内置函数
False
True
False
True
15
[1, 2, 3, 4, 5]
[3, 1, 4, 5, 2]
这里补充一个小知识:经典的math库中abs()表示取绝对值
<list_reverseiterator object at 0x0000019B8496A530> <class 'list_reverseiterator'>
[3, 2, 1]
True
True
False
<zip object at 0x0000019B84F18880> <class 'zip'>
[(1, 'name', 'clocky'), (2, 'age', '20')]
0
1
2
__name__
__doc__
__package__
__loader__
__spec__
__builtin__
__builtins__
........
{'x': 1, 'y': 2}
<filter object at 0x000002A4449C1F60> <class 'filter'>
[1, 2, 3, 4, 5]
5.1 高阶函数
5.1.1 map
[None, 2, None, 4, None, 6, None, 8, None, 10]
5.1.2 reduce
0 1
1 2
3 3
6 4
10 5
15
六.变量作用域
指在程序中某个变量的有效范围,也就是在代码的哪个部分可以访问或修改该变量
Python中的变量作用域遵循LEGB规则(Local, Enclosing, Global, Built-in),依次搜索变量的定义位置
函数内部可以访问内部变量和外部的全局变量,外部则不能访问内部局部变量
6.1 Local→局部作用域
在函数调用时被创建,在函数调用后自动销毁。
6.2 Enclosing→嵌套作用域
指外层函数中的变量,在内层函数中可访问,但不可修改。
当一个函数嵌套在另一个函数内部时,外层函数的变量属于Enclosing作用域
内层函数变量若与外层变量同名,则优先选择内层
实质上就是在最内层找到变量,若找不到,则继续往外层找,一层一层直到找到为止。
200
6.3 全局作用域
指模块级别定义的变量,整个模块都可以访问。
如果想在函数中修改全局变量,需要使用
global
关键字
6.4 Built-in→内建作用域
包含Python内建的函数、异常和常量,如
print()
,len()
,int
,Exception
等。这些变量可以在任何地方使用。
6.5 函数调用问题
2
1
修改变量的值
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
Cell In[31], line 7
4 print(x)
5 x = 2
----> 7 f1()
Cell In[31], line 4, in f1()
3 def f1():
----> 4 print(x)
5 x = 2
UnboundLocalError: cannot access local variable 'x' where it is not associated with a value
1
2
2
3
1
__main__
6.6 函数内层分配
1.将函数代码存储到代码区,函数中代码不执行。
2.调用函数时,在内存中开辟空间(栈帧),存储函数内部定义的变量。
3.函数调用后,栈帧立即被释放。
七.递归函数
1 None
1 None
1 None
...
1 None
1 None
---------------------------------------------------------------------------
RecursionError Traceback (most recent call last)
Cell In[40], line 10
8 print(fn())
9 print(fn1())
---> 10 fn1()
Cell In[40], line 9, in fn1()
7 print(a)
8 print(fn())
----> 9 print(fn1())
Cell In[40], line 9, in fn1()
7 print(a)
8 print(fn())
----> 9 print(fn1())
[... skipping similar frames: fn1 at line 9 (2972 times)]
Cell In[40], line 9, in fn1()
7 print(a)
8 print(fn())
----> 9 print(fn1())
Cell In[40], line 7, in fn1()
6 def fn1():
----> 7 print(a)
8 print(fn())
9 print(fn1())
File c:\Users\Clocky7\anaconda3\envs\start1\Lib\site-packages\ipykernel\iostream.py:664, in OutStream.write(self, string)
655 def write(self, string: str) -> Optional[int]: # type:ignore[override]
656 """Write to current stream after encoding if necessary
657
658 Returns
(...) 662
663 """
--> 664 parent = self.parent_header
666 if not isinstance(string, str):
667 msg = f"write() argument must be str, not {type(string)}" # type:ignore[unreachable]
RecursionError: maximum recursion depth exceeded
5
120