Python 3 中你可能没用过但很有用的特性

翻译自: https://datawhatnow.com/things-you-are-probably-not-using-in-python-3-but-should/

由于python 2 的停止支持(Python EOL), 许多人开始将他们的Python版本从2切换到3. 但是我发现很多 Python 3 代码仍然像 Python 2. 下面,我展示了一些你只能在 Python 3 中使用的激动人心的特性例子, 希望它能让你用 Python 解决问题变得更容易.

所有的例子都在 Python 3.7 下测试通过, 并且每个特性都在括号里列出了拥有这个特性的最小 Python 版本

f-字符串(f-strings) (3.6+)

在任何编程语言中没有字符串是很难做任何事情的. 为了保持清晰, 你希望有一个结构化的方式来处理字符串. 大多数使用python 的人推荐使用 format 方法

user = "Jane Doe"
action = "buy"
log_message = 'User {} has logged in and did an action {}.'.format(
  user,
  action
)
print(log_message)
# User Jane Doe has logged in and did an action buy.

format 相似, Python 3 提供了一个通过 f-strings 进行字符串插值的灵活方法, 上面的代码使用 f-strings 示例如下:

user = "Jane Doe"
action = "buy"
log_message = f'User {user} has logged in and did an action {action}.'
print(log_message)
# User Jane Doe has logged in and did an action buy.

Pathlib (3.4+)

f-strings 让人惊奇, 但是一些像文件路径这样的字符串有自己的库,这使得它们的操作更加容易. Python 3 提供了 pathlib 模块来处理文件路径. 如果你不确定为什么应该使用 pathlib, 试着读一下这篇精彩的帖子: Why you should be using pathlib – by Trey Hunner.

from pathlib import Path
root = Path('post_sub_folder')
print(root)
# post_sub_folder
path = root / 'happy_user'
# Make the path absolute
print(path.resolve())
# /home/weenkus/Workspace/Projects/DataWhatNow-Codes/how_your_python3_should_look_like/post_sub_folder/happy_user

类型提示(Type hinting) (3.5+)

静态和动态类型是软件工程领域一个热门的话题, 几乎每个人都有自己的看法. 写什么类型交给读者自己来定. 但我认为你至少应该了解 Python 3 支持的 “类型提示” (type hints)

def sentence_has_animal(sentence: str) -> bool:
  return "animal" in sentence
sentence_has_animal("Donald had a farm without animals")
# True

枚举类(Enumerations) (3.4+)

Python 3 支持通过枚举类Enum 来简单地编写枚举类型. 枚举是封装常量列表的一种方便方法,因此它们不会在没有太多结构的情况下随机分布在代码中。

from enum import Enum, auto
class Monster(Enum):
    ZOMBIE = auto()
    WARRIOR = auto()
    BEAR = auto()
    
print(Monster.ZOMBIE)
# Monster.ZOMBIE

An enumeration is a set of symbolic names (members) bound to unique, constant values. Within an enumeration, the members can be compared by identity, and the enumeration itself can be iterated over.

https://docs.python.org/3/library/enum.html

for monster in Monster:
    print(monster)
# Monster.ZOMBIE
# Monster.WARRIOR
# Monster.BEAR

内建的LRU缓存(Built-in LRU cache) (3.2+)

缓存几乎存在于我们今天使用的软件和硬件的任何水平切片中。Python 3通过暴露一个名为lru_cache的LRU(最近最少使用的)缓存装饰器, 使得使用它们变得非常简单.

一下是一个简单的斐波那契函数. 因为它通过递归重复做同样的工作, 所以我们知道它用到了缓存.

import time
def fib(number: int) -> int:
    if number == 0: return 0
    if number == 1: return 1
    
    return fib(number-1) + fib(number-2)
start = time.time()
fib(40)
print(f'Duration: {time.time() - start}s')
# Duration: 30.684099674224854s

现在我们可以使用lru_cache 来优化它(这种优化方法被称为 memoization ) 执行时间将从秒降到毫秒

from functools import lru_cache
@lru_cache(maxsize=512)
def fib_memoization(number: int) -> int:
    if number == 0: return 0
    if number == 1: return 1
    
    return fib_memoization(number-1) + fib_memoization(number-2)
start = time.time()
fib_memoization(40)
print(f'Duration: {time.time() - start}s')
# Duration: 6.866455078125e-05s

扩展的迭代器拆箱(Extended iterable unpacking) (3.0+)

功能描述在这 (docs).

head, *body, tail = range(5)
print(head, body, tail)
# 0 [1, 2, 3] 4
py, filename, *cmds = "python3.7 script.py -n 5 -l 15".split()
print(py)
print(filename)
print(cmds)
# python3.7
# script.py
# ['-n', '5', '-l', '15']

数据类(Data classes) (3.7+)

Python 3引入了没有很多限制的数据类, 可以用来减少样板代码, 因为decorator会自动生成特殊的方法, 例如__init__()__repr()__. 根据官方提议, 它们被描述为“具有默认值的可变命名元组”.

class Armor:
    def __init__(self, armor: float, description: str, level: int = 1):
        self.armor = armor
        self.level = level
        self.description = description
                 
    def power(self) -> float:
        return self.armor * self.level
    
armor = Armor(5.2, "Common armor.", 2)
armor.power()
# 10.4
print(armor)
# <__main__.Armor object at 0x7fc4800e2cf8>

Armour使用 数据类 的相同实现:

from dataclasses import dataclass
@dataclass
class Armor:
    armor: float
    description: str
    level: int = 1
    
    def power(self) -> float:
        return self.armor * self.level
    
armor = Armor(5.2, "Common armor.", 2)
armor.power()
# 10.4
print(armor)
# Armor(armor=5.2, description='Common armor.', level=2)

隐式命名包(Implicit namespace packages) (3.3+)

“包” (拥有 __init__.py 文件的目录) 是结构化 Python 代码的一种方法. 下面的例子来自 Python 官方文档

sound/                          Top-level package
      __init__.py               Initialize the sound package
      formats/                  Subpackage for file format conversions
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  Subpackage for sound effects
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  Subpackage for filters
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...

在 Python 2 中, 上面的每个文件夹都必须有__init__ 来将普通文件夹转换成Python包. 在 Python 3 中, 随着隐式命名空间包的引入, 这些文件不再需要.

sound/                          Top-level package
      __init__.py               Initialize the sound package
      formats/                  Subpackage for file format conversions
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  Subpackage for sound effects
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  Subpackage for filters
              equalizer.py
              vocoder.py
              karaoke.py
              ...

校订: 像很多人说的, 通过官方文档 PEP 420 Specification, 这个功能并不像我这段指出的那么简单. __init__.py对于常规包仍然是必需的, 将其从文件夹结构中删除会将其转换为带有附加限制的原生命名空间包. 官方示例 official docs on native namespace packages 提供了一个例子

结束语

像互联网上几乎所有的列表一样,这个列表并不完整。我希望这篇文章已经向您展示了至少一个您以前不知道的Python 3功能,并且它将帮助您编写更干净、更直观的代码。像往常一样,所有的代码都可以在GitHub上找到。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值