我是靠谱客的博主 难过啤酒,这篇文章主要介绍Pythonic---------详细讲解,现在分享给大家,希望可以做个参考。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
作者:半载流殇 链接:https://zhuanlan.zhihu.com/p/35219750 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 Pythonic,简言之就是以Python这门语言独特的方式写出既简洁又优美的代码!笔者精心整理了许多实用的Python tricks,想要提高效率、写出高质量的Python代码的话此文必看。 注:请将Python更新到3.6版,方能完美运行本文的所有代码。字符串格式化字符串在字符串前加f,就可以在里面用大括号嵌入变量了(可以代替format函数)>>> a = 5 >>> b = 10 >>> f'Five plus ten is {a + b} and not {2 * (a + b)}.' 'Five plus ten is 15 and not 30.' 字符串拼接>>> text = ['I', ' Love ', 'Python!'] >>> print(''.join(text)) I Love Python! 字符串的contains>>> 'ov' in 'love' True 反转元素>>> 'Love'[::-1] 'evoL' >>> for e in reversed([1,3,5]): print(e) 5 3 1 去除非法字符串保存文件时,我们必须去除一些非法字符串,此处利用any函数实现def rectify(name): if any(symbol in name for symbol in ['?', '<', '>', '|', '*', '"', ":"]): name = ''.join([c for c in name if c not in ['?', '<', '>', '|', '*', '"', ":"]]) return name HTML转义>>> import html >>> html.unescape('&lt') '<' >>> html.escape('<') '&lt;' 函数可变参数*args:任意数量的位置参数,可被打包成元组。**kwargs:任意数量的关键词参数,可被打包成字典。打包def foo(*args, **kwargs): print(f"args: {args}") print(f"kwargs: {kwargs}") >>> foo(1,2,3,4, a=1,b=2,c=3) args: (1, 2, 3, 4) kwargs: {'a': 1, 'b': 2, 'c': 3} 解包def foo(x, y): print(x, y) alist = [1, 2] adict = {'x': 1, 'y': 2} >>> foo(*alist) 1, 2 >>> foo(**adict) 1, 2 装饰器装饰器的主要用途:打印日志、检测性能、数据库事务、URL路由它本质上就是一个高阶函数,它接收一个函数作为参数,然后,返回一个新函数。想理解装饰器,就得知道以下两点:1. 函数皆对象2. 闭包特性(内函数能捕捉到外函数的环境变量)简单的日志函数from datetime import datetime import functools def log(f): @functools.wraps(f) def wr(*args, **kwargs): print(f'call {f.__name__}() at {datetime.now()}') return f(*args, **kwargs) return wr @log def square(x): return x ** 2 >>> square(2) call square() at 2018-01-24 11:01:19.547516 4 注意到为了让@deco自适应任何参数定义的函数,我们将可变参数args, *kwargs作为了wr的参数@functools.wraps(f)为了防止wr的函数属性覆盖掉原函数的属性,我们必须利用@functools.wraps(f)来把原函数的所有属性复制到新函数里# 不加@functools.wraps(f)的情况下 >>> square.__name__ 'wr' # 加了@functools.wraps(f)的情况下 >>> square.__name__ 'square' 如果想给装饰器传递参数,那么你必须利用闭包特性再嵌套一层函数,不过这并不常用。函数性能检测def perf(f): @functools.wraps(f) def wr(*args, **kwargs): start = time.time() r = f(*args, **kwargs) end = time.time() print(f'call {f.__name__}() in {end - start}') return r return wr @perf def test(x): time.sleep(2) return x >>> test(5) call test() in 2.0007083415985107 5 数据库的cursordef link_mysql(fun): def wr(*args, **kwargs): with pymysql.connect(host=host, port=port, user=user, passwd=passwd, db=dbname, charset=charset) as cur: fun(cur, *args, **kwargs) return wr @link_mysql def insert_data(cur, ...): # execute your sql here. 上下文管理器应用文件操作(超常用)、进程互斥锁和支持上下文的其他对象目的是为了代替try语句和简化语法以文件操作为例:利用它,文件会自动打开和关闭with open('/path/to/file', 'r') as f: handle_f 上下文语句支持嵌套(nested)例如将a文件的源数据写入b文件里:with open('a.txt') as i, open('b.txt') as o: o.write(i.read()) 实质通过上下文管理协议__enter__和__exit__来实现Python有个库contextlib利用生成器简化了这种实现,以下是大体框架from contextlib import contextmanager @contextmanager def make_context() : # enter try: yield <value> except Exception as e: # handle_err finally: # exit with make_context() as <value>: # handle_value 以下是with语句操作文件的实质由于自定义,函数名用my_open,但功能和open几乎一样@contextmanager def my_open(filename, mode): f = open(filename, mode) try: yield f except Exception as e: raise e finally: f.close() with my_open('/path/to/file', 'r') as f: handle_f 偏函数partial()用于把一个函数的某些参数给固定住(也就是设置默认值),并返回一个新的函数。def int2(x, base=2): return int(x, base) 相当于:import functools int2 = functools.partial(int, base=2) 数据结构元组元组是一个immutable对象,有以下重要性:- 性能优化- 线程安全- 可以作为dict的key(hashable)- 拆包特性元组拆包a, b = b, a两个数字交换的原理就是它。以下是利用它来获取文件名及其扩展名>>> import os >>> filename, ext = os.path.splitext('patch.exe') >>> filename 'patch' >>> ext 'exe' 更多的解包方式(_代表舍弃,*代表可变长元组)>>> t = (1, 2, 3, 4) >>> first, *middle, last = t >>> middle [2, 3] >>> _, *rest = t >>> rest [2, 3, 4] 列表切片如果想要获取列表的多个元素,就得用到切片list[start:stop:step] 你甚至可以给切片命名,增强复用性和可读性:s = slice(start,stop,step) list[s] 切片的原理是序列协议class Seq: def __getitem__(self, index): return index >>> s = Seq() >>> s[1:5:2] slice(1, 5, 2) 以上实现的是不可变序列协议,如果可变的话还要添加__setitem__()如果在运行时添加协议的话也行,这叫猴子补丁>>> def set_item(self, key, value): self[key] = value >>> classname.__setitem__ = set_item 列表推导式这是Python最强大的几个特征之一。格式也很简单,其中if条件可以省略,for循环可以有多个[i for i in iterable if condition] 10-20所有偶数的平方:[i*i for i in range(10, 21) if i % 2 == 0 ] 一行实现快排def qsort(arr): return arr if len(arr) <= 1 else qsort([x for x in arr[1:] if x<arr[0]]) + [arr[0]] + qsort([x for x in arr[1:] if x>=arr[0]]) 索引迭代enumerate()可以把一个list变成索引-元素对。for i, value in enumerate(['A', 'B', 'C']): print(i, value) 0 A 1 B 2 C zipzip()可以将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,并返回一个迭代器,常用于同时遍历两个可迭代对象。>>> li1 = ['Python' ,'JavaScript', 'Java'] >>> li2 = [1, 2, 3] >>> nl = zip(li1, li2) <zip object at memory> >>> list(nl) [('Python', 1), ('JavaScript', 2), ('Java', 3)] 配合dict可以生成字典>>> l1 = ['A', 'B', 'C'] >>> l2 = [1, 2, 3] >>> dict(zip(l1, l2)) {'A': 1, 'B': 2, 'C': 3} append和extend>>> x = [1, 2, 3] >>> x.extend([4, 5]) >>> x [1, 2, 3, 4, 5] >>> x.append([6, 7]) >>> x [1, 2, 3, 4, 5, [6, 7]] 集合运算首先将要比较的两个list转换为set,再转回list就行了>>> l1 = [1, 2, 3, 4] >>> l2 = [2, 3, 5, 7] >>> list(set(l1) & set(l2)) [2, 3] >>> list(set(l1) | set(l2)) [1, 2, 3, 4, 5, 7] >>> list(set(l1) ^ set(l2)) [1, 4, 5, 7] 字典本质是键值对哈希表get用来获取某个键的值,不存在的话就用设置的default(默认为None)>>> d = dict(a=1, b=2) >>> d.get('a') 1 >>> d.get('c') >>> d.get('d', 2) 2 合并>>> d1 = {'a':1, 'b':2} >>> d2 = {'c':3, 'd':4} >>> nd = {**d1, **d2} >>> nd {'a': 1, 'b': 2, 'c': 3, 'd': 4} 类似的,列表也可以这样合并>>> l1 = [1, 2] >>> l2 = [3, 4] >>> l3 = [*l1, *l2] >>> l3 [1, 2, 3, 4] 键值对反转>>> kv = {'a': 1, 'b':2 , 'c': 3} >>> vk = zip(kv.values(), kv.keys()) >>> dict(vk) {1: 'a', 2: 'b', 3: 'c'} >>> min(vk) (1, 'a') >>> sorted(vk) [(1, 'a'), (2, 'b'), (3, 'c')] 键值排序>>> rows = [{k1: v1, k2: v2 ...}, ...] >>> from operator import itemgetter # 根据k1排序 >>> sorted(rows, key=itemgetter(k1)) # 类似的,对于class的对象可以用attrgetter进行排序 集合运算>>> a = {'a': 1, 'b': 2, 'c': 3} >>> b = {'x': 1, 'b': 2, 'c': 4} >>> a.keys() & b.keys() {'b', 'c'} >>> a.keys() - b.keys() {'a'} >>> a.items() & b.items() {('b', 2)} 其他数据结构具名元组常用于构建简单的类>>> from collections import namedtuple >>> Point = namedtuple('Point', ['x', 'y']) >>> p = Point(x=11, y=22) >>> p Point(x=11, y=22) >>> p.x + p.y 33 >>> coord = (33, 44) >>> q = Point(*coord) >>> q Point(x=33, y=44) 默认值字典常用于统计数目>>> from collections import defaultdict >>> words = ('python', 'java', 'ruby', 'python', 'C', 'java', 'C++', 'C') >>> counts = defaultdict(int) >>> for word in words: ... counts[word] += 1 >>> counts defaultdict(<class 'int'>, {'python': 2, 'java': 2, 'ruby': 1, 'C': 2, 'C++': 1}) 双向队列>>> from collections import deque >>> q = deque(["Eric", "John", "Michael"]) >>> q.append("Terry") >>> q deque(['Eric', 'John', 'Michael', 'Terry']) >>> q.popleft() Eric' >>> q.pop() 'Terry' >>> q deque(['John', 'Michael']) 计数器>>> from collections import Counter >>> c = Counter('hello world') >>> c Counter({'l': 3, 'o': 2, ' ': 1, 'e': 1, 'd': 1, 'h': 1, 'r': 1, 'w': 1}) >>> c.most_common(2) [('l', 3), ('o', 2)] 堆>>> import heapq >>> a = [1, 2, 3] >>> b = [4, 5, 6] >>> c = list(heapq.merge(a, b)) >>> c [1, 2, 3, 4, 5, 6] >>> heapq.nlargest(3, c) [6, 5, 4] >>> heapq.nsmallest(3, c) [1, 2, 3] OOP只读属性可以通过在变量名前加__来使其变成私有变量,外部无法直接访问,但可以通过类定义的方法来访问。class Person(object): def __init__(self, name): self.__name = name def get_name(self): return self.__name def set_name(self, name): self.__name = name >>> p = Person('alphardex') >>> p.name Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Person' object has no attribute 'name' >>> p.get_name() 'alphardex' >>> p.set_name('wang') >>> p.get_name() 'wang' @property肯定有的人不习惯通过方法来访问私有变量,那么如何用属性来访问私有变量呢?这时就要用到@property了,它可以把一个方法变成属性调用class Person(object): def __init__(self, name): self.__name = name @property def name(self): return self.__name @name.setter def name(self, value): self.__name = value >>> p = Person('alphardex') >>> p.name 'alphardex' >>> p.name = 'wang' >>> p.name 'wang' slots当我们定义了一个class并用其创建了一个实例后,可以动态地给其绑定属性,如果要限制这一点,可以利用__slots__class Person(object): __slots__ = ('name', 'age') >>> p = Person('wang') >>> p.name = 'wang' >>> p.age = 21 >>> p.skill = 'Python' Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Person' object has no attribute 'skill' 魔术方法魔术方法可以用来定制类的功能。比如__repr__用来调试时打印类的字符串class Person(object): def __init__(self, name, age): self.name = name self.age = age def __repr__(self): return f'<Person {self.name} age: {self.age}>' >>> p = Person('alphardex', 21) >>> p <Person alphardex age: 21> 想了解更多魔术方法请参见官方文档元类type俗话说道生一,一生二,二生三,三生万物。在Python里可以这么说:type生元类,元类生类,类生实例。用一个数字变量的创建来说明这一点吧>>> age = 21 >>> age.__class__ <class 'int'> >>> age.__class__.__class__ <class 'type'> age可以看作为int类的实例,而int类又可以看做type类的实例。也就是说,type创建了int类,实际上诸如str和bool等类也是由type创建的。>>> help(type) Help on class type in module builtins: class type(object) | type(object_or_name, bases, dict) | type(object) -> the object's type | type(name, bases, dict) -> a new type def say_hello(self, name='world'): print(f'Hello, {name}') >>> Hello = type('Hello', (object,), dict(hello=say_hello)) >>> h = Hello() >>> type(Hello) <class 'type'> >>> type(h) <class '__main__.Hello'> 通过用help查看type,可以发现它确实能动态地创建类:第一个参数是类名name,第二个参数是基类bases,第三个参数是dict,里面包含着类的所有方法。实际上,type是Python的一个内置元类。自定义元类当然,你也可以利用type来定义自己的元类。class JSArrayMeta(type): def __new__(cls, name, bases, attrs): attrs['push'] = lambda self, value: self.append(value) attrs['shift'] = lambda self: self.pop(0) attrs['includes'] = lambda self, value: value in self return type.__new__(cls, name, bases, attrs) class JSList(list, metaclass=JSArrayMeta): def __init__(self, value): self.extend(value) >>> l = JSList([1, 2, 3]) >>> l [1, 2, 3] >>> l.push('a') >>> l [1, 2, 3, 'a'] >>> l.shift() 1 >>> l [2, 3, 'a'] >>> l.includes(3) True 我们首先定制了一个元类,叫JSArrayMetaclass(没错就是JS里的数组XD)注意元类的命名规则:结尾一定要有Meta作为识别__new__方法用来创建JSList类,它接受4个参数JSList继承了list类,同时获得了元类的所有方法其他加载内置模块利用-m参数,我们可以直接加载Python的模块# 搭建http服务器 $ python -m http.server # 创建虚拟环境 $ python -m venv <name> # 性能测试 $ python -m cProfile <file.py> # 查看JSON $ cat <file.json> | python -m json.tool 数据序列化import pickle data = ... # Some Python object # 存储 with open(f'{file}.pickle', 'wb') as f: pickle.dump(data, f) # 读取 with open(f'{file}.pickle', 'rb') as f: data = pickle.load(f) 数据分析利用pandas模块可以对数据进行分析$ pip install pandas >>> import pandas as pd >>> data = pd.read_csv(...) # 数据查看 >>> data.columns # 查看数据结构 >>> data.describe() # 简要数据分析 >>> data.sort_values(by=...) # 对数据排序 # 数据选取 >>> data.head() # 查看前五条数据 >>> data.iloc[n] # 选择位置为n的数据,支持切片 >>> data[data.A > 0] # 选择A栏大于0的数据 >>> data[data.B.isin([...])] # 利用in过滤数据 >>> data[~data.B.isin([...])] # 上一句的取反,相当于not in # 缺失值处理 >>> pd.isna(data) # 获取缺失值的布尔标记 >>> data.dropna(how='any') # 去除所有含有缺失值的栏 >>> data.fillna(value=5) # 填充所有含有缺失值的栏 # 数据保存(可以相互转换格式,支持excel、csv和json) >>> data.to_json(...)

 

作者:半载流殇
链接:https://zhuanlan.zhihu.com/p/35219750
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Pythonic,简言之就是以Python这门语言独特的方式写出既简洁又优美的代码!笔者精心整理了许多实用的Python tricks,想要提高效率、写出高质量的Python代码的话此文必看。

注:请将Python更新到3.6版,方能完美运行本文的所有代码。

字符串

格式化字符串

在字符串前加f,就可以在里面用大括号嵌入变量了(可以代替format函数)

复制代码
1
2
3
4
5
>>> a = 5 >>> b = 10 >>> f'Five plus ten is {a + b} and not {2 * (a + b)}.' 'Five plus ten is 15 and not 30.'

字符串拼接

复制代码
1
2
3
4
>>> text = ['I', ' Love ', 'Python!'] >>> print(''.join(text)) I Love Python!

字符串的contains

复制代码
1
2
3
>>> 'ov' in 'love' True

反转元素

复制代码
1
2
3
4
5
>>> 'Love'[::-1] 'evoL' >>> for e in reversed([1,3,5]): print(e) 5 3 1

去除非法字符串

保存文件时,我们必须去除一些非法字符串,此处利用any函数实现

复制代码
1
2
3
4
5
def rectify(name): if any(symbol in name for symbol in ['?', '<', '>', '|', '*', '"', ":"]): name = ''.join([c for c in name if c not in ['?', '<', '>', '|', '*', '"', ":"]]) return name

HTML转义

复制代码
1
2
3
4
5
6
>>> import html >>> html.unescape('&lt') '<' >>> html.escape('<') '&lt;'

函数

可变参数

*args:任意数量的位置参数,可被打包成元组。
**kwargs:任意数量的关键词参数,可被打包成字典。

打包

复制代码
1
2
3
4
5
6
7
def foo(*args, **kwargs): print(f"args: {args}") print(f"kwargs: {kwargs}") >>> foo(1,2,3,4, a=1,b=2,c=3) args: (1, 2, 3, 4) kwargs: {'a': 1, 'b': 2, 'c': 3}

解包

复制代码
1
2
3
4
5
6
7
8
9
def foo(x, y): print(x, y) alist = [1, 2] adict = {'x': 1, 'y': 2} >>> foo(*alist) 1, 2 >>> foo(**adict) 1, 2

装饰器

装饰器的主要用途:打印日志、检测性能、数据库事务、URL路由
它本质上就是一个高阶函数,它接收一个函数作为参数,然后,返回一个新函数。
想理解装饰器,就得知道以下两点:
1. 函数皆对象
2. 闭包特性(内函数能捕捉到外函数的环境变量)

简单的日志函数

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from datetime import datetime import functools def log(f): @functools.wraps(f) def wr(*args, **kwargs): print(f'call {f.__name__}() at {datetime.now()}') return f(*args, **kwargs) return wr @log def square(x): return x ** 2 >>> square(2) call square() at 2018-01-24 11:01:19.547516 4

注意到为了让@deco自适应任何参数定义的函数,我们将可变参数args, *kwargs作为了wr的参数

@functools.wraps(f)

为了防止wr的函数属性覆盖掉原函数的属性,我们必须利用@functools.wraps(f)来把原函数的所有属性复制到新函数里

复制代码
1
2
3
4
5
6
7
# 不加@functools.wraps(f)的情况下 >>> square.__name__ 'wr' # 加了@functools.wraps(f)的情况下 >>> square.__name__ 'square'

如果想给装饰器传递参数,那么你必须利用闭包特性再嵌套一层函数,不过这并不常用。

函数性能检测

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def perf(f): @functools.wraps(f) def wr(*args, **kwargs): start = time.time() r = f(*args, **kwargs) end = time.time() print(f'call {f.__name__}() in {end - start}') return r return wr @perf def test(x): time.sleep(2) return x >>> test(5) call test() in 2.0007083415985107 5

数据库的cursor

复制代码
1
2
3
4
5
6
7
8
9
def link_mysql(fun): def wr(*args, **kwargs): with pymysql.connect(host=host, port=port, user=user, passwd=passwd, db=dbname, charset=charset) as cur: fun(cur, *args, **kwargs) return wr @link_mysql def insert_data(cur, ...): # execute your sql here.

上下文管理器

应用

文件操作(超常用)、进程互斥锁和支持上下文的其他对象
目的是为了代替try语句和简化语法
以文件操作为例:利用它,文件会自动打开和关闭

复制代码
1
2
3
with open('/path/to/file', 'r') as f: handle_f

上下文语句支持嵌套(nested)
例如将a文件的源数据写入b文件里:

复制代码
1
2
3
with open('a.txt') as i, open('b.txt') as o: o.write(i.read())

实质

通过上下文管理协议__enter__和__exit__来实现
Python有个库contextlib利用生成器简化了这种实现,以下是大体框架

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
from contextlib import contextmanager @contextmanager def make_context() : # enter try: yield <value> except Exception as e: # handle_err finally: # exit with make_context() as <value>: # handle_value

以下是with语句操作文件的实质
由于自定义,函数名用my_open,但功能和open几乎一样

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
@contextmanager def my_open(filename, mode): f = open(filename, mode) try: yield f except Exception as e: raise e finally: f.close() with my_open('/path/to/file', 'r') as f: handle_f

偏函数

partial()用于把一个函数的某些参数给固定住(也就是设置默认值),并返回一个新的函数。

复制代码
1
2
3
def int2(x, base=2): return int(x, base)

相当于:

复制代码
1
2
3
import functools int2 = functools.partial(int, base=2)

数据结构

元组

元组是一个immutable对象,有以下重要性:
- 性能优化
- 线程安全
- 可以作为dict的key(hashable)
- 拆包特性

元组拆包

a, b = b, a
两个数字交换的原理就是它。
以下是利用它来获取文件名及其扩展名

复制代码
1
2
3
4
5
6
7
>>> import os >>> filename, ext = os.path.splitext('patch.exe') >>> filename 'patch' >>> ext 'exe'

更多的解包方式(_代表舍弃,*代表可变长元组)

复制代码
1
2
3
4
5
6
7
8
>>> t = (1, 2, 3, 4) >>> first, *middle, last = t >>> middle [2, 3] >>> _, *rest = t >>> rest [2, 3, 4]

列表

切片

如果想要获取列表的多个元素,就得用到切片

复制代码
1
2
list[start:stop:step]

你甚至可以给切片命名,增强复用性和可读性:

复制代码
1
2
3
s = slice(start,stop,step) list[s]

切片的原理是序列协议

复制代码
1
2
3
4
5
6
7
class Seq: def __getitem__(self, index): return index >>> s = Seq() >>> s[1:5:2] slice(1, 5, 2)

以上实现的是不可变序列协议,如果可变的话还要添加__setitem__()
如果在运行时添加协议的话也行,这叫猴子补丁

复制代码
1
2
3
4
>>> def set_item(self, key, value): self[key] = value >>> classname.__setitem__ = set_item

列表推导式

这是Python最强大的几个特征之一。
格式也很简单,其中if条件可以省略,for循环可以有多个

复制代码
1
2
[i for i in iterable if condition]

10-20所有偶数的平方:

复制代码
1
2
[i*i for i in range(10, 21) if i % 2 == 0 ]

一行实现快排

复制代码
1
2
3
def qsort(arr): return arr if len(arr) <= 1 else qsort([x for x in arr[1:] if x<arr[0]]) + [arr[0]] + qsort([x for x in arr[1:] if x>=arr[0]])

索引迭代

enumerate()可以把一个list变成索引-元素对。

复制代码
1
2
3
4
for i, value in enumerate(['A', 'B', 'C']): print(i, value) 0 A 1 B 2 C

zip

zip()可以将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,并返回一个迭代器,常用于同时遍历两个可迭代对象。

复制代码
1
2
3
4
5
6
7
>>> li1 = ['Python' ,'JavaScript', 'Java'] >>> li2 = [1, 2, 3] >>> nl = zip(li1, li2) <zip object at memory> >>> list(nl) [('Python', 1), ('JavaScript', 2), ('Java', 3)]

配合dict可以生成字典

复制代码
1
2
3
4
5
>>> l1 = ['A', 'B', 'C'] >>> l2 = [1, 2, 3] >>> dict(zip(l1, l2)) {'A': 1, 'B': 2, 'C': 3}

append和extend

复制代码
1
2
3
4
5
6
7
8
>>> x = [1, 2, 3] >>> x.extend([4, 5]) >>> x [1, 2, 3, 4, 5] >>> x.append([6, 7]) >>> x [1, 2, 3, 4, 5, [6, 7]]

集合运算

首先将要比较的两个list转换为set,再转回list就行了

复制代码
1
2
3
4
5
6
7
8
9
>>> l1 = [1, 2, 3, 4] >>> l2 = [2, 3, 5, 7] >>> list(set(l1) & set(l2)) [2, 3] >>> list(set(l1) | set(l2)) [1, 2, 3, 4, 5, 7] >>> list(set(l1) ^ set(l2)) [1, 4, 5, 7]

字典

本质是键值对哈希表

get

用来获取某个键的值,不存在的话就用设置的default(默认为None)

复制代码
1
2
3
4
5
6
7
>>> d = dict(a=1, b=2) >>> d.get('a') 1 >>> d.get('c') >>> d.get('d', 2) 2

合并

复制代码
1
2
3
4
5
6
>>> d1 = {'a':1, 'b':2} >>> d2 = {'c':3, 'd':4} >>> nd = {**d1, **d2} >>> nd {'a': 1, 'b': 2, 'c': 3, 'd': 4}

类似的,列表也可以这样合并

复制代码
1
2
3
4
5
6
>>> l1 = [1, 2] >>> l2 = [3, 4] >>> l3 = [*l1, *l2] >>> l3 [1, 2, 3, 4]

键值对反转

复制代码
1
2
3
4
5
6
7
8
9
>>> kv = {'a': 1, 'b':2 , 'c': 3} >>> vk = zip(kv.values(), kv.keys()) >>> dict(vk) {1: 'a', 2: 'b', 3: 'c'} >>> min(vk) (1, 'a') >>> sorted(vk) [(1, 'a'), (2, 'b'), (3, 'c')]

键值排序

复制代码
1
2
3
4
5
6
>>> rows = [{k1: v1, k2: v2 ...}, ...] >>> from operator import itemgetter # 根据k1排序 >>> sorted(rows, key=itemgetter(k1)) # 类似的,对于class的对象可以用attrgetter进行排序

集合运算

复制代码
1
2
3
4
5
6
7
8
9
>>> a = {'a': 1, 'b': 2, 'c': 3} >>> b = {'x': 1, 'b': 2, 'c': 4} >>> a.keys() & b.keys() {'b', 'c'} >>> a.keys() - b.keys() {'a'} >>> a.items() & b.items() {('b', 2)}

其他数据结构

具名元组

常用于构建简单的类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
>>> from collections import namedtuple >>> Point = namedtuple('Point', ['x', 'y']) >>> p = Point(x=11, y=22) >>> p Point(x=11, y=22) >>> p.x + p.y 33 >>> coord = (33, 44) >>> q = Point(*coord) >>> q Point(x=33, y=44)

默认值字典

常用于统计数目

复制代码
1
2
3
4
5
6
7
8
9
>>> from collections import defaultdict >>> words = ('python', 'java', 'ruby', 'python', 'C', 'java', 'C++', 'C') >>> counts = defaultdict(int) >>> for word in words: ... counts[word] += 1 >>> counts defaultdict(<class 'int'>, {'python': 2, 'java': 2, 'ruby': 1, 'C': 2, 'C++': 1})

双向队列

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
>>> from collections import deque >>> q = deque(["Eric", "John", "Michael"]) >>> q.append("Terry") >>> q deque(['Eric', 'John', 'Michael', 'Terry']) >>> q.popleft() Eric' >>> q.pop() 'Terry' >>> q deque(['John', 'Michael'])

计数器

复制代码
1
2
3
4
5
6
7
>>> from collections import Counter >>> c = Counter('hello world') >>> c Counter({'l': 3, 'o': 2, ' ': 1, 'e': 1, 'd': 1, 'h': 1, 'r': 1, 'w': 1}) >>> c.most_common(2) [('l', 3), ('o', 2)]

复制代码
1
2
3
4
5
6
7
8
9
10
11
>>> import heapq >>> a = [1, 2, 3] >>> b = [4, 5, 6] >>> c = list(heapq.merge(a, b)) >>> c [1, 2, 3, 4, 5, 6] >>> heapq.nlargest(3, c) [6, 5, 4] >>> heapq.nsmallest(3, c) [1, 2, 3]

OOP

只读属性

可以通过在变量名前加__来使其变成私有变量,外部无法直接访问,但可以通过类定义的方法来访问。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Person(object): def __init__(self, name): self.__name = name def get_name(self): return self.__name def set_name(self, name): self.__name = name >>> p = Person('alphardex') >>> p.name Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Person' object has no attribute 'name' >>> p.get_name() 'alphardex' >>> p.set_name('wang') >>> p.get_name() 'wang'

@property

肯定有的人不习惯通过方法来访问私有变量,那么如何用属性来访问私有变量呢?这时就要用到@property了,它可以把一个方法变成属性调用

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Person(object): def __init__(self, name): self.__name = name @property def name(self): return self.__name @name.setter def name(self, value): self.__name = value >>> p = Person('alphardex') >>> p.name 'alphardex' >>> p.name = 'wang' >>> p.name 'wang'

slots

当我们定义了一个class并用其创建了一个实例后,可以动态地给其绑定属性,如果要限制这一点,可以利用__slots__

复制代码
1
2
3
4
5
6
7
8
9
10
class Person(object): __slots__ = ('name', 'age') >>> p = Person('wang') >>> p.name = 'wang' >>> p.age = 21 >>> p.skill = 'Python' Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Person' object has no attribute 'skill'

魔术方法

魔术方法可以用来定制类的功能。
比如__repr__用来调试时打印类的字符串

复制代码
1
2
3
4
5
6
7
8
9
10
class Person(object): def __init__(self, name, age): self.name = name self.age = age def __repr__(self): return f'<Person {self.name} age: {self.age}>' >>> p = Person('alphardex', 21) >>> p <Person alphardex age: 21>

想了解更多魔术方法请参见官方文档

元类

type

俗话说道生一,一生二,二生三,三生万物。
在Python里可以这么说:type生元类,元类生类,类生实例。
用一个数字变量的创建来说明这一点吧

复制代码
1
2
3
4
5
6
>>> age = 21 >>> age.__class__ <class 'int'> >>> age.__class__.__class__ <class 'type'>

age可以看作为int类的实例,而int类又可以看做type类的实例。
也就是说,type创建了int类,实际上诸如str和bool等类也是由type创建的。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> help(type) Help on class type in module builtins: class type(object) | type(object_or_name, bases, dict) | type(object) -> the object's type | type(name, bases, dict) -> a new type def say_hello(self, name='world'): print(f'Hello, {name}') >>> Hello = type('Hello', (object,), dict(hello=say_hello)) >>> h = Hello() >>> type(Hello) <class 'type'> >>> type(h) <class '__main__.Hello'>

通过用help查看type,可以发现它确实能动态地创建类:第一个参数是类名name,第二个参数是基类bases,第三个参数是dict,里面包含着类的所有方法。
实际上,type是Python的一个内置元类。

自定义元类

当然,你也可以利用type来定义自己的元类。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class JSArrayMeta(type): def __new__(cls, name, bases, attrs): attrs['push'] = lambda self, value: self.append(value) attrs['shift'] = lambda self: self.pop(0) attrs['includes'] = lambda self, value: value in self return type.__new__(cls, name, bases, attrs) class JSList(list, metaclass=JSArrayMeta): def __init__(self, value): self.extend(value) >>> l = JSList([1, 2, 3]) >>> l [1, 2, 3] >>> l.push('a') >>> l [1, 2, 3, 'a'] >>> l.shift() 1 >>> l [2, 3, 'a'] >>> l.includes(3) True

 

  • 我们首先定制了一个元类,叫JSArrayMetaclass(没错就是JS里的数组XD)
  • 注意元类的命名规则:结尾一定要有Meta作为识别
  • __new__方法用来创建JSList类,它接受4个参数
  • JSList继承了list类,同时获得了元类的所有方法

其他

加载内置模块

利用-m参数,我们可以直接加载Python的模块

复制代码
1
2
3
4
5
6
7
8
9
# 搭建http服务器 $ python -m http.server # 创建虚拟环境 $ python -m venv <name> # 性能测试 $ python -m cProfile <file.py> # 查看JSON $ cat <file.json> | python -m json.tool

数据序列化

复制代码
1
2
3
4
5
6
7
8
9
import pickle data = ... # Some Python object # 存储 with open(f'{file}.pickle', 'wb') as f: pickle.dump(data, f) # 读取 with open(f'{file}.pickle', 'rb') as f: data = pickle.load(f)

数据分析

利用pandas模块可以对数据进行分析

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$ pip install pandas >>> import pandas as pd >>> data = pd.read_csv(...) # 数据查看 >>> data.columns # 查看数据结构 >>> data.describe() # 简要数据分析 >>> data.sort_values(by=...) # 对数据排序 # 数据选取 >>> data.head() # 查看前五条数据 >>> data.iloc[n] # 选择位置为n的数据,支持切片 >>> data[data.A > 0] # 选择A栏大于0的数据 >>> data[data.B.isin([...])] # 利用in过滤数据 >>> data[~data.B.isin([...])] # 上一句的取反,相当于not in # 缺失值处理 >>> pd.isna(data) # 获取缺失值的布尔标记 >>> data.dropna(how='any') # 去除所有含有缺失值的栏 >>> data.fillna(value=5) # 填充所有含有缺失值的栏 # 数据保存(可以相互转换格式,支持excel、csv和json) >>> data.to_json(...)

转载于:https://www.cnblogs.com/yezefei/p/8709039.html

最后

以上就是难过啤酒最近收集整理的关于Pythonic---------详细讲解的全部内容,更多相关Pythonic---------详细讲解内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(65)

评论列表共有 0 条评论

立即
投稿
返回
顶部