当前位置 主页 > 网站技术 > 代码类 >

    你可能不知道的Python 技巧小结

    栏目:代码类 时间:2020-01-30 06:12

    译者 | 豌豆花下猫

    声明 :本文获得原作者授权翻译,转载请保留原文出处,请勿用于商业或非法用途。

    有许许多多文章写了 Python 中的许多很酷的特性,例如变量解包、偏函数、枚举可迭代对象,但是关于 Python 还有很多要讨论的话题,因此在本文中,我将尝试展示一些我知道的和在使用的,但很少在其它文章提到过的特性。那就开始吧。

    1、对输入的字符串“消毒”

    对用户输入的内容“消毒”,这问题几乎适用于你编写的所有程序。通常将字符转换为小写或大写就足够了,有时你还可以使用正则表达式来完成工作,但是对于复杂的情况,还有更好的方法:

    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() 函数,来生成更大的重映射表(remapping table),并用它来删除字符串中所有的重音。

    2、对迭代器切片

    如果你尝试直接对迭代器切片,则会得到 TypeError ,提示说该对象不可取下标(not subscriptable),但是有一个简单的解决方案:

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

    使用itertools.islice,我们可以创建一个 islice 对象,该对象是一个迭代器,可以生成我们所需的内容。但是这有个重要的提醒,即它会消耗掉切片前以及切片对象 islice 中的所有元素。

    (译注:更多关于迭代器切片的内容,可阅读 Python进阶:迭代器与迭代器切片)

    3、跳过可迭代对象的开始

    有时候你必须处理某些文件,它们以可变数量的不需要的行(例如注释)为开头。 itertools 再次提供了简单的解决方案:

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

    这段代码仅会打印在初始的注释部分之后的内容。如果我们只想丢弃迭代器的开头部分(在此例中是注释),并且不知道有多少内容,那么此方法很有用。

    4、仅支持关键字参数(kwargs)的函数

    当需要函数提供(强制)更清晰的参数时,创建仅支持关键字参数的函数,可能会挺有用:

    def test(*, a, b):
     pass
    
    test("value for a", "value for b") # TypeError: test() takes 0 positional arguments...
    test(a="value", b="value 2") # Works...

    如你所见,可以在关键字参数之前,放置单个 * 参数来轻松解决此问题。如果我们将位置参数放在 * 参数之前,则显然也可以有位置参数。

    5、创建支持 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