欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第三周笔记

程序员文章站 2022-07-15 11:22:27
...

封装和解构

  • 封装

    • 将多个值使用逗号分割,组合在一起
    • 本质上,返回一个元组,只是省略掉了小括号
    • python特有语法,被很多语言借鉴
  • 交换

    • a = 4
      b = 5
      temp = a 
      a = b
      b = temp
      等价于
      a, b = b, a  # 右边封装,左边解构
      
  • 解构

    • 把线性结构的元素解开,并顺序的付给其他变量
    • 左边接纳的变量数要和右边解开的元素个数一致

Python3的解构

  • 使用*变量名接收,但不能单独使用

  • 被*变量名收集后组成一个列表

  • 举例

    • lst = list(range(1, 21, 2))
      head, *mid, tail = lst
      *lst2 = lst
      *body, tail = lst
      head, *tail = lst
      head, *m1, *m2, tail = lst
      head, *mid, tail = "abcdefghijk"
      type(mid)
      --->
      
  • 丢弃变量

    • 这是一个惯例,是不成文的约定,不是标准

    • 如果不关心一个变量,就可以定义该变量的名字为_

    • _是一个合法的标识符,也可以作为一个有效的变量使用,但是定义成下划线就是希望不要被使用,除非你明确知道整个数据需要使用

    • lst = [9, 8, 7, 20]
      first, *second = lst
      head, *_, tail = lst
      print(head)
      print(tail)
      --->9
      	20
      
    • 总结:

      • _这个变量本身无任何语义,没有任何可读性,所以不是用来给人使用的
      • Python中很多库,都是用这个变量,使用十分广泛。请不要在不明确变量作用域的情况下使用,导致和库中的_冲突
  • 总结:

    • 解构,是Python中提供的很好的功能,可以方便提取复杂数据结构的值
    • 配合_的使用,会更加的便利

set及操作

集set

  • 约定
    • set翻译为集合
    • collection翻译为集合类型或容器,是一个大概念
  • set
    • 可变的,无序的,不重复的元素的集合
  • set定义 初始化
    • set()
    • set(iterable)
  • set的元素
    • set的元素要求必须可以hash
    • 目前学过的不可hash的类型有list、set、bytearray
    • 元素不可以索引
    • set可以迭代
  • set增加
    • add(elem)
      • 增加一个元素到set中
      • 如果元素存在,什么都不做
    • update(*others)
      • 合并其他元素到set集合中
      • 参数others必须是可迭代对象
      • 就地修改
  • set删除
    • remove(elem)
      • 从set中移除一个元素
      • 元素不存在,抛出KeyError异常
    • discard(elem)
      • 从set中移除一个元素
      • 元素不存在,什么都不做
    • pop()->item
      • 移除并返回任意的元素
      • 空集返回KeyError异常
    • clear()
      • 移除所有元素
  • set修改、查询
    • 要么删除,要么加入新的元素,不可修改
    • 非线性结构,无法索引
    • 可以迭代所有元素
  • set和线性结构
    • 线性结构的查询时间复杂度是O(n),即随数据规模的增大而耗时增加
    • set、dict等结构,内部使用hash值作为key,时间复杂度可以做到O(1),查询时间和数据规模无关
    • 可hash
      • 数值型 int、float、complex
      • 布尔型 True、False
      • 字符串 string、bytes
      • tuple
      • None
      • 以上都是不可变类型,称为可哈希类型,hashable
    • set的元素必须是可hash的
  • 集合
    • 全集
    • 子集subset和超集superset
    • 真子集和真超集
  • 集合运算
    • 并集
      • 将两个集合A和B的所有元素合并到一起,组成的集合称作A与B的并集
      • | 运算符重载(等同union)
      • |= 将多个集合合并,就地修改(等同update)
    • 交集
      • 集合A和B,由所有属于A且属于B的元素组成的集合
      • intersection(*others)
        • 返回和多个集合的交集
      • &
        • 等同intersection
      • intersection_update(*others)
        • 获取和多个集合的交集,并就地修改
      • &=
        • 等同intersecton_update
    • 差集
      • 集合A和B,由所有属于A切不属于B的元素组成的集合
      • difference(*others)
        • 返回和多个集合的差集
        • 等同difference
      • difference_update(*others)
        • 获取和多个集合的差集并就地修改
      • -=
        • 等同difference_update
    • 对称差集
      • 集合A和B,由所有不属于A和B的交集元素组成的集合,记作(A-B)∪(B-A)
      • symmetric_difference(other)
        • 返回和另一个集合的对称差集
      • ^
        • 等同symmetric_difference
      • symmetric_difference_update(other)
        • 获取和另一个几个的对称差集并就地修改
      • ^=
        • 等同symmetric_difference_update
    • issubset(other)、<=
      • 判断当前集合是否是另一个集合的子集
    • set1 < set2
      • 判断set1是否是set2的真子集
    • issuperset(other)、>=
      • 判断当前集合是否是other的超集
    • set1 > set2
      • 判断set1是否是set2的真超集
    • isdisjoint(other)
      • 当前集合和另一个几个没有交集
      • 没有交集,返回True
  • 幂等性
    • 输入的参数不变,输出的值也对应相等
  • hash冲突
    • 两个不同的值,经过hash,hash值一样(可能性极小)

字典dict

  • key-value键值对的数据的集合
  • 可变的、无序的、key不重复

字典dict定义 初始化

  • d = dict()或者d = {}
  • dict(**kwargs)使用name=value对初始化一个字典
  • dict(iterable, **kwarg)使用可迭代对象和name=value对构造字典,不过可迭代对象的元素必须是一个二元结构
    • d=dict(((1,‘a’), (2,‘b’)))或者d=dict(([1,‘a’],[2,‘b’]), c=300)
  • dict(mapping, **kwarg)使用一个字典构建另一个字典
  • d={‘a’:10, ‘b’:20,‘c’:None,‘d’:[1,2,3]}
  • 类方法dict.fromkeys(iterabe, value)
    • d=dict.fromkeys(range(5))
    • d=dict.fromkeys(range(5), 0)

字典元素的访问

  • d[key]
    • 返回key对应的值value
    • key不存在抛出KeyError异常
  • get(key[,default])
    • 返回key对应的值value
    • key不存在返回缺省值,如果没有设置缺省值就返回None
  • setdefault(key[,default])
    • 返回key对应的值value
    • key不存在,添加kv对,value设置为default,并返回default,如果default没有设置,缺省为None

字典增加和修改

  • d[key] = value
    • 将key对应的值修改为value
    • key不存在添加新的kv对
  • update([other]) -> None
    • 使用另一个字典的kv对更新本字典
    • key不存在,就添加
    • key存在,覆盖已经存在的key对应的值
    • 就地修改

字典删除

  • pop(key[,default])
    • key存在,移除它,斌返回它的value
    • key不存在,返回给定的default
    • default未设置,key不存在则抛出KeyError异常
  • popitem()
    • 移除并返回一个任意的键值对
    • 字典为empty,抛出KeyError异常
  • clear()
    • 清空字典
  • del语句

字典遍历

  • 遍历key

    for ... in dict
        # 遍历key
        for k in d:
            print(K)
    
        for k in d.keys():
            print(k)
    
  • 遍历value

  • for ... in dict
    	# 遍历value
    	for k in d:
    		print(d[k])
    	
    	for k in d.keys():
    		print(d.get(k))
    		
    	for v in d.values():
    		print(v)
    
  • 遍历item

  • for ... in dict:
    	for item in d.items():
    		print(item)
    	for item in d.items():
    		print(item[0], item[1])
    	for k,v in d.items():
    		print(k, v)
    	for k,_ in d.items():
    		print(k)
    	for _,v in d.items():
    		print(v)
    
  • 总结:

    • Python3中,keys、values、items方法返回一个类似一个生成器的可迭代对象,不会把函数的返回结果复制到内存中
      • Dictionary view对象,可以使用len(),lter(),in操作
      • 字典的entry的动态的视图,字典变化,视图将反映出这些变化
      • keys返回一个类set对象,也就是可以看做一个set集合。如果values都可以hash,那么items也可以看做是类set对象
    • Python2中,上面的方法会返回一个新的列表,占据新的内存空间。所以Python2建议使用iterkeys,itervalues,iteritems版本,为不是返回一个copy
  • 如何在遍历的时候移除元素

    • d = dict(a=1, b=2, c='abc')
      keys = []
      for k,v in d.items():
      	if isinstance(v,str):
      		keys.append(k)
      		
      for k in keys:
      	d.pop(k)
      print(d)
      

字典的key

  • key的要求和set的元素要求一致

    • set的元素可以就是看作key,set可以看作dict的简化版
    • hashable可哈希才可以作为key,可以使用hahs()测试
    • d={1:0,2.0:3,“abc”:None, (‘hello’, ‘world’, ‘pyrhon’):‘string’,b’abc’:‘153’
  • defaultdict

    • collections.default([default_factory[, …]])

      • 第一个参数是default_factory,缺省是None,它提供一个初始化函数。当key不存在的时候,会调用这个工厂函数来生成key对应的value

      • import random
        
        d1 = {}
        for k in "abcdef":
        	for i in range(random.randint(1, 5)):
        		if k not in d1.keys():
        			d1[k] = []
        		d1[k].append(i)
        print(d1)
        --->{'a': [0, 1, 2], 'b': [0, 1], 'c': [0, 1, 2, 3, 4], 'd': [0, 1, 2, 3], 'e': [0, 1, 2, 3], 'f': [0]}
        
      • from collections import defaultdict
        import random
        
        d1 = defaultdict(list)
        for k in 'abcedf':
        	for i in range(random.randint(1, 5)):
        		d1[k].append(i)
        print(d1)
        --->defaultdict(<class 'list'>, {'a': [0, 1], 'b': [0, 1], 'c': [0, 1, 2], 'e': [0, 1], 'd': [0], 'f': [0]})
        
  • OrderedDict

    • collections.OrdedDict([items])

      • key并不是按照加入的顺序排列,可以使用OrderedDict记录顺序

      • from collections import OrderedDict
        import random
        d = {'banbana':3, 'apple':4, 'pear':2}
        print(d)
        keys = list(d.keys())
        random.shuffle(keys)
        print(keys)
        od = OrderedDict()
        for key in keys:
        	od[key] = d[key]
        print(od)
        print(od.keys)
        --->{'banbana': 3, 'apple': 4, 'pear': 2}
            ['banbana', 'pear', 'apple']
            OrderedDict([('banbana', 3), ('pear', 2), ('apple', 4)])
            <built-in method keys of collections.OrderedDict object at              0x000001BDE6531E18>
        
    • 有序字典可以记录元素插入的顺序,打印的时候也是按照你这个顺序输出打印

    • 3.6版本的python的字典就是记录key插入的顺序(ipython不一定有效果)

    • 应用场景

      • 假如使用字典记录了N个产品,这些产品使用ID由小到大加入到字典中
      • 除了使用字典检索的遍历,有时候需要取出ID,但是希望是按照输入的顺序,因为输入顺序是有序的
      • 否则还需要重新把遍历到的值排序

Python解析式、生成器

标准库datetime

  • datetime模块

    • 对日期、时间、时间戳的处理

    • datetime类

      • 类方法

        • today()返回本地区当前时间的datetime对象
        • now(tz=None)返回当前时间的datetime对象,时间到微秒,如果tz为None,返回和today()一样
        • utcnow()没有时区的当前时间
        • fromtimestamp(timestamp, tz=None)从一个时间戳返回一个datetime对象
      • datetime对象

        • timestamp()返回一个到微妙的时间戳

          • 时间戳:格林威治时间1970年1月1日0点到现在的秒数
          • 构造方法 datetime.datetime(2016, 12, 6, 16, 29, 43, 79043)
          • year,month,day,hour,minute,second,microsecond,取datetime对象的年月日时分秒及微秒
          • weekday()返回星期的天,周一0,周日6
          • isoweekday()返回星期的天,周一1,周日7
          • date()返回日期date对象
          • time()返回时间time对象
          • replace()修改并返回新的时间
          • isocalendar()返回一个三元组(年,周数,周的天)
        • 日期格式化

          • 类方法 strptime(date_string, format), 返回datetime对象

          • 对象方法strtfime(format),返回字符串

          • 字符串format函数格式化

          • import datetime
            dt = datetime.datetime.strptime("21/11/06 16:30", "%d%m%y %H:%M")
            print(dt.strftime(""%Y-%m-%d %H:%M:%S"))
            print("{0:%Y}/{0:%m}/{0:%d} {0:%H}::{0:%M}::{0:%S}".format(dt))
            
      • timedelta对象

        • 构造方法
          • datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
          • year = datetime.timedelta(days=365)
        • total_seconds()返回时间差的总秒数

time模块

  • time.sleep(secs)将调用线程挂起指定的秒数

列表解析式

  • 生成一个列表,元素0~9,对每一个元素自增1后求平方返回新列表

    • l1 = list(range(10))
      l2 = []
      for i in l1:
      	l2.append((i + 1) ** 2)
      print(l2)
      --->[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
      
    • # 列表解析式
      l1 = list(range(10))
      l2 = [(i + 1) ** 2 for i in l1]
      print(l2)
      print(type(l2))
      --->[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
      <class 'list'>
      
  • 语法

    • [返回值 for 元素 in 可迭代对象 if 条件]
    • 使用中括号[], 内部是for循环, if条件语句可选
    • 返回一个新的列表
  • 列表解析式是一种语法糖

    • 编译器会优化,不会因为简写而影响效率,反而因优化提高了效率
    • 减少程序员工作量,减少出错
    • 简化了代码,但可读性增强

生成器表达式

  • 语法

    • (返回值for元素in可迭代对象if条件)
    • 列表解析式的中括号换成小括号就行了
    • 返回一个生成器
  • 和列表解析式的区别

    • 生成器表达式时按需计算(或称惰性求值,延迟计算),需要的时候才计算值
    • 列表解析式时立即返回值
  • 生成器

    • 可迭代对象
    • 迭代器
  • 举例

    • g = ("{:04}".format(i) for i in range(1, 11))
      next(g)
      for x in g:
      	print(x)
      print('--------------------------')
      for x in g:
      	print(x)
      --->0002
      0003
      0004
      0005
      0006
      0007
      0008
      0009
      0010
      --------------------------
      
    • 总结

      • 延迟计算

        -返回迭代器,可以迭代

      • 从前到后走完一遍,不能回头

  • 和列表解析式的对比

    • 计算方式
      • 生成器表达式延迟计算,列表解析式立即计算
    • 内存占用
      • 单从返回值本身来说,生成器表达式省内存,列表解析式返回新的列表
      • 生成器没有数据,内存占用极少,到那时使用的时候,虽然一个个返回数据,但是合起来占用的内存也差不多
      • 列表解析式构造新的列表需要占用内训
    • 计算速度
      • 单看计算时间,生成器表达式耗时非常短,列表解析式耗时长
      • 但是生成器本身并没有任何返回值,只返回了一个生成器对象
      • 列表解析式构造并返回了一个新的列表

集合解析式

  • 语法

    • {返回值 for 元素 in 可迭代对象 if 条件}
    • 列表解析式的中括号换成大括号就行了
    • 立即返回一个集合
  • 用法

    • {(x, x+1) for x in range(10)}
      --->{(0, 1),
       (1, 2),
       (2, 3),
       (3, 4),
       (4, 5),
       (5, 6),
       (6, 7),
       (7, 8),
       (8, 9),
       (9, 10)}
      

字典解析式

  • 语法

    • {返回值 for 元素 in 可迭代对象 if 条件}

    • 列表解析式的中括号换成大括号就行了

    • 使用key:value形式

    • 立即返回一个字典

    • {x:(x, x+1) for x in range(10)}
      --->{0: (0, 1),
       1: (1, 2),
       2: (2, 3),
       3: (3, 4),
       4: (4, 5),
       5: (5, 6),
       6: (6, 7),
       7: (7, 8),
       8: (8, 9),
       9: (9, 10)}
      
  • 总结

    • 一般来说,应该多应用解析式,简短高效
    • 如果一个解析式非常复杂,难以读懂,要考虑拆成for循环
    • 生成器和迭代器时不同的对象,但都是可迭代对象

Python内建函数

  • 标识 id

    • 返回对象的唯一标识,CPython返回内存地址
  • 哈希 hash

    • 返回一个对象的哈希值
  • 类型 type()

    • 返回对象的类型
  • 类型转换

    • float(), int(), bin(), henx(), oct(), bool(), list(), tuple(), dict(), set(), complex(), bytes(), bytearray()
  • 输入 input

    • 接收用户输入,返回一个字符串
  • 打印 print

    • 打印输出,默认使用空格分隔,换行结尾,输出到控制台
  • 对象长度 len()

    • 返回一个集合类型的元素个数
  • isinstance(obj, class_or_tuple)

    • 判断对象obj是否是属于某种类型或元组中列出的某个子类

    • isinstance(True, int)

    • isinstance('234', (int, tuple))  # 布尔型是整型的子类
      --->False
      
  • issubclass(cls, class_or_tuple)

    • 判断类型cls是否是某种类型的子类或元组中列出的某个类型的子类
    • issubclass(bool, int)
  • 绝对值abs(x) x为数值

  • 最大值max() 最小值min()

  • round(x) 四舍六入五取偶

  • **pow(x, y) **

  • range(stop) 从0开始到stop-1的可迭代对象

  • divmod(x, y) 等价于tuple(x // y, x % y)

  • sum(iterable[,start]) 对可迭代对象的所有数值元素求和

  • chr(i) 给一个一定范围的这个念书返回对应的字符

  • ord© 返回字符对应的整数

    • ord('a) ord(‘中’)
  • str(), repr(), ascii() 后面说

  • sorted(iterable[, key][, reverse])排序

    • 返回一个新的列表,默认升序

    • reverse是反转

    • sorted([1, 3, 5])
      --->[1, 3, 5]
      
      sorted([1, 3, 5], reverse=True)
      --->[5, 3, 1]
      
      sorted({'c':1, 'b':2, 'a':1})
      --->['a', 'b', 'c']
      
  • 翻转 reversed(seq)

    • 返回一个翻转元素的迭代器

    • list(reversed(“13579”))

    • { reversed((2, 4))}
      --->{<reversed at 0x155cb206ba8>}
      
    • for x in reversed(['c', 'b', 'a']):
      	print(x)
      reversed(sorted({1, 5, 9}))
      --->a
      b
      c
      <list_reverseiterator at 0x155cb0ece10>
      
  • 枚举

    • 迭代一个序列,返回索引数字和元素构成的二元组

    • start表示索引开始的数字,默认是0

    • for x in enumerate([2, 4, 6, 8]):
      	print(x)
      --->(0, 2)
      (1, 4)
      (2, 6)
      (3, 8)
      
  • *拉链函数 zip(iterables)

    • 像拉链一样,把多个可迭代对象合并在一起,返回一个迭代器

    • 将每次从不同对象中取到的元素合并成一个元组

    • list(zip(range(10), range(10)))
      --->[(0, 0),
       (1, 1),
       (2, 2),
       (3, 3),
       (4, 4),
       (5, 5),
       (6, 6),
       (7, 7),
       (8, 8),
       (9, 9)]
      
    • list(zip(range(10), range(10), range(5), range(10)))
      --->[(0, 0, 0, 0), (1, 1, 1, 1), (2, 2, 2, 2), (3, 3, 3, 3), (4, 4, 4, 4)]
      
  • 迭代器和取元素 iter(iterable), next(iterator[, default])

    • iter将一个可迭代对象封装成一个迭代器

    • next对一个迭代器取下一个元素。如果元素全部都取过了,再次next会抛StopIleration异常

    • it = iter(range(5))
      next(it)
      --->0
      
      it = reversed([1, 3, 5])
      next(it)
      --->5
      
  • 可迭代对象

    • 能够通过迭代一次次返回不同的元素的对象
      • 所谓相同,不是指值是否相同,而是元素在容器中是否是同一个,例如列表中值可以重复的,[‘a’, ‘a’],虽然这个列表有两个元素,值一样,但是两个‘a’是不同的元素
    • 可以迭代,但是未必有序,未必可索引
    • 可迭代对象有:list, tuple, string, bytes, bytearray, range, set, dict, 生成器等
    • 可以使用成员操作符in,not in, in本质上对线性数据结构就是在遍历对象

迭代器

  • 迭代器

    • 特殊的对象,一定是可迭代对象,具备可迭代对象的特征

    • 通过iter方法把一个可迭代对象封装成迭代器

    • 通过next方法,迭代 迭代器

    • 生成器对象,就是迭代器对象

    • for x in iter(range(10)):
      	print(x)
      --->0
      1
      2
      3
      4
      5
      6
      7
      8
      9