Pythonic---------详细讲解

作者:半载流殇
链接: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 rreturn 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() :# entertry:yield <value>except Exception as e:# handle_errfinally:# exit

with make_context() as <value>:# handle_value
以下是with语句操作文件的实质由于自定义,函数名用my_open,但功能和open几乎一样@contextmanager
def my_open(filename, mode):f = open(filename, mode)try:yield fexcept Exception as e:raise efinally: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 = namedef get_name(self):return self.__namedef 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@propertydef name(self):return self.__name@name.setterdef 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 = nameself.age = agedef __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 typedef 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 selfreturn 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函数)

>>> 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 rreturn wr@perf
def test(x):time.sleep(2)return x>>> test(5)
call test() in 2.0007083415985107
5

数据库的cursor

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语句和简化语法
以文件操作为例:利用它,文件会自动打开和关闭

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() :# entertry:yield <value>except Exception as e:# handle_errfinally:# exitwith make_context() as <value>:# handle_value

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

@contextmanager
def my_open(filename, mode):f = open(filename, mode)try:yield fexcept Exception as e:raise efinally: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

zip

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

>>> 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 = namedef get_name(self):return self.__namedef 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@propertydef name(self):return self.__name@name.setterdef 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 = nameself.age = agedef __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 typedef 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 selfreturn 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://www.cnblogs.com/yezefei/p/8709039.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/389923.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据ab 测试_在真实数据上进行AB测试应用程序

大数据ab 测试Hello Everyone!大家好&#xff01; I am back with another article about Data Science. In this article, I will write about what is A-B testing and how to use it on real life data-set to compare two advertisement methods.我回来了另一篇有关数据科…

492. 构造矩形

492. 构造矩形 作为一位web开发者&#xff0c; 懂得怎样去规划一个页面的尺寸是很重要的。 现给定一个具体的矩形页面面积&#xff0c;你的任务是设计一个长度为 L 和宽度为 W 且满足以下要求的矩形的页面。要求&#xff1a; 你设计的矩形页面必须等于给定的目标面积。 宽度 …

node:爬虫爬取网页图片

前言 周末自己在家闲着没事&#xff0c;刷着微信&#xff0c;玩着手机&#xff0c;发现自己的微信头像该换了&#xff0c;就去网上找了一下头像&#xff0c;看着图片&#xff0c;自己就想着作为一个码农&#xff0c;可以把这些图片都爬取下来做成一个微信小程序&#xff0c;说干…

如何更好的掌握一个知识点_如何成为一个更好的讲故事的人3个关键点

如何更好的掌握一个知识点You’re launching a digital transformation initiative in the middle of the ongoing pandemic. You are pretty excited about this big-ticket investment, which has the potential to solve remote-work challenges that your organization fac…

centos 搭建jenkins+git+maven

gitmavenjenkins持续集成搭建发布人:[李源] 2017-12-08 04:33:37 一、搭建说明 系统&#xff1a;centos 6.5 jdk&#xff1a;1.8.0_144 jenkins&#xff1a;jenkins-2.93-1.1 git&#xff1a;git-2.9.0 maven&#xff1a;Maven 3.3.9 二、部署 2.1、jdk安装 1&#xff09;下…

638. 大礼包

638. 大礼包 在 LeetCode 商店中&#xff0c; 有 n 件在售的物品。每件物品都有对应的价格。然而&#xff0c;也有一些大礼包&#xff0c;每个大礼包以优惠的价格捆绑销售一组物品。 给你一个整数数组 price 表示物品价格&#xff0c;其中 price[i] 是第 i 件物品的价格。另有…

记录一次spark连接mysql遇到的问题

在使用spark连接mysql的过程中报错了&#xff0c;错误如下 08:51:32.495 [main] ERROR - Error loading factory org.apache.calcite.jdbc.CalciteJdbc41Factory java.lang.NoClassDefFoundError: org/apache/calcite/linq4j/QueryProviderat java.lang.ClassLoader.defineCla…

什么事数据科学_如果您想进入数据科学,则必须知道的7件事

什么事数据科学No way. No freaking way to enter data science any time soon…That is exactly what I thought a year back.没门。 很快就不会出现进入数据科学的怪异方式 ……这正是我一年前的想法。 A little bit about my data science story: I am a complete beginner…

python基础03——数据类型string

1. 字符串介绍 在python中&#xff0c;引号中加了引号的字符都被认为是字符串。 1 namejim 2 address"beijing" 3 msg My name is Jim, I am 22 years old! 那单引号、双引号、多引号有什么区别呢&#xff1f; 1) 单双引号木有任何区别&#xff0c;部分情况 需要考虑…

Java基础-基本数据类型

Java中常见的转义字符: 某些字符前面加上\代表了一些特殊含义: \r :return 表示把光标定位到本行行首. \n :next 表示把光标定位到下一行同样的位置. 单独使用在某些平台上会产生不同的效果.通常这两个一起使用,即:\r\n. 表示换行. \t :tab键,长度上相当于四个或者是八个空格 …

季节性时间序列数据分析_如何指导时间序列数据的探索性数据分析

季节性时间序列数据分析为什么要进行探索性数据分析&#xff1f; (Why Exploratory Data Analysis?) You might have heard that before proceeding with a machine learning problem it is good to do en end-to-end analysis of the data by carrying a proper exploratory …

TortoiseGit上传项目到GitHub

1. 简介 gitHub是一个面向开源及私有软件项目的托管平台&#xff0c;因为只支持git 作为唯一的版本库格式进行托管&#xff0c;故名gitHub。 2. 准备 2.1 安装git&#xff1a;https://git-scm.com/downloads。无脑安装 2.2 安装TortoiseGit(小乌龟)&#xff1a;https://torto…

496. 下一个更大元素 I

496. 下一个更大元素 I 给你两个 没有重复元素 的数组 nums1 和 nums2 &#xff0c;其中nums1 是 nums2 的子集。 请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。 nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果…

利用PHP扩展Taint找出网站的潜在安全漏洞实践

一、背景 笔者从接触计算机后就对网络安全一直比较感兴趣&#xff0c;在做PHP开发后对WEB安全一直比较关注&#xff0c;2016时无意中发现Taint这个扩展&#xff0c;体验之后发现确实好用&#xff1b;不过当时在查询相关资料时候发现关注此扩展的人数并不多&#xff1b;最近因为…

美团骑手检测出虚假定位_在虚假信息活动中检测协调

美团骑手检测出虚假定位Coordination is one of the central features of information operations and disinformation campaigns, which can be defined as concerted efforts to target people with false or misleading information, often with some strategic objective (…

869. 重新排序得到 2 的幂

869. 重新排序得到 2 的幂 给定正整数 N &#xff0c;我们按任何顺序&#xff08;包括原始顺序&#xff09;将数字重新排序&#xff0c;注意其前导数字不能为零。 如果我们可以通过上述方式得到 2 的幂&#xff0c;返回 true&#xff1b;否则&#xff0c;返回 false。 示例 …

org.apache.maven.archiver.MavenArchiver.getManifest

eclipse导入新的maven项目时&#xff0c;pom.xml第一行报错&#xff1a; org.apache.maven.archiver.MavenArchiver.getManifest(org.apache.maven.project.MavenProject, org.apache.maven.archiver.MavenArchiveConfiguration) 解决办法&#xff1a; help -> Install New…

杀进程常用命令

杀进程命令pkill 进程名killall 进程名 # 平缓kill -HUP pid # 平缓kill -USR2 pidkill pid &#xff08;-9 不要使用&#xff09;转载于:https://www.cnblogs.com/jmaly/p/9492406.html

CertUtil.exe被利用来下载恶意软件

1、前言 经过国外文章信息&#xff0c;CertUtil.exe下载恶意软件的样本。 2、实现原理 Windows有一个名为CertUtil的内置程序&#xff0c;可用于在Windows中管理证书。使用此程序可以在Windows中安装&#xff0c;备份&#xff0c;删除&#xff0c;管理和执行与证书和证书存储相…

335. 路径交叉

335. 路径交叉 给你一个整数数组 distance 。 从 X-Y 平面上的点 (0,0) 开始&#xff0c;先向北移动 distance[0] 米&#xff0c;然后向西移动 distance[1] 米&#xff0c;向南移动 distance[2] 米&#xff0c;向东移动 distance[3] 米&#xff0c;持续移动。也就是说&#x…