4

我有一种情况,我被要求阅读来自各种来源的数据库更新说明集合。所有源都将包含一个主键值,以便将更新应用于数据库的代码可以找到正确的记录。但是,这些文件会在报告的附加列中有所不同。

当我阅读并创建我的更新说明时,我必须区分提供了列(例如,MiddleName)但为空的更新(意味着没有中间名并且该字段应更新为 NULL)和其中 MiddleName不包括字段(意味着更新根本不应该触及中间名列)。

前一种情况(提供了列但没有值)似乎适当地由None值表示。然而,对于第二种情况,我想要一个NotInFile “值”,我可以使用类似于我使用 None 的方式。

执行此操作的正确方法如下?

NotInFile = 1

class PersonUpdate(object):

     def __init__(self):

         self.PersonID = None
         self.FirstName = NotInFile
         self.MiddleName = NotInFile

然后在另一个模块中

import othermod
upd = othermod.PersonUpdate()
if upd.MiddleName is othermod.NotInFile:
    print 'Hey, middle name was not supplied'
4

3 回答 3

10

我认为您的实施没有什么特别的问题。但是,1它不一定是最佳标记值,因为它是 Cpython 中的缓存常量。(例如-1+2 is 1将返回True)。在这些情况下,我可能会考虑使用哨兵对象实例:

NotInFile = object()

python 还提供了一些其他的命名常量,如果它看起来合适,您可以使用它们: NotImplementedEllipsis立即想到。(请注意,我不建议您使用这些常量……我只是提供更多选项)。

于 2013-06-24T14:26:32.360 回答
8

不,使用整数 1 是个坏主意。在这种情况下,如果MiddleName始终是一个字符串或None,它可能会起作用,但一般来说,实现可以自由地实习整数、字符串、元组和其他不可变的值。CPython 对上述类型的小整数和常量执行此操作。PyPyis按值定义整数和其他一些类型。所以如果MiddleName是 1,你一定会看到你的代码认为它没有提供。

使用 anobject相反,每个新对象都有一个不同的标识:

NotInFile = object()

或者,为了更好的调试输出,定义你自己的类:

class NotInFileType(object):
    # __slots__ = () if you want to save a few bytes
    def __repr__(self):
        return 'NotInFile'

NotInFile = NotInFileType()
del NotInFileType # look ma, no singleton

如果你是偏执狂,你可以让它成为一个合适的单身(丑陋)。如果您需要几个这样的实例,您可以将类重命名为Sentiel或其他东西,使表示成为实例变量并使用多个实例。

于 2013-06-24T14:27:16.310 回答
4

如果你想要类型检查,这个习语现在受到 PEP 484 的祝福得到 mypy 的支持

from enum import Enum

class NotInFileType(Enum):
    _token = 0

NotInFile = NotInFileType._token

如果您使用的是 mypy 0.740 或更早版本,则需要使用 typing.Final 来解决mypy 中的此错误

from typing import Final

NotInFile: Final = NotInFileType._token

如果您使用的是 Python 3.7 或更早版本,则可以使用typing_extensions.Finalfrom pip packagetyping_extensions而不是typing.Final

于 2019-08-17T11:28:35.683 回答