不关心python的值

omitted的Python项目详细描述


a不关心python的值

让我们谈谈夸尔格

这很容易被认为是理所当然的,但是python最优雅的方面之一 是它对函数关键字参数(kwargs)的处理。这个构造 提供:

  1. A way to specify parameters without having to know its position in the argument list
  2. Automatic checking of expected parameters
  3. An elegant way to specify parameter defaults
  4. A meaningful, self-documenting function signature

大多数时候,夸尔格语都是完美无瑕的;但也有少数情况下 它们的使用变得棘手。

我要谈谈这个问题,展示一个常见的反模式 尝试修复它,然后提出一种保留所有 以引入新概念为代价的上述好处 python,Omittedsingleton。

问题,什么问题?

让我们从一个例子开始。假设有一个函数 允许您更新此人的姓名、年龄、两者或两者都不更新。 天真地说,您可以将该函数编写为类似于:

def update(person, name=None, age=None):
    person.name = name
    person.age = age

现在我们调用此函数,但只更新此人的年龄:

> person = Person(name='Alice', age=32)
> update(person, age=33)
> person.age
33
> person.name
None

注意,代码正确地设置了年龄,但是,从调用方的 从角度看,还可以将名称设置为None。不是我们想要的。

这里的问题是None不能同时用于表示有效值 同时我们也代表了一种不在乎的状态。

意识到我们需要一种区分这两种情况的方法,我们修改了 稍微编码:

def update(person, **kwargs):
    for k, v in kwargs.items():
        setattr(person, k, v)

在这里,我们使用在夸尔格字典中存在或不存在的键来 表示不关心条件,None的值被单独保留 用于实际将属性设置为None(非常合理,是吗?).

让我们再次调用这个新版本的update

> person = Person(name='Alice', age=32)
> update(person, age=33)
> person.age
33
> person.name
'Alice'

这个方法的表现和我们预期的完全一样。根据我的经验,很多 开发人员停在这里是因为它工作正常。但代价是:我们没有 长久以来,人们一直期待着夸格检查(优点2),而不是优雅的设置方式 默认参数(benefit 3),我们失去了有意义的函数 签名(利益4)。基于这些原因,我认为这是一种反模式 提出不同的方法。

不再有

为了保留显式kwargs的好处,我们需要一种方法来获取 区分不关心条件和有效条件的关键字 价值。如上所述,None不够好,因为None是 对许多属性来说都是非常合理的值。

相反,我们需要创建一个新值,一个像None这样的单例 表示这种情况,我称之为Omitted。有了它,我们的功能变成:

Omitted = object()

def update(person, name=Omitted, age=Omitted):
    if name is not Omitted:
        person.name = name

    if age is not Omitted:
        person.age = age

我们最终得到的代码与调用时的预期行为完全相同,但是 保留显式Kwargs的优点:

update(person, age=33)      # Just set the age to 33
update(person, name=None)   # Set the name to None
update(person)              # Doesn't update any attributes
update(person, foo=bar)     # Raises a TypeError because foo isn't an
                            # expected kwargs (benefit #2)

有什么发现?

所以,解决我们的默认Kwarg问题,我们已经发布了 包含update函数的库。现在假设有人来了 想用我们的图书馆。首先,他们会感谢我们 显式kwargs的用法-一旦它们通过不寻常的外观Omitted 默认值。

但是,当他们使用它时,他们可能会做如下操作:

Omitted = object()

def update_with_email(person, name=Omitted, age=Omitted):
    update(person, name=name, age=age)
    send_email(person)

> person = Person(name='Alice', age=32)
> update_with_email(age=33)
> person.age
33
> person.name
<object object at 0x105ae2080>

如您所见,person.name以值Omitted结束。这个 这里的问题是调用方的Omitted实例不同于 库Omitted实例,因此它们不会进行相同的比较。

我们想要的是定义一个表示 这并不关心所有python包中的条件,就像 None无论在哪里使用都是相同的。

介绍…

这个python模块旨在通过定义 Omitted实例,可在系统上的所有包之间共享。

要清楚,仅仅因为库使用Omitted,并不意味着 调用代码也必须如此。不传递Kwarg或将其设置为Nonewill 表现C正确地说,不必知道Omitted是在 让它发挥作用的场景。

调用方需要导入Omitted的唯一时间是 将调用方的“不关心”条件代理到库中。在那里面 凯斯,你只需要做如下事情:

from libperson import update
from omitted import Omitted

def update_with_email(person, name=Omitted, age=Omitted):
    update(person, name=name, age=age)
    send_email(person)

考虑到这一点,继续导入Omitted,让您的代码停止关心。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
春爪哇。lang.ClassCastException:com。爪哇语。模型DAOUser无法转换为com。爪哇语。刀。用户道   java是ConcurrentHashMap的密钥集迭代器是线程安全的吗?   java上的EmptyStackException   java Android通过多种布局进行导航   java Android将视频从其路径保存到gallery中   html Selenium Java如何搜索和查找给定父元素的特定嵌套元素是相同的   非顺序任务中的Java异常处理(模式/良好实践)   Java:自定义将1个月添加到当前日期   JAVAutil。Observable不遵循GoF的Observable设计模式,对吧?   java有人知道X.509证书中的哪些字段用于验证数字签名吗?   多线程如何在Java中实现同步?   java Spring boot+Thymeleaf+ajax无法向控制器发送VO或DTO   调用IBM Mobilefirst 7.0SAP JCo适配器时发生java错误   java Hibernate搜索在布尔查询中处理null   java如何使用angularJS将共享文件夹文件复制到本地计算机