【问题标题】:How to cleanly keep below 80-char width with long strings?如何用长字符串干净地保持低于 80 字符的宽度?
【发布时间】:2013-03-17 20:15:23
【问题描述】:

我现在正试图将我的代码保持在 80 个字符或更少,因为我认为它在大多数情况下看起来更美观。但是,有时,如果我不得不在奇怪的地方放置换行符,代码最终会看起来更糟。

我还没有弄清楚如何很好地处理的一件事是长字符串。例如:

#0.........1........2........3........4.........5.........6.........7.........8xxxxxxxxx9xxxxxx
def foo():
    if conditional():
        logger.info("<Conditional's meaning> happened, so we're not setting up the interface.")
        return

    #.....

结束了!把它放在下一行也无济于事:

#0.........1........2........3........4.........5.........6.........7.........8xxxxxxxxx9xxxxxx
def foo():
    if conditional():
        logger.info(
            "<Conditional's meaning> happened, so we're not setting up the interface.")
        return

    #.....

我可以使用换行符,但这看起来很糟糕:

#0.........1........2........3........4.........5.........6.........7.........8
def foo():
    if conditional():
        logger.info(
            "<Conditional's meaning> happened, so we're not setting \
up the interface.")
        return

    #.....

怎么办?缩短字符串是一种选择,但我不希望我的消息的可读性受到代码当时恰好有多少缩进级别这样的任意因素的影响。

【问题讨论】:

    标签: python coding-style readability code-readability


    【解决方案1】:

    你可以把字符串一分为二:

    def foo():
        if conditional():
            logger.info("<Conditional's meaning> happened, so we're not "
                        "setting up the interface.")
    

    同一表达式中的多个连续字符串自动为concatenated into one, at compile time

    >>> def foo():
    ...     if conditional():
    ...         logger.info("<Conditional's meaning> happened, so we're not "
    ...                     "setting up the interface.")
    ... 
    >>> import dis
    >>> dis.dis(foo)
      2           0 LOAD_GLOBAL              0 (conditional)
                  3 CALL_FUNCTION            0
                  6 POP_JUMP_IF_FALSE       25
    
      3           9 LOAD_GLOBAL              1 (logger)
                 12 LOAD_ATTR                2 (info)
                 15 LOAD_CONST               1 ("<Conditional's meaning> happened, so we're not setting up the interface.")
                 18 CALL_FUNCTION            1
                 21 POP_TOP             
                 22 JUMP_FORWARD             0 (to 25)
            >>   25 LOAD_CONST               0 (None)
                 28 RETURN_VALUE        
    

    注意第 3 行的 LOAD_CONST,函数的字节码包含 一个 字符串,已连接。

    如果您要在表达式中添加 +,则会创建两个单独的常量:

    >>> def foo():
    ...     if conditional():
    ...         logger.info("<Conditional's meaning> happened, so we're not " + 
    ...                     "setting up the interface.")
    ... 
    >>> dis.dis(foo)
      2           0 LOAD_GLOBAL              0 (conditional)
                  3 CALL_FUNCTION            0
                  6 POP_JUMP_IF_FALSE       29
    
      3           9 LOAD_GLOBAL              1 (logger)
                 12 LOAD_ATTR                2 (info)
                 15 LOAD_CONST               1 ("<Conditional's meaning> happened, so we're not ")
    
      4          18 LOAD_CONST               2 ('setting up the interface.')
                 21 BINARY_ADD          
                 22 CALL_FUNCTION            1
                 25 POP_TOP             
                 26 JUMP_FORWARD             0 (to 29)
            >>   29 LOAD_CONST               0 (None)
                 32 RETURN_VALUE        
    

    在字节编译器的窥视孔优化中,Python 确实在编译时对常量进行了折叠二进制操作(如 +*- 等)。因此,对于某些字符串连接,编译器可能也将+ 常量字符串连接替换为连接结果。请参阅peephole.c,对于序列(包括字符串),仅当结果限制为 20 个项目(字符)或更少时才会应用此优化。

    【讨论】:

    • @nightcracker:编译器合并字符串。使用+,您可以将串联移动到运行时。
    • @nightcracker:添加了证据。对不起,但你错了。 +两个 字符串常量,它们是在运行时添加的。
    • @MartijnPieters 反证:gist.github.com/nightcracker/5255760 他们同样快。
    • @nightcracker:似乎对于 some 字符串,编译器优化了字符串连接。对于 this 情况,编译时连接不会发生。我在你的要点中添加了一个反例。
    • @MartijnPieters 啊好的。无论哪种方式,性能参数都与 IMO 无关——除非我们在这里谈论性能瓶颈。但我强烈怀疑这个记录器条目是性能瓶颈。
    猜你喜欢
    • 1970-01-01
    • 2014-05-06
    • 2011-06-15
    • 2017-06-13
    • 2017-11-04
    • 1970-01-01
    • 1970-01-01
    • 2018-12-21
    • 1970-01-01
    相关资源
    最近更新 更多