我有一个用例,需要检查给定的值是True还是False

def stringify(value):
    """Returns the string representation of the value."""

    if value is None:
        return '-'

    if value is True:
        return '✓'

    if value is False:
        return '✗'

    return str(value)


我知道,在大多数情况下,您只需要事实是,您只需要执行if value:即可。但这并不能满足要求,因为我希望以十进制形式显示零个int s和float s以及空的list s,set s dict s。
上面的代码是否可以接受?首先使用isinstance(value, bool)检查,然后再使用if value:吗?

最令人惊讶的方式是什么?到终端输出:
MariaDB→peewee→API→终端

示例输出:

 $ termutil ls -T 1000
  ID  TID         CID  VID  OS                     IPv4 Address               Deployed  Testing  Tainted  Address                                           Annotation                      
 214    1        1000    -  HIDSL latest              XX.Y.Z.75                      -        ✓        ✗  Musterstraße 42, 123456 Irgendwo                      -                               
 215    2        1000    -  HIDSL latest              XX.Y.Z.76                      -        ✓        ✗  Musterstraße 42, 123456 Irgendwo                      -                               
 216    3        1000    -  HIDSL latest              XX.Y.Z.77                      -        ✓        ✗  Musterstraße 42, 123456 Irgendwo                      -                               
 217    4        1000    -  HIDSL latest              XX.Y.Z.78                      -        ✓        ✗  Musterstraße 42, 123456 Irgendwo                      -                               
 218    5        1000    -  HIDSL latest              XX.Y.Z.79                      -        ✓        ✗  Musterstraße 42, 123456 Irgendwo                      -                               
 219    6        1000    -  HIDSL latest              XX.Y.Z.80                      -        ✓        ✗  Musterstraße 42, 123456 Irgendwo                      -                               
 330    7        1000  399  HIDSL latest             XX.Y.Z.182                      -        ✗        ✗  Musterstraße 42, 123456 Irgendwo                      -                               
 508    8        1000    -  HIDSL latest             XX.Y.Z.189                      -        ✗        ✗  N/A                                                   -                       
 


评论

我个人不喜欢这里的最终案例。如果我输入“-”,“✓”或“✗”怎么办?返回的值将是不明确的。或者,您可以指定您不接受文档字符串中的字符串或键入合同。

@LukeSawczak如果对象可能是字符串,则在将对象转换为字符串时始终会有歧义。您的示例也适用于[]→“ []”和“ []”→“ []”等。

-除非您发现了这种情况并为其定义了行为:)

@LukeSawczak在我的用例中,我不介意这种歧义。

最好的答案是您的问题。我在下面看不到任何改进。

#1 楼

由于代码段非常小,并且缺少其他上下文,因此很难确定在代码其他地方可能出现的扩展问题。因此,如果您想要一个更合适的答案,则应添加更多代码。

是的,这很好。这样只会增加额外的缩进级别而没有理由。

#2 楼

我个人会使用字典,因为它们几乎是标准的switch语句。
如果您仅使用仅以True作为键的普通字典,那么它对于'✓'True
因此您可以创建一个字典,键为值和类型的元组。您想:

_stringify_values = {
    (type(None), None): '-',
    (bool, True): '✓',
    (bool, False): '✗'
}

def stringify(value):
    try:
        return _stringify_values[(type(value), value)]
    except (KeyError, TypeError):
        return str(value)



如果您打算大量使用它,也可以制作一个简单的类来包含所有特殊逻辑。通过使用1

_stringify_values = {
    None: '-',
    True: '✓',
    False: '✗'
}
_stringify_values = {(type(k), k): v for k, v in _stringify_values.items()}


评论


\ $ \ begingroup \ $
这是在过度设计的解决方案中查找不存在的问题。
\ $ \ endgroup \ $
–将
18年7月20日在1:32

\ $ \ begingroup \ $
除了一般的过度设计之外,为什么在世界上您会捕获KeyError而不是使用return _stringify_values.get((type(value),value),str(value))
\ $ \ endgroup \ $
–约翰内斯·皮尔(Johannes Pille)
18年7月20日在6:35

\ $ \ begingroup \ $
@JohannesPille因为在密钥无法散列时已经需要捕获TypeError;因此无需使行的可读性降低。
\ $ \ endgroup \ $
–301_Moved_Permanently
18年7月20日在7:11

\ $ \ begingroup \ $
@Will我不认为使用字典会导致尝试过度。该类是,这就是为什么我给它加上“如果您打算大量使用它”的原因。
\ $ \ endgroup \ $
– Peilonrayz
18年7月20日在9:02

#3 楼

即使return如果一个匹配项都缩短了链的长度,我还是更喜欢在这里使用elif链,因为它更明显,但是YMMV(尤其是自动短绒):
br />除此之外,没有真正的选择,因为所有其他方法都将因0False之间的差异而失败,而这只能通过is或不可散列的类型(例如list)才能获得。

我看到的唯一另一种可能性是在转换为True, False, None后替换str的值,不使用str.translate,但是这将无法区分None"None"

评论


\ $ \ begingroup \ $
实际上,由于pylint发出的噪音,我实际上摆脱了小精灵。
\ $ \ endgroup \ $
–理查德·诺伊曼(Richard Neumann)
18年7月19日在11:56

\ $ \ begingroup \ $
就是这样一种情况:告诉短绒小动物安静,而不是修改您的代码以使其安逸。
\ $ \ endgroup \ $
–chepner
18年7月19日在15:38

\ $ \ begingroup \ $
pylint的默认设置很糟糕。
\ $ \ endgroup \ $
– user2357112支持Monica
18年7月19日在19:32

\ $ \ begingroup \ $
IMO使用elif实际上会使代码更糟,因为它意味着可到达的else分支。引入这样的重言式并不能使我澄清任何事情:每次我阅读带有冗余语句的代码时,都会对那些写有清楚自己的控制流思维模型的人失去一点信心。代码可能“太聪明”,但有时也可能...太笨了?
\ $ \ endgroup \ $
–将
18年7月20日在1:22

\ $ \ begingroup \ $
@如我所说,YMMV。我通常同意您的意见,但在这里我喜欢它,因为一眼就可以看出案件是互斥的。对于原始的if链,这对我来说不那么明显。
\ $ \ endgroup \ $
–地狱
18年7月20日在6:01

#4 楼

我可能会使用嵌套的条件表达式,这些条件表达式可以很干净地格式化:匹配的情况。

评论


\ $ \ begingroup \ $
-1表示内联条件,而+2表示“对于少量硬编码的检查,可读性胜于线性搜索以找到匹配的大小写。”完全同意。
\ $ \ endgroup \ $
– Quelklef
18年7月19日在16:53

#5 楼

关于函数名称和文档字符串的说明:

def stringify(value):
   """Returns the string representation of the value."""






stringify:什么值?它必须是数字值吗?任何类型的值,但没有对象?变量名并不能完全清楚显示该变量名。


返回该值的字符串表示形式。因为阅读后我不知道...


允许使用哪些值?有限制吗?
定义值的“字符串表示形式”的原因是什么?仅to_string就有很多可能的表示形式。从value到完整序列化,嵌套结构,对象等也可以具有许多可能的表示形式。有什么区别?
某些数据类型是否有特殊处理?我不知道您对float的表示形式将是一个Unicode字符,而不是[object]strunicode,它们将遵循最少的原则。默认处理其他所有内容。如果输入不是布尔值,则可能为True并引发"True"

#6 楼

要消除由'-''[1, 2]'之类的输入引起的歧义,我建议将str(value)调用替换为repr(value)调用。

如果您希望将其扩展到线性搜索可能导致不必要的延迟的地步,您可以将需要使用以下单例中的id来避免在将不可散列的类型进行字符串化时出现问题:

try:
    # Using the id() of singletons to support unhashable types
    return appropriately_named_lookup_table[id(value)]
except KeyError:
    return repr(value)


如果最终这样做,请确保对此进行记录,并记住尽管它似乎适用于整数in range(-5, 256),但这仅是CPython实现的细节。

评论


\ $ \ begingroup \ $
+1代表repr,但是对于“用户”来说,代码似乎比“开发者”更有用
\ $ \ endgroup \ $
–吉列什·乔汉(Grijesh Chauhan)
18年7月20日在6:47

\ $ \ begingroup \ $
OP表示模棱两可是不可避免的。
\ $ \ endgroup \ $
– wizzwizz4
18年7月20日在6:50

\ $ \ begingroup \ $
正如我在上面评论的那样,模棱两可根本不是问题。相反,我不希望'使我的弦泛滥。
\ $ \ endgroup \ $
–理查德·诺伊曼(Richard Neumann)
18年7月20日在13:00

\ $ \ begingroup \ $
您可以使用defaultdict而不是捕获异常。
\ $ \ endgroup \ $
– allo
18年7月23日在7:33

\ $ \ begingroup \ $
@allo真的吗?我不知道该支持传递参数!但是不,因为它必须使用从id强制转换的ctypes,它恰好是CPython中的地址,但不是必需的。
\ $ \ endgroup \ $
– wizzwizz4
18年7月23日在21:47