这是关于 Python 3.x 版本中首次出现的功能系列文章的第五篇。Python 3.4 于 2014 年首次发布,尽管它已经发布很长时间了,但它引入的许多功能都未被充分利用,而且非常酷。以下是其中三个。
enum
我最喜欢的逻辑谜题之一是自描述的史上最难逻辑谜题。 其中,它谈到了三个被称为 A、B 和 C 的神。 他们的身份是 True、False 和 Random,顺序不定。 你可以问他们问题,但他们只用神语回答,其中“da”和“ja”表示“是”和“否”,但你不知道哪个是哪个。
如果您决定使用 Python 来解决这个谜题,您将如何表示神的名字和身份以及神语中的单词? 传统的答案是使用字符串。 但是,字符串可能会拼写错误,从而导致灾难性的后果。
如果在解决方案的关键部分,您将与字符串 jaa
而不是 ja
进行比较,您将得到不正确的解决方案。 虽然谜题没有具体说明风险是什么,但这可能最好避免。
enum
模块使您能够以可调试且安全的方式定义这些内容
import enum
@enum.unique
class Name(enum.Enum):
A = enum.auto()
B = enum.auto()
C = enum.auto()
@enum.unique
class Identity(enum.Enum):
RANDOM = enum.auto()
TRUE = enum.auto()
FALSE = enum.auto()
@enum.unique
class Language(enum.Enum):
ja = enum.auto()
da = enum.auto()
枚举的一个优点是,在调试日志或异常中,枚举会以有用的方式呈现
name = Name.A
identity = Identity.RANDOM
answer = Language.da
print("I suspect", name, "is", identity, "because they answered", answer)
I suspect Name.A is Identity.RANDOM because they answered Language.da
functools.singledispatch
在开发游戏的“基础设施”层时,您希望通用地处理各种游戏对象,但仍然允许对象自定义操作。 为了使示例更容易解释,假设这是一个基于文本的游戏。 当您使用对象时,大多数情况下,它只会打印 You are using <x>
。 但是,使用特殊的剑可能需要随机掷骰子,否则会失败。
当您获得一个对象时,它通常会添加到库存中。 但是,一块特别重的石头会砸碎一个随机对象; 如果发生这种情况,库存将丢失该对象。
一种方法是在对象上使用方法 use
和 acquire
。 随着游戏复杂性的增加,将添加越来越多的这些方法,这使得游戏对象难以编写。
相反,functools.singledispatch
允许您以追溯方式添加方法——以安全且尊重命名空间的方式。
您可以定义没有行为的类
class Torch:
name="torch"
class Sword:
name="sword"
class Rock:
name="rock"
import functools
@functools.singledispatch
def use(x):
print("You use", x.name)
@functools.singledispatch
def acquire(x, inventory):
inventory.add(x)
对于火炬,这些通用实现就足够了
inventory = set()
def deploy(thing):
acquire(thing, inventory)
use(thing)
print("You have", [item.name for item in inventory])
deploy(Torch())
You use torch
You have ['torch']
但是,剑和石头需要一些专门的功能
import random
@use.register(Sword)
def use_sword(sword):
print("You try to use", sword.name)
if random.random() < 0.9:
print("You succeed")
else:
print("You fail")
deploy(sword)
You try to use sword
You succeed
You have ['sword', 'torch']
import random
@acquire.register(Rock)
def acquire_rock(rock, inventory):
to_remove = random.choice(list(inventory))
inventory.remove(to_remove)
inventory.add(rock)
deploy(Rock())
You use rock
You have ['sword', 'rock']
石头可能压碎了火炬,但您的代码更易于阅读。
pathlib
自时间开始以来,Python 中文件路径的接口一直是“智能字符串操作”。 现在,借助 pathlib
,Python 拥有了一种面向对象的方式来操作路径
import pathlib
gitconfig = pathlib.Path.home() / ".gitconfig"
text = gitconfig.read_text().splitlines()
诚然,使用 /
作为运算符来生成路径名有点可爱,但实际上效果很好。 像 .read_text()
这样的方法允许您从小型文件中获取文本,而无需手动打开和关闭文件句柄。
这使您可以专注于重要的事情
for line in text:
if not line.strip().startswith("name"):
continue
print(line.split("=")[1])
Moshe Zadka
欢迎来到 2014 年
Python 3.4 大约在七年前发布,但此版本中首次出现的一些功能很酷且未被充分利用。 如果您还没有这样做,请将它们添加到您的工具包中。
评论已关闭。