Python的30个语言特性技巧(待提取整理)

分拆

a, b, c = 1, 2, 3
print(a,b,c) # 1 2 3
a, b, c = [1, 2, 3]
print(a,b,c) # 1 2 3
a, b, c = (2 * i + 1 for i in range(3)) # range不能超出value的范围,超出too many values to unpack (expected 3)
print(a,b,c) # 1 3 5

a, (b, c), d = [1, (2, 3), 4]
print(a,b,c) # 1 2 3
print('-'*10,"分割线","-"*10)

交换变量分拆

a, b = 1, 2
a, b = b, a
print(a,b) # 2 1
print('-'*10,"分割线","-"*10)

拓展分拆 (Python 3下适用)

a, *b, c = [1, 2, 3, 4, 5] # *匹配多个值
print(a,b,c) #1 [2, 3, 4] 5
print('-'*10,"分割线","-"*10)

负索引

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(a[-1]) # 10
print('-'*10,"分割线","-"*10)

列表切片 (a[start:end])

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(a[2:8]) #[2, 3, 4, 5, 6, 7]
print('-'*10,"分割线","-"*10)

使用负索引的列表切片

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(a[-4:-2]) # [7,8]
print('-'*10,"分割线","-"*10) 

带步进值的列表切片 (a[start🔚step])

print(a[::2]) # [0, 2, 4, 6, 8, 10]
print(a[::3]) # [0, 3, 6, 9]
print(a[2:8:2]) # [2, 4, 6]
print('-'*10,"分割线","-"*10)

负步进值得列表切片

print(a[::-1]) # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
print(a[::-2]) # [10, 8, 6, 4, 2, 0]
print('-'*10,"分割线","-"*10)

列表切片赋值

a = [1, 2, 3, 4, 5]
a[2:3] = [0, 0]
print(a) # [1, 2, 0, 0, 4, 5]
a[1:1] = [8, 9]
print(a) # [1, 8, 9, 2, 0, 0, 4, 5]
a[1:-1] = []
print(a) # [1, 5]
print('-'*10,"分割线","-"*10)

命名切片 (slice(start, end, step))

a = [0, 1, 2, 3, 4, 5]
LASTTHREE = slice(-3, None)
print(LASTTHREE) # slice(-3, None, None)
print(a[LASTTHREE]) # [3, 4, 5]
print('-'*10,"分割线","-"*10)

zip打包解包列表和倍数(好奇)

a = [1, 2, 3]
b = ['a', 'b', 'c']
z = zip(a, b) # 
# <class 'zip'>类型是什么,打印z返回个内存地址,类似迭代器
print(type(z))
print(type(zip(*z)))
'''
问题:
zip(a,b)返回了什么对象,不知,但不能迭代,
打印返回内存地址,不能用该赋值的对象用list直接转化为列表
'''

zip(a,b)是从a,b种各自取出一个元素组成元组,再将依次组成的元组合成一个新的迭代器

print(list(zip(a,b))) # zip直接作用在参数上可以用list转化为列表 [(1, 'a'), (2, 'b'), (3, 'c')]
print(list(z)) # []
print(list(zip(*zip(a,b)))) #[(1, 2, 3), ('a', 'b', 'c')]
print('-'*10,"分割线","-"*10)

使用zip合并相邻的列表项

a = [1, 2, 3, 4, 5, 6]
b = zip(*([iter(a)] * 2))
# 打印不出[(1, 2), (3, 4), (5, 6)]
print(b) # <zip object at 0x000002387349DB48> ;zip属性还不能用下标,用了报错'zip' object is not subscriptable

zip属性迭代也打印不出

print(i for i in b) # <generator object <genexpr> at 0x0000016DAE8C7A40>
print('-'*10,"分割线","-"*10)
group_adjacent = lambda a, k: zip(*([iter(a)] * k))
print(group_adjacent(a, 3)) # <zip object at 0x000002251FBBDF48>
print(list(group_adjacent(a,3))) # [(1, 2, 3), (4, 5, 6)]
print('-'*10,"分割线","-"*10)

使用zip和iterators生成滑动窗口 (n -grams) 不理解

from itertools import islice
def n_grams(a, n):
    z = (islice(a, i, None) for i in range(n))
    return list(zip(*z))
a = [1, 2, 3, 4, 5, 6]
print(n_grams(a, 3))
print('-'*10,"分割线","-"*10)

使用zip反转字典

m = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
print(m.items()) # dict_items([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
# [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]
print( list(zip(m.values(), m.keys()))) # 由于zip返回的是内存地址,所以用list转化为列表,但list无法转化zip对象,转化的话返回空列表
mi = dict(zip(m.values(), m.keys()))
print(mi) # {1: 'a', 2: 'b', 3: 'c', 4: 'd'}
print('-'*10,"分割线","-"*10)

摊平列表

import itertools
a = [[1, 2], [3, 4], [5, 6]]
# 使用itertools.chain.from_iterable使二维变一维
print(list(itertools.chain.from_iterable(a))) # [1, 2, 3, 4, 5, 6]
# sum使二维变一维
b = sum(a, [])
print(b) # [1, 2, 3, 4, 5, 6]
# []内加双for
c= [x for l in a for x in l]
print(c) # [1, 2, 3, 4, 5, 6]
a = [1, 2, [3, 4], [[5, 6], [7, 8]]]
# 自定义函数这么长;我什么时候才有这么本事啊
flatten = lambda x: [y for l in x for y in flatten(l)] if type(x) is list else [x]
print(flatten(a)) # [1, 2, 3, 4, 5, 6, 7, 8]
print('-'*10,"分割线","-"*10)

生成器表达式

g = (x ** 2 for x in range(10))
print(next(g)) # 0
print(next(g)) # 1
d = sum(x ** 3 for x in range(10))
print(d) # 2025
e = sum(x ** 3 for x in range(10) if x % 3 == 1) # 3的倍数
print(e) # 408
print('-'*10,"分割线","-"*10)

迭代字典

m = {x: x ** 2 for x in range(5)}
print(m) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
m = {x: 'A' + str(x) for x in range(10)} # {0: 'A0', 1: 'A1', 2: 'A2', 3: 'A3', 4: 'A4', 5: 'A5', 6: 'A6', 7: 'A7', 8: 'A8', 9: 'A9'}
print(m)
print('-'*10,"分割线","-"*10)

通过迭代字典反转字典

m = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
print(m) # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
m1 = {v: k for k, v in m.items()} 
print(m1) # {1: 'a', 2: 'b', 3: 'c', 4: 'd'}
print('-'*10,"分割线","-"*10)

命名序列 (collections.namedtuple)

import collections
Point = collections.namedtuple('Point', ['x', 'y'])
p = Point(x=1.0, y=2.0)
print(p) # Point(x=1.0, y=2.0)
print(p.x) # 1.0
print(p.y) # 2.0
print('-'*10,"分割线","-"*10)

命名列表的继承:

class Point(collections.namedtuple('PointBase', ['x', 'y'])):
    __slots__ = ()
    def __add__(self, other):
        return Point(x=self.x + other.x, y=self.y + other.y)

p = Point(x=1.0, y=2.0)
q = Point(x=2.0, y=3.0)
print(p+q) # Point(x=3.0, y=5.0)
print('-'*10,"分割线","-"*10)

集合及集合操作

A = {1, 2, 3, 3}
B = {3, 4, 5, 6, 7}
print(A|B) # {1, 2, 3, 4, 5, 6, 7}
print(A & B) # {3}
print(A - B) # {1, 2}去除A中B所拥有的元素
print(B - A) # {4, 5, 6, 7}去除B中A所拥有的元素
# print(A + B) # 没有A+B
print(A ^ B) # {1, 2, 4, 5, 6, 7}
# ^的作用是前面的集合去掉后面的集合剩下的部分或者成并集
print(set([1,2,3])^set([1])) # {2, 3}
print(set([1])^set([1,2,3])) # {2, 3}
print((A ^ B) == ((A - B) | (B - A))) # True
print('-'*10,"分割线","-"*10)

多重集及其操作 (collections.Counter

A = collections.Counter([1, 2, 2])
B = collections.Counter([2, 2, 3])
print(A) # Counter({2: 2, 1: 1})
print(B) # Counter({2: 2, 3: 1})
print(A-B) # Counter({1: 1})
print(B-A) # Counter({3: 1})
print(A+B) # Counter({2: 4, 1: 1, 3: 1})
print(A&B) # Counter({2: 2})
print(A | B) # Counter({2: 2, 1: 1, 3: 1})
print('-'*10,"分割线","-"*10)

迭代中最常见的元素 (collections.Counter)

A = collections.Counter([1, 1, 2, 2, 3, 3, 3, 3, 4, 5, 6, 7])
print(A) # Counter({3: 4, 1: 2, 2: 2, 4: 1, 5: 1, 6: 1, 7: 1})
print(A.most_common(1)) # [(3, 4)]
print(A.most_common(3)) # [(3, 4), (1, 2), (2, 2)]
print('-'*10,"分割线","-"*10)

双端队列 (collections.deque) rotate的用法顺时针或逆时针旋转

Q = collections.deque()
Q.append(1)
Q.appendleft(2)
Q.extend([3, 4])
Q.extendleft([5, 6])
print(Q) # deque([6, 5, 2, 1, 3, 4])
print(Q.pop()) # 4
print(Q.popleft()) # 6
print(Q) # deque([5, 2, 1, 3])
Q.rotate(3)  # 整个队列顺时针旋转3个单位
print(Q) #deque([2, 1, 3, 5])
Q.rotate(-3)
print(Q) # deque([5, 2, 1, 3])
print('-'*10,"分割线","-"*10)

有最大长度的双端队列 (collections.deque)

last_three = collections.deque(maxlen=3)
for i in range(10):
    last_three.append(i)
    # 这打印出每组3个元素有什么用么,每组3个,都是循环队列中最大的值
    print (','.join(str(x) for x in last_three))
print('-'*10,"分割线","-"*10)

缺省字典(collections.defaultdict)

m = dict()
# m['a'] # KeyError: 'a'
m = collections.defaultdict(int)
print(m['a']) # 0
m = collections.defaultdict(str)
print(m['a']) # 空白换行
m['b'] += 'a'
print(m['b']) # a
m = collections.defaultdict(lambda: '[default value]')
print(m['a']) # [default value]
print('-'*10,"分割线","-"*10)

用缺省字典表示简单的树

import json
tree = lambda: collections.defaultdict(tree)
root = tree()
root['menu']['id'] = 'file'
root['menu']['value'] = 'File'
root['menu']['menuitems']['new']['value'] = 'New'
root['menu']['menuitems']['new']['onclick'] = 'new();'
root['menu']['menuitems']['open']['value'] = 'Open'
root['menu']['menuitems']['open']['onclick'] = 'open();'
root['menu']['menuitems']['close']['value'] = 'Close'
root['menu']['menuitems']['close']['onclick'] = 'close();'
# print(json.dumps(root, sort_keys=True, indent=4, separators=(',', ': '))) 
print('-'*10,"分割线","-"*10)

映射对象到唯一的序列数 (collections.defaultdict)

import itertools, collections
value_to_numeric_map = collections.defaultdict(itertools.count().__next__) # 这里使用__next__;不使用next
print(value_to_numeric_map['a']) # 0
print(value_to_numeric_map['b']) # 1
print(value_to_numeric_map['a']) # 0
print('-'*10,"分割线","-"*10)

最大最小元素 (heapq.nlargest和heapq.nsmallest)

import random,heapq
a = [random.randint(0, 100) for __ in range(100)]
print(heapq.nsmallest(5, a)) # [0, 0, 0, 1, 1] 最小的5个元素
print(heapq.nlargest(5, a)) # [100, 98, 97, 96, 92]
print('-'*10,"分割线","-"*10)

笛卡尔乘积 (itertools.product)

for p in itertools.product([1, 2, 3], [4, 5]):
    print(p)
# for p in itertools.product([0, 1], repeat=4):
###    print (''.join(str(x) for x in p))
print('-'*10,"分割线","-"*10)

组合的组合和置换

(itertools.combinations 和 itertools.combinations_with_replacement)

# for c in itertools.combinations([1, 2, 3, 4, 5], 3):
###    print (''.join(str(x) for x in c))
print('-'*10,"分割线","-"*10)

排序(itertools.permutations)

# for p in itertools.permutations([1, 2, 3, 4]):
###    print (''.join(str(x) for x in p))

链接的迭代 (itertools.chain)

a = [1, 2, 3, 4]
# for p in itertools.chain(itertools.combinations(a, 2), itertools.combinations(a, 3)):
###    print(p)
print('-'*10,"分割线","-"*10)

按给定值分组行 (itertools.groupby)

# from operator import itemgetter
# import itertools
# with open('contactlenses.csv', 'r') as infile: # 我并没有准备这个文件
###    data = [line.strip().split(',') for line in infile]
# data = data[1:]
# def print_data(rows):
###    print ('\n'.join('\t'.join('{: <16}'.format(s) for s in row) for row in rows))
# print_data(data)
print('-'*10,"分割线","-"*10)
posted @ 2021-09-11 21:13  索匣  阅读(47)  评论(1编辑  收藏  举报