Python进阶之道

栏目: Python · 发布时间: 5年前

内容简介:repo:如果说优雅也有缺点的话,那就是你需要艰巨的工作才能得到它,需要良好的教育才能欣赏它。 —— Edsger Wybe Dijkstra笔者精心整理了许多实用的Python tricks,欢迎各位Pythonistia参考。

repo: github.com/alphardex/p…

如果说优雅也有缺点的话,那就是你需要艰巨的工作才能得到它,需要良好的教育才能欣赏它。 —— Edsger Wybe Dijkstra

笔者精心整理了许多实用的Python tricks,欢迎各位Pythonistia参考。

基本

f-string

name = 'alphardex'
f'Ore wa {name} desu, {4 * 6} sai, gakusei desu.'
# 'Ore wa alphardex desu, 24 sai, gakusei desu.'
复制代码

三元运算符

# if condition:
#    fuck
# else:
#    shit
fuck if condition else shit
复制代码

字符串的拼接,反转与分割

letters = ['h', 'e', 'l', 'l', 'o']
''.join(letters)
# 'hello'
letters.reverse()
# ["o", "l", "l", "e", "h"]
name = 'nameless god'
name.split(' ')
# ['nameless', 'god']
复制代码

判断元素的存在性

'fuck' in 'fuck you'
# True
'slut' in ['bitch', 'whore']
# False
'company' in {'title': 'SAO III', 'company': 'A1 Pictures'}
# True
复制代码

函数

匿名函数

类似ES6的箭头函数,函数的简化写法,配合map、filter、sorted等高阶函数食用更佳

注:在 Python 中,一般更倾向于用列表推导式来替代map和filter

# def foo(parameters):
#     return expression
foo = lambda parameters: expression
复制代码

map - 映射

numbers = [1, 2, 3, 4, 5]
list(map(lambda e: e ** 2, numbers))
# [1, 4, 9, 16, 25]
复制代码

filter - 过滤

values = [None, 0, '', True, 'alphardex', 666]
list(filter(lambda e:e, values))
# [True, "alphardex", 666]
复制代码

sort - 排序

tuples = [(1, 'kirito'), (2, 'asuna'), (4, 'alice'), (3, 'eugeo')]
sorted(tuples, key=lambda x: x[1])
# [(4, 'alice'), (2, 'asuna'), (3, 'eugeo'), (1, 'kirito')]
sorted(tuples, key=lambda x: x[1], reverse=True)
# [(1, 'kirito'), (3, 'eugeo'), (2, 'asuna'), (4, 'alice')]
tuples.sort()
tuples
# [(1, 'kirito'), (2, 'asuna'), (3, 'eugeo'), (4, 'alice')]
复制代码

其中,key这个参数接受一个函数,并将其运用在序列里的每一个元素上,所产生的结果将是 排序 算法依赖的对比关键字

在这个例子中,key里面的函数获取了每个元素的字符串,排序算法将会基于字母顺序进行排序

排序默认是升序,把reverse设置为True,就能按降序排序

sorted会新建一个列表作为返回值,而list.sort则是就地排序

其他骚操作

from functools import reduce
# 求1到100的积
reduce(lambda x, y: x * y, range(1, 101))
# 求和就更简单了
sum(range(101))
# 5050
复制代码

扁平化列表

from functools import reduce
li = [[1,2,3],[4,5,6], [7], [8,9]]
flatten = lambda li: [item for sublist in li for item in sublist]
flatten(li)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
# 或者直接用more_itertools这个第三方模块
# from more_itertools import flatten
# list(flatten(li))
复制代码

星号和双星号

数据容器的合并

l1 = ['a', 'b']
l2 = [1, 2]
[*l1, *l2]
# ['a', 'b', 1, 2]
d1 = {'name': 'alphardex'}
d2 = {'age': 24}
{**d1, **d2}
# {'name': 'alphardex', 'age': 24}
复制代码

函数参数的打包与解包

# 打包
def foo(*args):
    print(args)
foo(1, 2)
# (1, 2)

def bar(**kwargs):
    print(kwargs)
bar(name='alphardex', age=24)
# {'name': 'alphardex', 'age': 24}

# 解包
t = (10, 3)
quotient, remainder = divmod(*t)
quotient
# 商:3
remainder
# 余:1
复制代码

数据容器

列表

推导式

笔者最爱的语法糖:)

even = [i for i in range(10) if not i % 2]
even
# [0, 2, 4, 6, 8]
复制代码

同时迭代元素与其索引

用enumerate即可

li = ['a', 'b', 'c']
print([f'{i+1}. {elem}' for i, elem in enumerate(li)])
# ['1. a', '2. b', '3. c']
复制代码

元素的追加与连接

append在末尾追加元素,extend在末尾连接元素

li = [1, 2, 3]
li.append([4, 5])
li
# [1, 2, 3, [4, 5]]
li.extend([4, 5])
li
# [1, 2, 3, [4, 5], 4, 5]
复制代码

测试是否整体/部分满足条件

all测试所有元素是否都满足于某条件,any则是测试部分元素是否满足于某条件

all([e<20 for e in [1, 2, 3, 4, 5]])
# True
any([e%2==0 for e in [1, 3, 4, 5]])
# False
复制代码

同时迭代2个以上的可迭代对象

用zip即可

subjects = ('nino', 'miku', 'itsuki')
predicates = ('saikou', 'ore no yome', 'is sky')
print([f'{s} {p}' for s, p in zip(subjects, predicates)])
# ['nino saikou', 'miku ore no yome', 'itsuki is sky']
复制代码

去重

利用集合的互异性

li = [3, 1, 2, 1, 3, 4, 5, 6]
list(set(li))
# [1, 2, 3, 4, 5, 6]
# 如果要保留原先顺序的话用如下方法即可
sorted(set(li), key=li.index)
# [3, 1, 2, 4, 5, 6]
复制代码

解包

此法亦适用于元组等可迭代对象

最典型的例子就是2数交换

a, b = b, a
# 等价于 a, b = (b, a)
复制代码

用星号运算符解包可以获取剩余的元素

first, *rest = [1, 2, 3, 4]
first
# 1
rest
# [2, 3, 4]
复制代码

字典

遍历

d = {'name': "alphardex", 'age': 24}
[key for key in d.keys()]
# ['name', 'age']
[value for value in d.values()]
# ['alphardex', 24]
[f'{key}: {value}' for key, value in d.items()]
# ['name: alphardex', 'age: 24']
复制代码

排序

import operator
data = [{'rank': 2, 'author': 'alphardex'}, {'rank': 1, 'author': 'alphardesu'}]
data_by_rank = sorted(data, key=operator.itemgetter('rank'))
data_by_rank
# [{'rank': 1, 'author': 'alphardesu'}, {'rank': 2, 'author': 'alphardex'}]
data_by_rank_desc = sorted(data, key=lambda x: x['rank'], reverse=True)
# [{'rank': 2, 'author': 'alphardex'}, {'rank': 1, 'author': 'alphardesu'}]
复制代码

反转

d = {'name': 'alphardex', 'age': 24}
{v: k for k, v in d.items()}
# {'alphardex': 'name', 24: 'age'}
复制代码

缺失键处理

get返回键值,如果键不在字典中,将会返回一个默认值

d = {'name': 'alphardex', 'age': 24}
d.get('sex', 'male')
# male
复制代码

setdefault返回键值,如果键不在字典中,将会添加它并设置一个默认值

d = {'name': 'alphardex', 'age': 24}
# if 'sex' not in d:
#     d['sex'] = 'male'
d.setdefault('sex', 'male')
# male
d
# {'name': 'alphardex', 'age': 24, 'sex': 'male'}
复制代码

分组

from collections import defaultdict
people = [('alphardex', 'male'), ('koizumi moeka', 'female'), ('alphardesu', 'male'), ('satou hinata', 'female')]
gender_group = defaultdict(list)
for name, gender in people:
    gender_group[gender].append(name)
gender_group
# defaultdict(<class 'list'>, {'male': ['alphardex', 'alphardesu'], 'female': ['koizumi moeka', 'satou hinata']})
复制代码

实例化一个defaultdict时,通常要传入一个可调用对象(这里以list为例),它会在__getitem__找不到键时被调用,让__getitem__返回某种默认值

向字典插入数据,如果键(假设为 new_key )不存在,则有以下三步:

new_key

语言专属特性

下划线_的几层含义

repl中暂存结果

>>> 1 + 1
# 2
>>> _
# 2
复制代码

忽略某个变量

filename, _ = 'eroge.exe'.split('.')
filename
# 'eroge'
for _ in range(2):
    print('wakarimasu')
# wakarimasu
# wakarimasu
复制代码

i18n国际化

_("This sentence is going to be translated to other language.")
复制代码

增强数字的可读性

1_000_000
# 1000000
复制代码

上下文管理器

用于资源的获取与释放,以代替try-except语句

常用于文件IO,锁的获取与释放,数据库的连接与断开等

# try:
#     f = open(input_path)
#     data = f.read()
# finally:
#     f.close()
with open(input_path) as f:
    data = f.read()
复制代码

可以用@contextmanager来实现上下文管理器

from contextlib import contextmanager

@contextmanager
def open_write(filename):
    try:
        f = open(filename, 'w')
        yield f
    finally:
        f.close()

with open_write('onegai.txt') as f:
    f.write('Dagakotowaru!')
复制代码

静态类型注解

给函数参数添加类型,能提高代码的可读性和可靠性,大型项目的最佳实践之一

from typing import List

def greeting(name: str) -> str:
    return f'Hello {name}.'

def gathering(users: List[str]) -> str:
    return f"{', '.join(users)} are going to be raped."

print(greeting('alphardex'))
print(gathering(['Bitch', 'slut']))
复制代码

多重继承

在django中经常要处理类的多重继承的问题,这时就要用到super函数

如果单单认为super仅仅是“调用父类的方法”,那就错了

其实super指的是MRO中的下一个类,用来解决多重继承时父类的查找问题

MRO是啥?Method Resolution Order(方法解析顺序)

看完下面的例子,就会理解了

class A:
    def __init__(self):
        print('A')

class B(A):
    def __init__(self):
        print('enter B')
        super().__init__()
        print('leave B')

class C(A):
    def __init__(self):
        print('enter C')
        super().__init__()
        print('leave C')

class D(B, C):
    pass

d = D()
# enter B
# enter C
# A
# leave C
# leave B
print(d.__class__.__mro__)
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
复制代码

首先,因为D继承了B类,所以调用B类的__init__,打印了 enter B

打印 enter B 后的super寻找MRO中的B的下一个类,也就是C类,并调用其__init__,打印 enter C

打印 enter C 后的super寻找MRO中的C的下一个类,也就是A类,并调用其__init__,打印 A

打印 A 后回到C的__init__,打印 leave C

打印 leave C 后回到B的__init__,打印 leave B

特殊方法

在django中,定义model的时候,希望admin能显示model的某个字段而不是XXX Object,那么就要定义好__str__

每当你使用一些内置函数时,都是在调用一些特殊方法,例如len()调用了__len__(), str()调用__str__()等

以下实现一个数学向量类,里面有6个特殊方法

from math import hypot

class Vector:
    # 实例创建
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    # 字符串表示形式
    def __repr__(self) -> str:
        return f'Vector({self.x}, {self.y})'

    # 数值转换 - 绝对值
    def __abs__(self) -> float:
        return hypot(self.x, self.y)

    # 数值转换 - 布尔值
    def __bool__(self) -> bool:
        return bool(abs(self))

    # 算术运算符 - 加
    def __add__(self, other: Vector) -> Vector:
        x = self.x + other.x
        y = self.y + other.y
        return Vector(x, y)

    # 算术运算符 - 乘
    def __mul__(self, scalar: float) -> Vector:
        return Vector(self.x * scalar, self.y * scalar)

v = Vector(3, 4)

# repr(v) => v.__repr__()
v
# Vector(3, 4)

# abs(v) => v.__abs__()
abs(v)
# 5.0

# bool(v) => v.__bool__()
bool(v)
# True

# v1 + v2  => v1.__add__(v2)
v1 = Vector(1, 2)
v2 = Vector(3, 4)
v1 + v2
# Vector(4, 6)

# v * 3  => v.__mul__(3)
v * 3
# Vector(9, 12)
复制代码

想了解所有的特殊方法可查阅官方文档,以下列举些常用的:

字符串表示形式:__str__, __repr__
数值转换:__abs__, __bool__, __int__, __float__, __hash__
集合模拟:__len__, __getitem__, __setitem__, __delitem__, __contains__
迭代枚举:__iter__, __reversed__, __next__
可调用模拟:__call__
实例创建与销毁:__init__, __del__
运算符相关:__add__, __iadd__, __mul__, __imul__
复制代码

以上所述就是小编给大家介绍的《Python进阶之道》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

编程真好玩

编程真好玩

[英] 乔恩·伍德科克 / 余宙华 / 南海出版公司 / 2017-8-1 / 88.00元

在美国,编程已进入幼儿园和中小学课堂,是备受欢迎的课程之一。 在英国,编程被列入国家教学大纲,成为6~15岁孩子的必修课。 在芬兰,编程理念融入了小学的各门课程,孩子们可以随时随地学编程。 编程已经成为世界的通用语言,和听、说、读、写、算一样,是孩子必须掌握的技能。 Scratch是美国麻省理工学院设计开发的可视化少儿编程工具,全球1500多万孩子正在学习使用。它把枯燥乏味......一起来看看 《编程真好玩》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

SHA 加密
SHA 加密

SHA 加密工具