16. 阶段总结
目标:对第二模块 “函数和模块” 阶段的知识点进行总结
概要:
- 知识补充
- 阶段总结(思维导图)
- 练习题
1.知识补充
1.1 nolocal关键字
在之前,我们学过global关键字。
name = 'root'
def outer():
name = "盖伦"
def inner():
global name
name = 123
inner()
print(name)
outer()
print(name)
其实,还有一个nolocal关键字,用的比较少,此处作为了解即可。
name = 'root'
def outer():
name = "盖伦"
def inner():
nonlocal name
name = 123
inner()
print(name)
outer()
print(name)
name = 'root'
def outer():
name = 'alex'
def func():
name = "盖伦"
def inner():
nonlocal name
name = 123
inner()
print(name)
func()
print(name)
outer()
print(name)
name = 'root'
def outer():
name = 'alex'
def func():
nonlocal name
name = "盖伦"
def inner():
nonlocal name
name = 123
inner()
print(name)
func()
print(name)
outer()
print(name)
1.2 yield from
在生成器部分我们了解了yield关键字,其在python3.3之后有引入了一个yield from。
def foo():
yield 2
yield 2
yield 2
def func():
yield 1
yield 1
yield 1
yield from foo()
yield 1
yield 1
for item in func():
print(item)
1.3 深浅拷贝
-
浅拷贝
-
不可变类型,不拷贝。
import copy v1 = "盖伦" print(id(v1)) # 2545640854832 v2 = copy.copy(v1) print(id(v2)) # 2545640854832
按理说拷贝v1之后,v2的内存地址应该不同,但由于python内部优化机制,内存地址是相同的,因为对不可变类型而言,如果以后修改值,会重新创建一份数据,不会影响原数据,所以,不拷贝也无妨。
-
可变类型,只拷贝第一层。
import copy v1 = ["盖伦", "root", [44, 55]] print(id(v1)) # 2507538579072 print(id(v1[2])) # 2507538575872 v2 = copy.copy(v1) print(id(v2)) # 2507538576640 print(id(v2[2])) # 2507538575872
-
-
深拷贝
-
不可变类型,不拷贝
import copy v1 = "盖伦" print(id(v1)) # 2050284377392 v2 = copy.deepcopy(v1) print(id(v2)) # 2050284377392
特殊的元组:
-
元组元素中无可变类型,不拷贝
import copy v1 = ("盖伦", "root") print(id(v1)) # 2680313833792 v2 = copy.deepcopy(v1) print(id(v2)) # 2680313833792
-
元素元素中有可变类型,找到所有【可变类型】或【含有可变类型的元组】 均拷贝一份
import copy v1 = ("盖伦", "root", [11, [44, 55], (11, 22), (11, [], 22), 33]) v2 = copy.deepcopy(v1) print(id(v1)) # 2402519922176 print(id(v2)) # 2402522087680 print(id(v1[2])) # 2402521920768 print(id(v2[2])) # 2402521921472 print(id(v1[2][1])) # 2402521920000 print(id(v2[2][1])) # 2402521919872 print(id(v1[2][2])) # 2402519443776 print(id(v2[2][2])) # 2402519443776 print(id(v1[2][3])) # 2402519748288 print(id(v2[2][3])) # 2402522030720
-
-
可变类型,找到所有层级的 【可变类型】或【含有可变类型的元组】 均拷贝一份
import copy v1 = ["盖伦", "root", [11, [44, 55], (11, 22), (11, [], 22), 33]] v2 = copy.deepcopy(v1) print(id(v1)) # 2035731018752 print(id(v2)) # 2035731019712 print(id(v1[2])) # 2035731019008 print(id(v2[2])) # 2035731018112 print(id(v1[2][1])) # 2035731018240 print(id(v2[2][1])) # 2035731020352 print(id(v1[2][2])) # 2035728279872 print(id(v2[2][2])) # 2035728279872 print(id(v1[2][3])) # 2035728584384 print(id(v2[2][3])) # 2035728758272
import copy v1 = ["盖伦", "root", [44, 55]] v2 = copy.deepcopy(v1) print(id(v1)) # 2044520251008 print(id(v2)) # 2044520248576 print(id(v1[2])) # 2044520247808 print(id(v2[2])) # 2044520248320
-
2.阶段总结
3.练习题
-
一个大小为100G的文件 etl_log.txt,要读取文件中的内容,写出具体过程代码。
# 如果文件有很多行 with open('etl_log.txt',mode='r',encoding="utf-8") as file_object: for line in file_object: pass
# 如果文件只有一行 import os file_size = os.path.getsize("etl_log.txt.txt") read_size = 0 with open('etl_log.txt.txt', 'rb') as file_object: while read_size < file_size: data = file_object.read(1) read_size += len(data)
-
编写一个函数,这个函数接受一个文件夹名称作为参数,寻找文件夹中所有文件的路径并输入(包含嵌套)。
import os def get_file_path(folder_path): for base_path, folder_list, file_list in os.walk(folder_path): for file in file_list: file_path = os.path.join(base_path, file) print(file_path)
-
以下的代码数据的结果是什么?
def extend_list(val, data=[]): data.append(val) return data list1 = extend_list(10) list2 = extend_list(123, []) list3 = extend_list("a") print(list1, list2, list3)
输出:[10, 'a'] [123] [10, 'a']
-
python代码获取命令行参数。
import sys print(sys.argv)
-
简述深浅拷贝?
浅拷贝: - 不可变类型,不拷贝 - 可变类型,只拷贝第一层 深拷贝: - 不可变类型,不拷贝 - 可变类型,所有层级的可变类型都拷贝(元组中如果包含可变类型也会被拷贝)
-
基于推导式一行代码生成1-100以内的偶数列表。
v = [i for i in range(1, 101) if i % 2 == 0] print(v)
-
请把以下函数转化为python lambda匿名函数
def add(x,y): return x+y
add = lambda x,y:x+y
-
看代码写结果
def num(): return [lambda x: i * x for i in range(4)] result = [m(2) for m in num()] print(result)
输出:[6, 6, 6, 6]
-
列表推导式和生成器表达式 [i % 2 for i in range(10)] 和 (i % 2 for i in range(10)) 输出结果分别是什么?
[i % 2 for i in range(10)] ,得到一个列表,内部元素是 [0, 1, 0, 1, 0, 1, 0, 1, 0, 1] (i % 2 for i in range(10)) ,的到一个生成器对象。
-
写装饰器
# 写timer装饰器实现:计算fun函数执行时间,并将结果给 result,最终打印(不必使用datetime,使用time.time即可)。 @timer def func(): pass result = func() print(result)
import time import functools def timer(func_name): @functools.wraps(func_name) def inner(*args, **kwargs): start = time.time() res = func_name(*args, **kwargs) end = time.time() message = "耗时:{}".format(end - start) print(message) return res return inner
-
re的match和search区别?
match,从头开始匹配。 search,在整个字符串中进行匹配。 他们均获取一个匹配成功的值。
-
正则匹配中的贪婪模式与非贪婪模式的区别?
贪婪匹配,尽量多的匹配字符。 非贪婪匹配,尽量少的匹配字符(只要符合匹配条件就结束),特点是:?
-
sys.path.append("/root/mods")的作用?
将路径加入到sys.path,那么项目中就可以直接导入/root/mods目录下的模块和包。
-
写函数
有一个数据结构如下所示,请编写一个函数从该结构数据中返画由指定的 字段和对应的值组成的字典。如果指定字段不存在,则跳过该字段。 DATA = { "time": "2016-08-05T13:13:05", "some_id": "ID1234", "grp1": {"fld1": 1, "fld2": 2, }, "xxx2": {"fld3": 0, "fld4": 0.4, }, "fld6": 11, "fld7": 7, "fld46": 8 } fields:由"|"连接的以fld开头的字符串, 如fld2|fld7|fld29 def select(fields): print(DATA) return result
DATA = { "time": "2016-08-05T13:13:05", "some_id": "ID1234", "grp1": {"fld1": 1, "fld2": 2, }, "xxx2": {"fld3": 0, "fld4": 0.4, }, "fld6": 11, "fld7": 7, "fld46": 8 } def select(fields): result = {} field_list = fields.split('|') for field in field_list: value = DATA.get(field) if not value: continue result[field] = value return result
-
编写函数,实现base62encode加密(62进制),例如:
内部维护的数据有:0123456789AB..Zab..z(10个数字+26个大写字母+26个小写字母)。 当执行函数: base62encode(1),获取的返回值为1 base62encode(61),获取的返回值为z base62encode(62),获取的返回值为10 base62encode(63),获取的返回值为11
思路:一直让输入的数值除以62取余数,以此取到的余数分别是每一位的索引位置。 5/62 得到 0 , 余数 5 05 62/62 得到 1 , 余数 0 10 178/62 得到 2 ,余数 54 2P 98723/62 得到1592,余数19 [C,B,K] 1592/62 得到25,余数42
import string import itertools MAP = list(itertools.chain(string.digits, string.ascii_uppercase, string.ascii_lowercase)) def base62encode(num): total_count = len(MAP) position_value = [] while num >= total_count: num, remain = divmod(num, total_count) position_value.insert(0, MAP[remain]) position_value.insert(0, MAP[num]) result = "".join(position_value) return result
-
基于列表推导式一行实现输出9*9乘法表。
# # 第一步:[['{}*{}'.format(i, j) for j in range(1, i + 1)] for i in range(1, 10)] # 第二步:[" ".join(['{}*{}'.format(i, j) for j in range(1, i + 1)]) for i in range(1, 10)] # 第三步:'\n'.join([" ".join(['{}*{}'.format(i, j) for j in range(1, i + 1)]) for i in range(1, 10)])
print("\n".join([" ".join(['{}*{}'.format(i, j) for j in range(1, i + 1)]) for i in range(1, 10)]))