16. 阶段总结

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.练习题

  1. 一个大小为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)
    
  2. 编写一个函数,这个函数接受一个文件夹名称作为参数,寻找文件夹中所有文件的路径并输入(包含嵌套)。

    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)
    
  3. 以下的代码数据的结果是什么?

    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']
    
  4. python代码获取命令行参数。

    import sys
    
    print(sys.argv)
    
  5. 简述深浅拷贝?

    浅拷贝:
    	- 不可变类型,不拷贝
        - 可变类型,只拷贝第一层
    深拷贝:
    	- 不可变类型,不拷贝
        - 可变类型,所有层级的可变类型都拷贝(元组中如果包含可变类型也会被拷贝)
    
  6. 基于推导式一行代码生成1-100以内的偶数列表。

    v = [i for i in range(1, 101) if i % 2 == 0]
    print(v)
    
  7. 请把以下函数转化为python lambda匿名函数

    def add(x,y):  
        return x+y
    
    add = lambda x,y:x+y
    
  8. 看代码写结果

    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]
    
  9. 列表推导式和生成器表达式 [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)) ,的到一个生成器对象。
    
  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
    
  11. re的match和search区别?

    match,从头开始匹配。
    search,在整个字符串中进行匹配。
    
    他们均获取一个匹配成功的值。
    
  12. 正则匹配中的贪婪模式与非贪婪模式的区别?

    贪婪匹配,尽量多的匹配字符。
    非贪婪匹配,尽量少的匹配字符(只要符合匹配条件就结束),特点是:?
    
  13. sys.path.append("/root/mods")的作用?

    将路径加入到sys.path,那么项目中就可以直接导入/root/mods目录下的模块和包。
    
  14. 写函数

    有一个数据结构如下所示,请编写一个函数从该结构数据中返画由指定的 字段和对应的值组成的字典。如果指定字段不存在,则跳过该字段。
    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
    
  15. 编写函数,实现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
    
  16. 基于列表推导式一行实现输出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)]))
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一枚学渣.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值