python
python
编译型与解释型语言区别:
编译型:开发完成,一次性把所有的代码进行编译成机器成识别的二进制码,在运行。
代表语言:c, c++
优点:执行速度快。
缺点:开发速度慢,调试周期长。
解释型:代码从上到下一行一行解释并运行。
代表语言:python,php
优点:开发效率快,调试周期短。
缺点:执行速度相对慢。
python的解释器
1、Cpython(审方推荐)
把python代码转化为c语言能识别的二进制码
2、Jpython
把pythont代码转化为java语言能识别的二进制码
3、PyPy
将所有代码一次性编译成二进制码,加快执行效体(摸仿编译型语言的一款python解器)
4、其他语言解拜器
把pytham代码转化为其他语言能识别的二进制码
变量和赋值
什么是变量
-
一个实体的指代
-
查看变量的内存地址
id(x)
-
可重新赋值
-
为变量层值
- 通过=来赋值
x = 3
- 被重新赋值之后的值去哪了?
- 被系统回收了。
Python的常量
- python没有常量这个数据类型
- 程序员之间的约定如果这个变量的命名都是大写字母,那么就视为一个常量
Python的六大基本类型
强调基本的数据类型和数据结构指向的范围更加广泛,不要产生错误的认知,形成思维定式
通过type()函数来查看当前变量的数据类型
int(整数)
int('1')
float(浮点数)
float('1.0')
float('INF')
- 因为计算机内部只认识1和0,所以浮点数强调的时小数的表现形式
string(字符串,字符序列)
str(2)
- 在有些语言中,单个字符也是一个基本的数据类型(char)
- 有序的
- 如何表示字符串
''
""
''''''
""""""
转义字符
告诉python解释器,我们当前要表示的是一个字符或者是特殊字符
-
通过\来转义
"2\"" "2\n"
boo1ean(布尔值)
bool(2)
bool(0)
-
用来表示True或者False
- True等价于1
- False等价于0
-
bytes(二进制序列)
二进制的表示形式
-
None(空)
-
有了False和0为什么还要有None
因为False和0有时候也代表了一种结果
-
Python的四大基本数据结构
list(列表)
-
什么是列表?
用来装载不同数据类型的数据集结构
-
列表的特点
- 有序的
- 可以装载任意数据类型
- 可以更改的
-
如何表示list
-
通过list()新建一个列表
list("hello world")
-
通过[声明一个列表
a=[1,2,3]
-
tuple(元组)
- 什么是元组
可以简单地认为,元组就是不可修改的例列表常用来表示记录
-
元组的特点?
- 有序的
- 可以装载任意数据类型
- 不可更改
-
如何表示tuple
通过tuple()新建一个元组
tuple("hello")
-
通过(,)来声明一个元组
a=(1,2,3) #声明单个元素的元组,要添加逗号 a = (1,)
dict(字典)
-
什么是字典?
字典也叫hashtable,通过hash(散列)函数将传入的key值生成地址来查找value
key -> hash函数 -> 返回了value的地址 -> 通过地址返回value值
-
字典的特点
- 无序的
- python3.6是有序的.无视这一点
- 字典中的key必须是可hash的,也就是不可更改的,唯的
- 可以更改的
-
如何表示字典
-
通过dict()来创建字典
dict(a=2)
-
通过)来声明一个字典
a={"a":2}
-
set(集合)
- 什么是set
- 如何表示set
- 通过set()来创建
-
set(集合)
-
什么是set
set其实是没有value的字典
-
集合的特点
- 无序的
- 集合中的key必须是可hash的
- 可以更改的
- 元素是唯的
-
如何表示set
-
通过set()来创建集合
set([1,2,2])
-
通过{}来表示
{1,2,3}
课后作业
- 四大基本数据结构中那些是可变的那些是不可变的
- 四大基本数据结构中哪些是有序的.那些是无序的?
- 创建set,Iist,dict,tuple实例每个数据结构的实例需要包括六大基本类型.
Python函数的基本介绍
什么是函数?
函数是一段可以直接被另外一段程序或代码引用的程序或代码,也叫做子程序,方法。
- 可重复使用
- 可互相调用
函数的目的
- 为了代码段的复用
在Python中如何定义一个函数?
def foo(arg):
return "Hello "str(arg)
函数的组成
-
参数列表
-
必须参数
当前参数必须按顺序传入 -
关键字参数
根据关键字参数传参可以无视顺序def foo(arg-None,arg_2=None)
-
默认参数
def foo(arg='tunan',arg_2=None)
-
不定长参数
在装饰器中会大量应用
可以接受任意长度的参数 -
*
代表了省略,省略了参数tuple(元组)
-
**
省略了关键字参数dict(字典)
-
-
函数体
-
返回值
Python的运算符
算术运算
-
加法:
+
-
减法:
-
-
乘法:
*
-
除法:
/
-
整除:
//
-
取余数:
%
-
x的y次幂:
x**y
-
开方(没有提供直接的运算符):
x ** (1/2)
-
取绝对值
赋值运算
通过 =
赋值
a = 1
比较运算
比较的是两个对象的字面值,字面值暂时可以简单地理解为输出值
<
>
<=
>=
==
- 等于
!=
- 不等于
标识号比较运算
比较的是两个变量的内存地址
- is
- is not
- 赋值类型为 str,int 的时候要考虑 python 常量池
a = "test_1"
b = "test_1"
a is b
成员检测运算
-
in
a = [1,2,3] 1 in a b = [1,2] b in a
- not in
布尔运算
判断当前语句的结果是True还是False
-
and
只有两边都是True才返回True -
or
两边表达式有一个True返回的结果为True-
短路
表达式A or 表达式B 当表达式A为True时,表达式B就不会运行
逻辑取反
not
位运算
二进制运算,未来刷避的时候再说,有兴胞的同学可以了解一下
-
^
>>
<<
&
|
Python运算符优先级
运算符 描述 or 布尔运算或 and 布尔运算与 not 布尔运算逻辑取反 in,not in,is,is not,<,!=,.. 比较运算,成员检测运算,标识号检测 +,- 加法和减法 *, /, //, % 乘、除法、整除、取余 +x, -x 正负数 ** 幂 -
自定义优先级
如果不确定优先级,出于可读性和避免未知的BUG,我们都应该用()来自定义优先级
- 通过()
(not b and c) or (d and e)
课后作业
- 用函数实现一个具有加、减、乘、除、整除、取余、开方的计算器。
字符串(字符序列)和字节序列
-
字符
由于历史原因将字符定义为un1code字符还不够准确,但是未来字符的定义一定是unicode字符
-
字节
就是字符的二进制表现形式
-
码位
我们计算机显示的实际上是码位
'你好'.encode("unicode_escape").decode() '\\u4f60\\u597d' '\u4f60\u597d' '你好'
UNICODE标准中以4-6个十六进制数字表示
编码
-
字节序列(bytes)->字符序列(string)…………解码(decode)
"你好".encode("utf-8") b'\xe4\xbd\xa0\xe5\xa5\xbd'
-
字符序列(string)->字节序列(bytes)…………编码(encode)
b = "你好".encode("utf-8") b.decode("utf-8") '你好'
编码错误
-
乱码和混合编码
-
检查编码
没有办法通过字节序列来得出编码格式都是统计学来预估当前的编码# 安装chardet pip install chardet #导入charet import chardet chardet.detect(b)
-
-
解决乱码和混合偏码
-
忽略错误编码
b_2.decode("utf-8", errors='ignore') '你好'
-
利用鬼符来替换
b_2.decode("utf-8", errors='replace') '你好��'
-
字符串的CRUD操作
通过dir("")可以查看当前字符串的操作方法
Create(创建)
+
a = "a"
id(a)
22951584
a = a+"b"
id(a)
60513280
a
'ab'
-
+=
a += b 就是 a = a + 'b' 省略写法
Retrieve(检索
-
根据索获取字符
在计算机语言当中,索引值是从0开始数的
a = "hello, world" a[1] 'e'
-
find(获取目标字符的索引值)
a.find("e") 1
-
find 和 index(获取目标字符的索引值)
a.find("!") -1 # 找不到目标字符时,index会报错 a.index("!") Traceback (most recent call last): File "D:\Program Files\JetBrains\PyCharm 2022.3.1\plugins\python\helpers\pydev\pydevconsole.py", line 364, in runcode coro = func() ^^^^^^ File "<input>", line 1, in <module> ValueError: substring not found
-
startswith和endswith
f = "2020-11-22-xxxxx" f.startswith("2020-11-22") True f_1 = "xxxx.jpg" f_1.endswith("jpg") True
UPDATE(更新)
-
replace(替换)
返回的是一个新的字符串a.replace("wer", "wor")
-
split(分割)
a = "<《python》,《java》,《c++》" a.split(",") ['《python》','《java》','《c+》']
-
join(拼接)
a = "<《python》,《java》,《c++》" a.split(",") ['<《python》', '《java》', '《c++》'] b = a.split(",") ",".join(b) '<《python》,《java》,《c++》'
DELETE(删除)
-
strip
a = ' hello, world ' a.strip() 'hello, world'
-
Istrip
-
rstrip
字符串的输出和输入
保存到文件
# open()函数打开一个文件,没有文件会新建,但是路劲不对会报错
# 指定文件名,方法(读,写,追加),编码格式
output = open("output.txt","w",encoding="utf-8")
content = "hello,world"
# 正式写入文
output.write(content)
# 关闭文件句柄
output.close()
读取文件
input = open("output.txt","r",encoding="utf-8")
# 获取文件中的内容
content = input.read()
print(content)
# 智时理解为贝能读取一海
content_2 = input.read()
print(content_2)
追加文件
output open("output.txt","a",encoding="utf-8")
content "\nhello,world"
# 正式写入文件
output.write(content)
# 关闭文件句柄
output.close()
字符串的格式化输出
format
-
按传入参数默认顺序
a = "ping" b = "pong" "play pingpong:{}, {}".format(a, b)
-
按指定参数索引
a = "ping" b = "pong" "play pingpong:({0}, {1}, {0}, {1}".format(a,b)
-
按关键词参数
a = "ping" b = "pong" print("play pingpong:{a},(b},{a},{b}".format(a='ping', b='pong'))
-
按变量(推荐但是只有3.6以上才可以使用)
a = "ping" b = "pong" print(f"playing pingpong:{a},{b}")
-
小数的表示
"{:.2f1}".format(3.14159)
"3.14"
-
%
"playing %s %s" % ("ping","pong") 'playing ping pong'
课后作业
-
练习字符串的编码和解码
-
练习字符串的CRUD
-
练习字符串的格式化
content = ''' "playing %s %s" % ("ping","pong") 'playing ping pong' '''
-
将content内容保存到本地文件
了解变量和引用
-
变量简单地说就是指向了一个实体
-
引用简单地说就是指向变量的变量
a = 1 b = a id(a) 140732024087336 id(b) 140732024087336
基础数据结构的CRUD操作
List(列表)
- list中存的元素是引用
create(增)
-
append
末尾添加元素
l ['a', 'b'] l.append('c') l ['a', 'b', 'c']
-
+
和+=
-
+
拼接两个列表,然后返回一个新列表
-
+=
l ['a'] l = l + ['b'] l ['a', 'b'] l.append('c') l ['a', 'b', 'c']
-
*
和*=
l = ['a'] l ['a'] l_1 = l*10 l_1 ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'] id(l_1[1]) 140732053357960
-
insert
指定位置添加元素
l = ['a'] l ['a'] l.insert(0,'b') l ['b', 'a']
-
Retrieve(检索)
-
索引取值
所有序列都支持索取值 -
切片
your_list(start:end:step) #取一段区问 your_list[start:end] #取最后一个值 your_list[-1] #问隔问题 your-11st[1:20:21
-
index
l ['a','b','c'] l.index('a') 0
-
Update(更新)
-
索赋值
l[0] = 'a'
-
切片赋值
l = ['a','b','c','d'] l[0:2] = 'a' l ['a', 'c', 'd']
-
DELETE(删除)
- pop()
从末尾别除元素并返回
l
['a',b','c]
X=l.pop()
l
['a', 'b']
X
'c'
- clear()
清楚当前列表的元素,不会改变列表的内存地址。
★SORT排序
-
sort()
l = [5,4,3,2,1] l [5, 4, 3, 2, 1] l.sort() l [1, 2, 3, 4, 5]
-
sorted
-
排序后返回新列表
l [5, 4, 3, 2, 1] l_1 = sorted(l) l_1 [1, 2, 3, 4, 5] id(l) 2713722638592 id(l_1) 2713722645184
-
reverse
l = list(range(10)) l [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] l.reverse() l [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
-
reversed
l = list(range(10)) l_2 = reversed(l) l_2 <list_reverseiterator object at 0x00000277D67D59C0> list(l_2) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-
tuple
- Create
无 - Retrieve
- 素取值
- index
- 切片
- Update
无 - Delete
无
- Create
dict
Create
-
键对值赋值
-
update
提供合并字典的功能d {'a': 1} b = dict(b=2, c=3, d=4) d.update(b) d {'a': 1, 'b': 2, 'c': 3, 'd': 4}
-
setdefault
如果字典中没有当前key,那么就设置默认值d {'a': 1, 'b': 2, 'c': 3, 'd': 4} d {'a': 1, 'b': 2, 'c': 3, 'd': 4} d.setdefault('a', 5) 1 d.setdefault('e', 5) 5 d {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
Retrieve
-
键对值访问
-
get
键对值访问缺失key会报错.而get可以指定默认值d {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5} d['f'] Traceback (most recent call last): File "D:\Program Files\JetBrains\PyCharm 2022.3.1\plugins\python\helpers\pydev\pydevconsole.py", line 364, in runcode coro = func() ^^^^^^ File "<input>", line 1, in <module> KeyError: 'f' d.get('f', '不存在') '不存在'
-
keys()
返回所有keyd.keys()
-
values()
返回所有valued.values()
-
items()
返回所有键对值d.items()
Update
-
键对值赋值
d['a'] = 100
-
update
d.update({"b":200,"c":300]) d {'a':100,'b':200,'c':300,'d':0}
Delete
- pop(key)
制除当前元素并返回value - popitem()
对于人来说相当于随机返回一个tem - clear()
set
Create
- add
- update
Retrieve
-
运算符
in
s = {'a', 'b', 'c', 'd'} 'g' in s False 'a' in s True
update
- union
合并两个set并返回一个新的set
delete
-
remove和discard
discard缺失元素时不会报错,而remove会报错
>>> s ['b','c','a'] >>> s.remove("a") >>> s {'b',"c"} >>s.discard("e") >>s.remove("a") Traceback (most recent call last): File "<stdin>",line 1,in <module> KeyError:'a'
-
pop()
当成无序别除并返回元素
课后作业
- 完成四大基础数据结构的CRUD操作
Python的逻辑控制语句
条件判断语句
-
if
-
elif
-
else
a = 50 if a > 100: print("a 超过了阈值") elif a == 50: print("a 只有阈值的一半") else: print("a 小于阈值")
循环语句
for循环
遍历一个可送代对像(暂时理解为s).会影响相同作用域当中的变量
l=[1,2,3,4,5,6]
e=0
for e in l:
print(e)
print(f"final e value:{e}")
获取索引值和值
l=[1,2,3,4,5,6]
for i,e in enumerate(l):
print(f"index:{i},value:{e}")
whi1e循环
一定要有逻辑判新语句来退出h11e循环
while 判断语句:
表达式
while True:
判断语句
表达式
跳出循环
-
break
停止当前循环
-
continue
跳过当前的执行逻辑继续循环语句的执行
-
pass
跳过当前条件判断中的执行语句,后续语句继续执行。
Python的异常与处理
异常
程序遇到严重错误时,会终止程序的运行并抛出异常
def my_sub(a,b):
return a /b
my_sub(1, 0)
捕获异常
try:
表达式
except [Exception]:
def my_sub(a,b):
finally:
表达式
def my_sub(a, b):
try:
return a / b
except Exception as e:
#print(e)
print("分母不可为0")
return None
my_sub(1,0)
Exception
所有异常的基类,所有的异常都是Exception的子类
- 处理异常颗粒度要细一点,尽量不要捕获基类Exception,尤其是数据处理的时候。
常见的异常
-
IndexError
索引值超过了列表长度>>> l = [1] >>> l[1] Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: list index out of range
-
KeyError
找不到Key>>> d = {'a':1,'b':2} >>> d {'a': 1, 'b': 2} >>> d['c'] Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'c'
-
ValueError
传入的参数错误>>> int('a1') Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: invalid literal for int() with base 10: 'a1'
-
TypeError
类型错误常见于运算>>> 1 + '2' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'int' and 'str'
-
SyntaxError
语法报错,检查自己的语法有没有写错 -
IndentationError
缩进错误-
"混用tab和space(空格
-
缩进长度不对
-
如何处理异常
-
处理
-
抛出新异常
def my_sub(a, b): try: return a / b except ZeroDivisionError: print("分母不可为0") raise Exception("params error") finally: print("function my_sub end") my_sub(1,0)
-
重新抛出
def my_sub(a, b): try: return a / b except ZeroDivisionError: print("分母不可为0") raise ZeroDivisionError finally: print("function my_sub end") my_sub(1,0)
-
忽略(不推荐)
pass
用来指示当前处理语句没有正式写完,尽量不要忽略异常,否则代码的健壮度会很差,造成不可预知的bug。
自定义异常
class ParamsError(Exception):
pass
def my_sub(a, b):
try:
return a / b
except ZeroDivisionError:
print("分母不可为0")
raise ParamsError("分母不可以为0")
finally:
print("function my_sub end")
my_sub(1,0)
课后作业
-
用for循环和while:来完成简单的i计数
-
用for循环和while循环两种方式来实现斐波那契函数限制在100以内
-
斐波那奖函数
第N项是N-1,N-2的和F(n)=F(n-1)+F(n-2)
[0,1,1,2,3,5,8,13,21..]
-
-
在第二周第一节课我们实现的简单计算器的基础上对参数进行检查如果报错就抛出我们自定义异常
ParamsError
重新认识函数
内置函数
-
认识Pytho自带的.可全局调用的函数避免我们命名冲突导致了函数性状发生改变
-
直看Python携带的内置函数
-
from pprint import pprint # 格式化输出的用 pprint(dir(__builtins__))
-
常见的内置函数
-
str
>>> int(1.0) 1 >>> int("1.0") Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: invalid literal for int() with base 10: '1.0' >>> int("1") 1
-
float
>>> float("1.0") 1.0 >>> float(1) 1.0 >>> float('1') 1.0
-
bytes
>>> bytes('a'.encode("utf-8")) b'a'
-
bool
>>> bool(0) False >>> bool(1) True >>> bool('0') True >>> bool('') False >>> bool(0.0) False
-
list
只要是序列都可以转换成
list
>>> list("hello world!") ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!']
-
tuple
-
>>> tuple("Hello World!") ('H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!') >>> tuple([1,2,3]) (1, 2, 3)
-
dict
>>> dict(a=1) {'a': 1}
-
set
>>> set([1,2,2,3,3]) {1, 2, 3}
-
id
>>> a = '1' >>> id(a) 140731469433984
-
dir
当前对像下的所有方法和属性
在Python中一切皆为对像dir(__builtins__)
-
max
返回一个序列中的最大值>>> max([5,12,14,15]) 15
-
min
>>> min([34,43,5,67]) 5
-
range
返回一组数字区间的可送代对象
>>> r = range(1000) >>> r range(0, 1000) >>> for i in range(10): print(i)
-
函数的形参和实参
形参
形式参数简单地说就是还没接受到实际值的参数.函数未调用时就是形参
def my_power(a,b):
return a *b
实参
实际传入的参数函数调用时传入的值就叫实参
print(my_power(2,3))
函数的返回值
-
返回值的类型
任意类型包括函数 -
如何接受返回值
-
接收单个值
-
一个变量接受返回的多个值
实际上返回的是个tuple>>> def foo(a, b): ... return a*2, b*2 ... >>> result = foo(1, 2) >>> print(result) (2, 4)
-
-
多个变量按顺序接收
实现原理是元组解包(unpack)
>>> def foo(a, b): ... return a*2, b*2 ... >>> result = foo(1, 2) >>> print(result) (2, 4) >>> a,b = foo(1,2) >>> a 2 >>> b 4 # 等同于 >>> result = foo(1,2) >>> a,b=result >>> a 2 >>> b 4
-
不定长变量接收
>>> result=(1,2,3,4,5,6,7) >>> a, *b, c = result >>> a 1 >>> b [2, 3, 4, 5, 6] >>> c 7
匿名函数
顾名思义匿名函数就是没有名字的函数一般都是提供给高阶函数调用
-
通过1 ambda关键字来声明匿名函数
>>> lambda x: x ** 2 #返回的是一个医名函数对象 <function <lambda> at 0x00000245BE1704A0>
-
函数体是纯表达式
-
不能有复杂的逻辑判断语句
-
唯一例外的例子:
lambda x: 返回值 if 纯表达式 else 返回值 lambda x: True if x % 2 == 0 else False
-
-
不能有循环语句
-
不能有异常捕获
-
不能有赋值语句
-
不能有return
-
默认表达式运行的结果就是返回值
>>> lambda x: x ** 2 # 返回值就是 x ** 2
-
-
-
例子
l = [[3, 2], [5, 1], [2, 4], [7, 6]] l.sort() print(l) l.sort(key=lambda x: x[1]) print(l)
高阶函数
接受函数作为参数或者把函数作为结果返回
- map(映射)
对一个序列每个元素进行相同的操作,这个过程就叫映射
>>> l = [1,2,3]
>>> m = map(lambda x: x**2,l)
# map对象是一个可迭代对象,需要驱动可迭代对象返回值,list就有这样的功能,暂时不要太纠结
>>> list(m)
[1, 4, 9]
>>> l
[1, 2, 3]
-
等同于以下:
def my_power_2(a): return a ** 2 # 匿名函数只是图方便,所有的匿名都可以通过正常函数替换 m = map(my_power_2, [1,2,3]) print(list(m))
-
多用于和
math
库进行运算操作import math m = map(math.sqrt,[1,4,9,16,25]) print(list(m))
-
filter(过滤)
filter(函数,可选代对象) 函数中的表达式返回结果为False,就会被过滤
l = list(range(10)) # 过滤偶数 f = filter(lambda x: x%2, l) print(list(f)) l = list(range(10)) # 过滤奇数 f = filter(lambda x: False if x%2 == 1 else True, l) print(list(f))
递归函数
在函数中调用自身的函数就递归函数
-
核心思想
将大的任务拆分为子任务来解决复杂问题只要大任务能拆分成子任务,就可以使用递归F(n)=F(F(n-1))
-
声明一个递归函数(阶乘)
-
一定要有退出机制
F(n)=n * F(n-1) def fact(n): if n == 1: return 1 return n * fact(n-1)
-
课后作业
-
给定一个列表根据grade来排序
classes = [ {"name":"n_1", "age": 24, "grade": "A"}, {"name":"n_2", "age": 21, "grade": "B"}, {"name":"n_3", "age": 20, "grade": "A"}, {"name":"n_4", "age": 26, "grade": "C"}, {"name":"n_5", "age": 27, "grade": "C"}, {"name":"n_6", "age": 23, "grade": "D"}, {"name":"n_7", "age": 29, "grade": "A"}, {"name":"n_8", "age": 22, "grade": "B"}, {"name":"n_9", "age": 26, "grade": "D"}, {"name":"n_10", "age": 28, "grade": "A"} ]
-
通过filter语句来筛选出Grade为A的同学
-
通过map函数将上述同学的age+1对原数据结构有影响.尽量不要用lambda)
-
使用递归函数重构斐波那契函数
f(n)=f(n-1)+f(n-2)
作用域
程序创建访问,改变一个变量时,都是在一个保存该变量的空间内进行,这个空间被称为命名空间,即作用域
Built-in
内置
可以在Python环境中的任何模块任意位置访问和调用
Global
全局变量
-
只作用于当前模块(可以理解为当前文件)
-
可以简单地理解为定义在函数外的变量就是全局变量如果在函数体定义那就是局部变量,
-
如何将局部变量变成全局变量?
-
使用g1oba1关键字
a=1 def foo(): global a a=2 print(a) foo() print(a)
-
Enclosed
(嵌套)自由变量
在嵌套函数中,访问函数体之外的非全局变量
-
只作用于嵌套函数体
-
最大的应用就是闭包
-
自由变量是个相对的概念
-
使用non1oca1关键字
def make_averager(): total = 0 count = 0 def averager(value): nonlocal total,count total +value count +1 return total / count return averager my_avg = make_averager() print(my_avg(1)) print(my_avg(2))
-
Local
局部变量
-
只作用于当前函数体
-
一旦变量在函数体中赋值那么该变量相对该函数来说就是局部变量
a = 1 b = [] def foo(): a=2 b.append(2) # 禁局部变量会在函数声明的时候就定义好 # 不是按照我们逻辑思维上先执行全周变量b,append(2),然后再声明·个局部变量b # 而是再函数声明之初就己经定义了b为局部变量 # b=3 return None foo() print(a) print(b)
闭包和装饰器
-
闭包
闭包指延申了作用域的函数也就是作用域中的Enclosed的概念def make_averager(): series=[】 def averager(value): series.append(value) total sum(series) return total / len(series) return averager # my-avg就是延中了作用域的函数 # series就是被延申作用域的变量 my_avg = make_averager() print(my_avg(1)) print(my_avg(2))
装饰器
-
实现原理
就是闭包延申了被装饰函数的作用域本质是将函数作为参数传递给一个可调用对象(函数或类) -
目的
增加和扩展可调用对象(函数或类)的行为 -
实现一个装饰器
-
通过
@
关键字装饰函数def clock_it_deco(func): def wrapper("args,**kwargs): start_time time.time() result func("args,**kwargs) end_time time.time() print(f"{func._name_} execute time:{format(end_time - start_time,'.2f')} s") return result return wrapper @clock_it_deco def foo(a,b): count 1 while True: if count a *b: break count +1 foo(10,5)
-
课后作业
-
背诵作用域的概念
-
练习作用域之间的转换
-
默写一个装饰器,用来输出函数的执行时间
-
使用装饰器来为斐波那契函数添加缓存
def cache_deco(func): # 保存n执行后的结果 a = {} # 判断当前cache a中是否有结果,有的话就直接返回,没有就执行以下 result func(n) return result @cache_deco def fibo(n): pass
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?