介绍 Python 功能和小技巧的文章网上有无数篇,比如变量解压缩,partial 偏函数,枚举可迭代对象... 但关于 Python 我们能说的还有很多。所以今天我将向大家展示一些我知道和有使用过的特性,这些特性在其它文章或博客中很少被提及:

消毒字符串输入

对用户输入内容进行消毒几乎适用于你写的每一个程序。通常来说转换字符大小写的操作就足够了,有时候用 Regex 正则表达式就能完成,但对于比较复杂的情况,我们有更好的办法:

user_input = "This\nstring has\tsome whitespaces...\r\n"
character_map = {
ord('\n') : ' ',
ord('\t') : ' ',
ord('\r') : None
}
user_input.translate(character_map) # This string has some whitespaces... "

在这个例子中我们可以看到空格子字符"\n"和"\t"已被单个空格代替,而"\r"已经被删除。这是一个很简单的示例,但我们可以更进一步,并使用unicodedata包和它的 combining() 函数来重新生成映射。

迭代器切片

如果尝试对 Iterator 进行切片,则会出现 TypeError和"generator object is not subscriptable"的报错,但我们有一个简单的解决办法:

import itertools
s = itertools.islice(range(50), 10, 20) # <itertools.islice object at 0x7f70fab88138>
for val in s:
...

通过使用 itertools.islice我们可以创建一个 islice对象,该对象是产生所需项目的迭代器。不过这里需要注意的是,它会消耗所有的生成器项直到切片的开始为止,而且还会消耗 islice对象中的所有项。

跳过可迭代对象的开始部分

有时候你不得不去处理这样一些文件,它们的开头是毫无用处的行,比如注释之类的。itertools再一次地能在这里派上用场:

string_from_file = """
// Author: ...
// License: ...
//
// Date: ...
Actual content...
"""
import itertools
for line in itertools.dropwhile(lambda line: line.startswith("//"), string_from_file.split
print(line)

这个代码片段只会生成文件开始注释之后的部分。如果我们只想丢弃可迭代对象开头的某些项(比如这个例子中的注释部分),但不确定这个项的大小,这个方法很实用。

创建支持 with声明的对象

大家想必都知道如何用 with声明来打开文件或者获取锁,但我们能实现自己的 with声明吗?是的,实际上通过使用 enter和 exit我们就可以实现一个上下文管理器协议:

class Connection:
def __init__(self):
...
def __enter__(self):
# Initialize connection...
def __exit__(self, type, value, traceback):
# Close connection...
with Connection() as c:
# __enter__() executes
...
# conn.__exit__() executes

这是 Python 中实现上下文管理最常见的方法,但其实还有一种更简单的方法:

from contextlib import contextmanager
@contextmanager
def tag(name):
print(f"<{name}>")
yield
print(f"")
with tag("h1"):
print("This is Title.")

上面的代码片段使用 contextmanager管理器装饰器实现了内容管理协议 。进入 with块时,执行 tag()的第一部分(在 yield之前),然后再执行该块,最后执行 tag()剩下的部分。

用 slots节省内存

如果在你编写的程序中会创建某个类的大量实例,那么你肯定已经注意到你的程序会占用大量内存。这是因为 Python 使用 Dictionary 来表示类实例的属性,虽然它速度很快但内存效率却很低。大部分情况下这个问题并不那么严重,但如果它对你的程序来说是一个大问题,你可以尝试使用 slots:

class Person:
__slots__ = ["first_name", "last_name", "phone"]
def __init__(self, first_name, last_name, phone):
self.first_name = first_name
self.last_name = last_name
self.phone = phone

所以这里的情况就是当我们定义slots的属性时,Python 使用的是小型的固定大小的数组,而不是 dictionary,这就大大减少了每个实例所需的内存。使用 slots也有缺点——我们无法声明任何新属性,并且只能在 slots上使用它们。同样,带有 slots的类不能使用多重继承。

限制 CPU 和内存使用

如果你不是想通过优化程序来降低它的 CPU 和内存使用率,而是想简单粗暴地直接限制它为某个数字,那么 Python 中有一个库可以做到:

import signal
import resource
import os
# To Limit CPU time
def time_exceeded(signo, frame):
print("CPU exceeded...")
raise SystemExit(1)
def set_max_runtime(seconds):
# Install the signal handler and set a resource limit
soft, hard = resource.getrlimit(resource.RLIMIT_CPU)
resource.setrlimit(resource.RLIMIT_CPU, (seconds, hard))
signal.signal(signal.SIGXCPU, time_exceeded)
# To limit memory usage
def set_max_memory(size):
soft, hard = resource.getrlimit(resource.RLIMIT_AS)
resource.setrlimit(resource.RLIMIT_AS, (size, hard))

这里我们看到了两种限制最大 CPU 运行时间和最大内存使用的方法。对于 CPU 限制,我们首先获得该特定资源( RLIMIT_CPU)的软限制与硬限制,然后使用参数指定的描述和闲钱获取的硬限制来设置它。最后,如果 CPU 时间被超出,我们将注册导致系统退出的信号。至于内存方面,我们再次获取软限制与硬限制,并使用带有 size 参数的 setrlimit和获取的硬限制对其进行设置。

控制可导入和不可导入的内容

有些语言对于到处成员变量,方法和接口有着非常明确的机制,比如 Golang,在 Go 中仅有以大写字母开头的成员才能被导出。另一方面,在 Python 中,所有内容都可以到处,除非我们使用 all:

def foo():
pass
def bar():
pass
__all__ = ["bar"]

根据上面的代码片段,我们可以看出只有 bar()会被导出。另外,我们可以将 all保留为空,并且从此模块导入时,不会输出任何 AttributeError。

比较运算符的简便方法

Python 中有很多比较运算符:lt , le , gt 和 ge,但有没有更容易的方法呢?functools.total_ordering就可以办到:

from functools import total_ordering
@total_ordering
class Number:
def __init__(self, value):
self.value = value
def __lt__(self, other):
return self.value < other.value
def __eq__(self, other):
return self.value == other.value
print(Number(20) > Number(3))
print(Number(1) < Number(5))
print(Number(15) >= Number(15))
print(Number(10) <= Number(2))

那么它实际上是怎么工作的呢?total_ordering装饰器用于简化为我们的类实现实力顺序的过程。只需要定义 lt 和 eq,这也是映射剩余操作所需的最低要求,也是装饰器的工作——它为我们填补了这个空缺。在学习Python的过程中,往往因为没有资料或者没人指导从而导致自己不想学下去了,因此我特意准备了个群 592539176 ,群里有大量的PDF书籍、教程都给大家免费使用!不管是学习到哪个阶段的小伙伴都可以获取到自己相对应的资料!

总结

上述的特性与操作都不一定是你在日常 Python 编程中常用到的,但其中一些时不时会让你感到头疼。上面所提供的解决方案大多简化了很多任务,这些任务用较为常见的方法处理都会比较冗长无聊。另外要指出的一点是,所有的这些功能都是 Python 标准库的一部分。在我看来,其中一些功能类似于“标准库中的非标准功能”,因此每当你想要在 Python 中实现某些功能时,首先去标准库里找一找,如果没有这个功能,那肯定是你找得不够仔细,如果实在是没有,再去找相关的第三方库。

关于 Python_你一定没读过的8个技巧的更多相关文章

  1. hdu 5092 Seam Carving (简单数塔DP,题没读懂,,不过可以分析样例)

    题意: 给一个m*n的矩阵,每格上有一个数. 找从第1行到第m行的一条路径,使得这条路径上的数之和最小. 路径必须满足相邻两行所选的两个数的纵坐标相邻(即一个格子必须是另一个格子的周围八个格子中的一个 ...

  2. PAT 甲级 1023 Have Fun with Numbers (20 分)(permutation是全排列题目没读懂)

    1023 Have Fun with Numbers (20 分)   Notice that the number 123456789 is a 9-digit number consisting ...

  3. 读>>>>白帽子讲Web安全<<<<摘要→我推荐的一本书→1

      <白帽子讲Web安全>吴翰清著 刚开始看这本书就被这本书吸引,感觉挺不错,给大家推荐下,最近读这本书,感觉不错的精华就记录下, 俗话说>>>好脑袋不如一个烂笔头< ...

  4. c++中ifstream读文件的问题(关于eof())

    今天帮别人找BUG,是一段关于c++读写文件的问题,使用的是ifstream与outstream类,关于ofstream与ifstream的用法,此处不再獒述,见代码: #include<ios ...

  5. Linux中的读函数与块高速缓存

    为了提高Linux块设备读写的效率,Unix会在内存中建立块高速缓存,块高速缓存存储了系统最近读的数据块和刚刚写入的数据块,也就是说IO访问其实是和块高速缓存打交道的(直接IO除外),块高速缓存会适时 ...

  6. [No000016D]把知识种进脑子:像读教材一样读书

    读书,常常是书读一遍,过后脑子却空白一片.旁人问起感受,只能以不错.很好作答.更有甚者,有时翻阅豆瓣才发现一本书竟早已「读过」,这事儿可真叫尴尬.为了对付这症状,我笔记也做过,思维导图也画过,奈何只是 ...

  7. POJ1410_还是没考虑全面——线段是否与矩形有共同的垂直投影

    题意如题目 有几个点1.怪我没读好题目:给出的矩形两个端点不一定都是左上右下,但是肯定能勾勒出一个矩形. 2.现在才发现很多线段相交的判断我都没有仔细考虑这一个问题 bool ssinsert(Poi ...

  8. Codeforces Round #589 (Div. 2) (e、f没写)

    https://codeforces.com/contest/1228/problem/A A. Distinct Digits 超级简单嘻嘻,给你一个l和r然后寻找一个数,这个数要满足的条件是它的每 ...

  9. Python_面试题_更新中

    Python-面试题 线上操作系统 centos py2和py3的区别 每种数据类型,列举你了解的方法 3 or 9 and 8 字符串的反转 is 和 == 的区别? git流程 v = (1) / ...

随机推荐

  1. Springboot中使用redis进行api限流

    api限流的场景 限流的需求出现在许多常见的场景中 秒杀活动,有人使用软件恶意刷单抢货,需要限流防止机器参与活动 某api被各式各样系统广泛调用,严重消耗网络.内存等资源,需要合理限流 淘宝获取ip所 ...

  2. 常用torch代码片段合集

    PyTorch常用代码段整理合集 本文代码基于 PyTorch 1.0 版本,需要用到以下包 import collections import os import shutil import tqd ...

  3. mysql 忘记登录密码(修改root密码)

    1.以管理员身份打开cmd,键入net stop mysql,停止mysql 2.切换到mysql的安装目录下(例:S:\mysql\mysql-8.0.18-winx64\mysql-8.0.18- ...

  4. 洛谷 CF402A Nuts 题解

    本蒟蒻又来发题解啦! 这题是个紫题? 好吧,恶意评分可海星? 回到正题 这题很明显是贪心啊: 有a个坚果,b个隔板,x个隔板,最多分成v个区间. 那么我们的贪心策略是: 如果一共使用的挡板小于x,且当 ...

  5. hibernate查询方式(三)

    QBC查询 (Query By Criteria) *****QBC查询有三个特点 **查询时不写sql语句 而是用方法来查询 **操作实体类和属性 **通过criteria对象来实现 1.查询所有 ...

  6. IO 单个文件的多线程拷贝

    package FileCopyThread; //自建的包,根据个人调整 import java.io.File; import java.io.FileNotFoundException; imp ...

  7. Java中跳出多重嵌套循环的方法

    一.使用标号 1.多重嵌套循环前定义一个标号 2.里层循环的代码中使用带有标号 break 的语句 public static void main(String[] args) { ok: for(i ...

  8. zabbix4.0.1 安装部署

    zabbix安装部署 目录 一.环境准备... 3 1.1.版本:... 3 1.2.部署环境... 3 二.安装部署... 3 2.1.zabbix安装... 3 2.1.1.下载zabbix的rp ...

  9. 【Web技术】281- 滴滴开源小程序框架 Mpx2.0

    滴滴Mpx框架负责人@hiyuki,滴滴出行网约车webapp乘客团队的负责人,也是滴滴开源的小程序框架Mpx的负责人和核心作者 Mpx是一款致力于提高小程序开发体验和效率的增强型小程序框架,目前在滴 ...

  10. ES7中的async 和 await

    async 和 await 一个函数如果加上 async ,那么该函数就会返回一个 Promise async function test() { return "1" } con ...