北冥神功,取名于道家的庄子《逍遥游》。它的主旨要诀全在以下几点:
“世人练功,皆自云门而至少商,我逍遥派则反其道而行之,自少商而至云门,拇指与人相接,彼之内力即入我身,贮于云门等诸穴。然敌之内力若胜于我,则海水倒灌而入江河,凶险莫甚,慎之,慎之。
从北冥神功的修炼心法来看,它和普通内功修炼者的行走筋脉是完全相反的。因此北冥神功具有海纳百川的功能,才可以做到天下内功全都可以吸取。而且这种吸取是完全没有副作用,因为它还可以将别人的内力同化。
iterable 技巧
▍1、创建一个数字序列(从 0 到 10,间隔为 2)
>>> range(0,10,2)
[0, 2, 4, 6, 8]
▍2、对一串数字求和(从 0 到 10,间隔为 2)
>>> l = range(0,10,2)
>>> sum(l)
20
▍3、检查序列中的任一元素是否为 True
>>> any(a % 2 for a in range(0,10,2))
True
▍4、检查序列中的所有元素是否为 True
>>> all(a % 2 for a in range(0,10,2))
True
▍5、累计求和一串数字序列
>>> import numpy as np
>>> res = list(np.cumsum(range(0,10,2)))
>>> res
[ 0, 2, 6, 12, 20]
▍6、给定每个 iterable,通过添加索引来构造一个元组
>>> a = ['Hello', 'world', '!']
>>> list(enumerate(a))
[(0, 'Hello'), (1, 'world'), (2, '!')]
▍7、将 iterable 连接到单个字符串
>>> a = ["python","really", "rocks"]
>>> " ".join(a)
'python really rocks'
▍8、组合两个可迭代的元组或 pivot 嵌套的 iterables
# Combining two iterables
>>> a = [1, 2, 3]
>>> b = ['a', 'b', 'c']
>>> z = zip(a, b)
>>> z
[(1, 'a'), (2, 'b'), (3, 'c')]
# Pivoting list of tuples
>>> zip(*z)
[(1, 2, 3), ('a', 'b', 'c')]
▍9、从 iterables 中获取最小值 / 最大值(具有 / 不具有特定功能)
# Getting maximum from iterable
>>> a = [1, 2, -3]
>>> max(a)
2
# Getting maximum from iterable
>>> min(a)
1
# Bot min/max has key value to allow to get maximum by appliing function
>>> max(a,key=abs)
3
▍10、可迭代排序(可以通过 “compare” 函数排序)
>>> a = [1, 2, -3]
>>> sorted(a)
[-3, 1, 2]
>>> sorted(a,key=abs)
[1, 2, -3]
▍11、将单个字符串拆分为列表
>>> s = "a,b,c"
>>> s.split(",")
["a", "b", "c"]
▍12、初始化一个包含重复数字的列表
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
▍13、合并 / 插入两个字典
>>> a = {"a":1, "b":1}
>>> b = {"b":2, "c":1}
>>> a.update(b)
>>> a
{"a":1, "b":2, "c":1}
▍14、命名和保存 iterables 切片
# Naming slices (slice(start, end, step))
>>> a = [0, 1, 2, 3, 4, 5]
>>> LASTTHREE = slice(-3, None)
>>> LASTTHREE
slice(-3, None, None)
>>> a[LASTTHREE]
[3, 4, 5]
▍15、在列表中查找项的索引
>>> a = ["foo", "bar", "baz"]
>>> a.index("bar")
1
▍16、在 iterables 中查找最小 / 最大项的索引
>>> a = [2, 3, 1]
>>> min(enumerate(a),key=lambda x: x[1])[0]
2
▍17、旋转 iterables 的 k 个元素
>>> a = [1, 2, 3, 4]
>>> k = 2
>>> a[-2:] + a[:-2]
[3, 4, 1, 2]
▍18、删除字符串末尾 / 开始 / 两端无用的字符
>>> name = "//George//"
>>> name.strip("/")
'George'
>>> name.rstrip("/")
'//George'
>>> name.lstrip("/")
'George//'
▍19、倒序 iterables 的顺序(字符串、列表等)
# Reversing string
>>> s = "abc"
>>> s[::-1]
"cba"
# Reversing list
>>> l = ["a", "b", "c"]
>>> l[::-1]
["c", "b", "a"]
branching 技巧
▍20、多个 short-cut
>>> n = 10
>>> 1 < n < 20
True
▍21、For-else 结构在搜索某些东西并找到它时很有用
for i in mylist:
if i == theflag:
break
process(i)
else:
raise ValueError("List argument missing terminal flag.")
▍22、Trenary operator
>>> "Python ROCK" if True else " I AM GRUMPY"
"Python ROCK"
▍23、Try-catch-else 结构
try:
foo()
except Exception:
print("Exception occured")
else:
print("Exception didnt occur")
finally:
print("Always gets here")
▍24、While-else 结构
i = 5
while i > 1:
print("Whil-ing away!")
i -= 1
if i == 3:
break
else:
print("Finished up!")
comprehensions(推导式)技巧
▍25、List 推导式
>>> m = [x ** 2 for x in range(5)]
>>> m
[0, 1, 4, 9, 16]
▍26、Set 推导式
>>> m = {x ** 2 for x in range(5)}
>>> m
{0, 1, 4, 9, 16}
▍27、Dict 推导式
>>> m = {x: x ** 2 for x in range(5)}
>>> m
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
▍28、Generator 推导式
# A generator comprehension is the lazy version of a list comprehension.
>>> m = (x ** 2 for x in range(5))
>>> m
<generator object <genexpr> at 0x108efe408>
>>> list(m)
[0, 1, 4, 9, 16]
>>> m = (x ** 2 for x in range(5))
>>> next(m)
0
>>> list(m)
[1, 4, 9, 16]
▍29、list 推导使用当前值和过往值
>>> a = [1, 2, 4,2]
>>> [y - x for x,y in zip(a,a[1:])]
[1, 2, -2]
unpacking 技巧
▍30、从 iterable 解压缩变量
# One can unpack all iterables (tuples, list etc)
>>> a, b, c = 1, 2, 3
>>> a, b, c
(1, 2, 3)
>>> a, b, c = [1, 2, 3]
>>> a, b, c
(1, 2, 3)
▍31、交换变量值
>>> a, b = 1, 2
>>> a, b = b, a
>>> a, b
(2, 1)
▍32、在不指示所有元素的情况下从 iterable 解包变量
>>> a, *b, c = [1, 2, 3, 4, 5]
>>> a
1
>>> b
[2, 3, 4]
>>> c
5
▍33、使用 splat 运算符解包变量
>>> def test(x, y, z):
>>> print(x, y, z)
>>> res = test(*[10, 20, 30])
10 20 30
>>> res = test(**{'x': 1, 'y': 2, 'z': 3} )
10 20 30
view raw
Itertools 技巧
▍34、Flatten iterables
>>> a = [[1, 2], [3, 4], [5, 6]]
>>> list(itertools.chain.from_iterable(a))
[1, 2, 3, 4, 5, 6]
▍35、从 iterables 创建笛卡尔积
>>> for p in itertools.product([1, 2, 3], [4, 5]):
>>> print(''.join(str(x) for x in p))
(1, 4)
(1, 5)
(2, 4)
(2, 5)
(3, 4)
(3, 5)
▍36、从 iterable 创建排列
>>> for p in itertools.permutations([1, 2, 3, 4]):
>>> print(''.join(str(x) for x in p))
123
132
213
231
312
321
▍37、从 iterable 创建 ngram
>>> from itertools import islice
>>> def n_grams(a, n):
... z = (islice(a, i, None) for i in range(n))
... return zip(*z)
...
>>> a = [1, 2, 3, 4, 5, 6]
>>> n_grams(a, 3)
[(1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6)]
>>> n_grams(a, 2)
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
>>> n_grams(a, 4)
[(1, 2, 3, 4), (2, 3, 4, 5), (3, 4, 5, 6)]
▍38、使用填充组合元组的两个迭代器或使用填充 pivot 嵌套迭代
>>> import itertools as it
>>> x = [1, 2, 3, 4, 5]
>>> y = ['a', 'b', 'c']
>>> list(zip(x, y))
[(1, 'a'), (2, 'b'), (3, 'c')]
>>> list(it.zip_longest(x, y))
[(1, 'a'), (2, 'b'), (3, 'c'), (4, None), (5, None)]
▍39、从一个 iterable n 中创建 k 个组合
>>> import itertools
>>> bills = [20, 20, 20, 10, 10, 10, 10, 10, 5, 5, 1, 1, 1, 1, 1]
>>> list(itertools.combinations(bills, 3))
[(20, 20, 20), (20, 20, 10), (20, 20, 10), ... ]
▍40、在给定函数情况下创建一个迭代的累积结果
>>> import itertools
>>> list(itertools.accumulate([9, 21, 17, 5, 11, 12, 2, 6], min))
[9, 9, 9, 5, 5, 5, 2, 2]
▍41、创建一个迭代器,只要谓词为 True,就从 iterable 返回元素
>>> import itertools
>>> itertools.takewhile(lambda x: x < 3, [0, 1, 2, 3, 4])
[0, 1, 2]
>>> it.dropwhile(lambda x: x < 3, [0, 1, 2, 3, 4])
[3, 4]
▍42、创建一个迭代器,它从 iterable 中过滤元素,只返回谓词为 False 的元素
>>> import itertools
# keeping only false values
>>> list(itertools.filterfalse(bool, [None, False, 1, 0, 10]))
[None, False, 0]
▍43、创建一个迭代器,使用从迭代的迭代中获得的参数来计算函数
>>> import itertools
>>> import operator
>>> a = [(2, 6), (8, 4), (7, 3)]
>>> list(itertools.starmap(operator.mul, a))
[12, 32, 21]
collections 技巧
▍44、设置基本操作
>>> A = {1, 2, 3, 3}
>>> A
set([1, 2, 3])
>>> B = {3, 4, 5, 6, 7}
>>> B
set([3, 4, 5, 6, 7])
>>> A | B
set([1, 2, 3, 4, 5, 6, 7])
>>> A & B
set([3])
>>> A - B
set([1, 2])
>>> B - A
set([4, 5, 6, 7])
>>> A ^ B
set([1, 2, 4, 5, 6, 7])
>>> (A ^ B) == ((A - B) | (B - A))
True
▍45、计数器数据结构(无序集合,其中元素存储为字典键,其计数存储为字典值)
import collections
>>> A = collections.Counter([1, 1, 2, 2, 3, 3, 3, 3, 4, 5, 6, 7])
>>> A
Counter({3: 4, 1: 2, 2: 2, 4: 1, 5: 1, 6: 1, 7: 1})
>>> A.most_common(1)
[(3, 4)]
>>> A.most_common(3)
[(3, 4), (1, 2), (2, 2)]
▍46、默认字典结构(字典的子类,在访问不存在的键时检索默认值)
>>> import collections
>>> m = collections.defaultdict(int)
>>> m['a']
0
>>> m = collections.defaultdict(str)
>>> m['a']
''
>>> m['b'] += 'a'
>>> m['b']
'a'
>>> m = collections.defaultdict(lambda: '[default value]')
>>> m['a']
'[default value]'
>>> m['b']
'[default value]'
>>> m = collections.defaultdict(list)
>>> m['a']
[]
▍47、有序的 dict 结构(保持有序字典的子类)
>>> from collections import OrderedDict
>>> d = OrderedDict.fromkeys('abcde')
>>> d.move_to_end('b')
>>> ''.join(d.keys())
'acdeb'
>>> d.move_to_end('b', last=False)
>>> ''.join(d.keys())
'bacde'
▍48、Deques 结构(Deques 是堆栈和队列的概括)
>>> import collection
>>> Q = collections.deque()
>>> Q.append(1)
>>> Q.appendleft(2)
>>> Q.extend([3, 4])
>>> Q.extendleft([5, 6])
>>> Q
deque([6, 5, 2, 1, 3, 4])
>>> Q.pop()
4
>>> Q.popleft()
6
>>> Q
deque([5, 2, 1, 3])
>>> Q.rotate(3)
>>> Q
deque([2, 1, 3, 5])
>>> Q.rotate(-3)
>>> Q
deque([5, 2, 1, 3])
>>> last_three = collections.deque(maxlen=3)
>>> for i in range(4):
... last_three.append(i)
... print ', '.join(str(x) for x in last_three)
...
0
0, 1
0, 1, 2
1, 2, 3
2, 3, 4
▍49、命名元组结构(创建类元组的对象,这些对象的字段可通过属性查找访问,也可索引和迭代)
>>> import collections
>>> Point = collections.namedtuple('Point', ['x', 'y'])
>>> p = Point(x=1.0, y=2.0)
>>> p
Point(x=1.0, y=2.0)
>>> p.x
1.0
>>> p.y
2.0
▍50、使用字典来存储 Switch
>>> func_dict = {'sum': lambda x, y: x + y, 'subtract': lambda x, y: x - y}
>>> func_dict['sum'](9,3)
12
>>> func_dict['subtract'](9,3)
6
▍51、数据类结构
>>> from dataclasses import dataclass
>>> @dataclass
>>> class DataClassCard:
>>> rank: str
>>> suit: str
>>> queen_of_hearts = DataClassCard('Q', 'Hearts')
>>> queen_of_hearts.rank
'Q'
>>> queen_of_hearts
DataClassCard(rank='Q', suit='Hearts')
>>> queen_of_hearts == DataClassCard('Q', 'Hearts')
True
其他技巧
▍52、生成 uuid
# This creates a randomized
#128-bit number that will almost certainly be unique.
# In fact, there are over 2¹²² possible
#UUIDs that can be generated.
#That’s over five undecillion (or 5,000,000,000,000,000,000,000,000,000,000,000,000).
>>> import uuid
>>> user_id = uuid.uuid4()
>>> user_id
UUID('7c2faedd-805a-478e-bd6a-7b26210425c7')
▍53、使用 LRU 缓存进行记忆
import functools
@functools.lru_cache(maxsize=128)
def fibonacci(n):
if n == 0:
return 0
elif n == 1:
return 1
return fibonacci(n - 1) + fibonacci(n - 2)
▍54、Suppression of expressions
>>> from contextlib import suppress
>>> with contextlib.suppress(ZeroDivisionError):
>>> 10/0
# No exception raised
▍55、在需要设置和拆卸时创建上下文管理
class FileManager:
def __init__(self, filename):
self.filename = filename
self.file = None
def __enter__(self):
self.file = open(self.filename, 'r')
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close()
# 使用上下文管理器读取文件
with FileManager('example.txt') as file:
for line in file:
print(line)
▍56、一种处理文件路径的优雅方法(3.4≥)
>>> from pathlib import Path
>>> data_folder = Path("source_data/text_files/)
# Path calculation and metadata
>>> file_to_open = data_folder / "raw_data.txt"
>>> file_to_open.name
"raw_data.txt"
>>> file_to_open.suffix
"txt"
>>>file_to_open.stem
"raw_data"
# Files functions
>>> f = open(file_to_open)
>>> f.read()
# content of the file
>>> file_to_open.exists()
True
▍57、将标准操作符实现为类的函数
@staticmethod
def add(x, y):
return x + y
@staticmethod
def subtract(x, y):
return x - y
@staticmethod
def multiply(x, y):
return x * y
@staticmethod
def divide(x, y):
return x / y
▍58、创建装饰器来分离 concerns
>>>from functools import wraps
>>>def add_sandwich(wrapped):
>>> @wraps(wrapped)
>>> def wrapper(*args, **kwargs):
>>> return wrapped(*args, **kwargs) + ' sandwich'
>>> return wrapper
>>>@add_sandwich
>>>def ham():
>>> return 'ham'
>>>ham()
'ham sandwich'
▍59、使用 yield 创建一个简单的迭代器
>>> def foo(lst):
>>> for x in lst:
>>> yield x
>>> yield x*2
>>> a = [1, 3]
>>> list(foo(a))
[1, 2, 3, 6]
▍60、yield from use cases and tricks
def numbers():
yield from range(1, 4)
def letters():
yield from ('A', 'B', 'C')
def combine():
yield from numbers()
yield from letters()
for value in combine():
print(value)
# 输出结果:1 2 3 A B C
彩蛋
▍61、Anti-gravity
import antigravity
antigravity.fly()
▍62、The Zen of Python
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren not special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one and preferably only one obvious way to do it.
Although that way may not be obvious at first unless you are Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it is a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea let us do more of those!