关于 Python_你一定没读过的8个技巧

是程序员吖 · · 468 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

介绍 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 中实现某些功能时,首先去标准库里找一找,如果没有这个功能,那肯定是你找得不够仔细,如果实在是没有,再去找相关的第三方库。

![](https://upload-images.jianshu.io/upload_images/12778909-6fa6b9d73c6347bd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:是程序员吖

查看原文:关于 Python_你一定没读过的8个技巧

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

468 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传