【问题标题】:What is the proper level of indent for hanging indent with type hinting in python?在 python 中使用类型提示挂起缩进的适当缩进级别是多少?
【发布时间】:2017-01-20 07:43:24
【问题描述】:

对于具有多个参数和类型提示的方法,悬挂缩进的正确语法是什么?

在第一个参数下对齐

def get_library_book(self,
                     book_id: str,
                     library_id: str
                     )-> Book:

缩进一层

def get_library_book(
    self, 
    book_id: str, 
    library_id: str
) -> Book:

PEP8 支持 Indent one level below 的情况,但没有指定是否允许 Align under first parameter。它指出:

使用悬挂缩进时,应考虑以下事项;那里 第一行和进一步缩进应该没有参数 应该用来明确区分自己作为续行。

【问题讨论】:

    标签: python python-3.x pep8 type-hinting


    【解决方案1】:

    PEP8 有很多好主意,但我不会依赖它来决定这类关于空格的问题。当我研究 PEP8 关于空白的建议时,我发现它们前后矛盾,甚至自相矛盾。

    相反,我会研究适用于几乎所有编程语言的一般原则,而不仅仅是 Python。

    第一个示例中显示的列对齐有很多缺点,我在任何项目中都没有使用或允许它。

    一些缺点:

    • 如果更改函数名称使其长度不同,则必须重新对齐所有参数。
    • 当您进行重新调整时,您的源代码管理差异会因不必要的空白更改而变得混乱。
    • 随着代码的更新和维护,您可能会在重命名变量时错过一些对齐,从而导致代码错位。
    • 您可以获得更长的行长。
    • 对齐在比例字体中不起作用。 (是的,一些开发人员更喜欢比例字体,如果您避免列对齐,您的代码在等宽字体或比例字体中同样具有可读性。)

    如果在更复杂的情况下使用列对齐,情况会变得更糟。考虑这个例子:

    let mut rewrites = try_opt!(subexpr_list.iter()
                                            .rev()
                                            .map(|e| {
                                                rewrite_chain_expr(e,
                                                                   total_span,
                                                                   context,
                                                                   max_width,
                                                                   indent)
                                            })
                                            .collect::<Option<Vec<_>>>());
    

    这是来自 Servo 浏览器的 Rust 代码,其编码风格要求这种列对齐。虽然它不是 Python 代码,但完全相同的原则适用于 Python 或几乎任何语言。

    在此代码示例中应该很明显,使用列对齐会导致糟糕的情况。如果您需要在嵌套的rewrite_chain_expr 调用中调用另一个函数或具有更长的变量名怎么办?除非您想要非常长队,否则您几乎没有空间了。

    将上述内容与使用纯缩进样式的这些版本中的任何一个进行比较,例如您的第二个 Python 示例:

    let mut rewrites = try_opt!(
        subexpr_list
            .iter()
            .rev()
            .map( |e| {
                rewrite_chain_expr( e, total_span, context, max_width, indent )
            })
            .collect::<Option<Vec<_>>>()
    );
    

    或者,如果rewrite_chain_expr 的参数更长,或者您只是想要更短的行:

    let mut rewrites = try_opt!(
        subexpr_list
            .iter()
            .rev()
            .map( |e| {
                rewrite_chain_expr(
                    e,
                    total_span,
                    context,
                    max_width,
                    indent
                )
            })
            .collect::<Option<Vec<_>>>()
    );
    

    与列对齐样式相比,这种纯缩进样式有很多优点,完全没有缺点。

    【讨论】:

    • 我同意你所说的一切。谁认为可变缩进一开始是个好主意?是否有胜过此答案中列出的 [重] 缺点的优点?我看不见它们;我很好奇其他人是否可以。
    【解决方案2】:

    Appart from Terrys answer,以typeshed 为例,这是 Python 的 GitHub 上用于使用存根注释 stdlib 的项目。

    例如,在importlib.machinery(以及在其他情况下,如果您查看)注释是使用您的第一个表单完成的,for example

    def find_module(cls, fullname: str,
                    path: Optional[Sequence[importlib.abc._Path]]
                   ) -> Optional[importlib.abc.Loader]:
    

    【讨论】:

      【解决方案3】:

      仔细阅读PEP 8的上一行,“或使用悬挂缩进”之前的部分。

      连续行应该使用 Python 的隐式行在括号、方括号和大括号内连接,或者使用悬挂缩进垂直对齐被包裹的元素。

      这旨在涵盖第一个“是”示例,以及您上面的第一个示例。

      # Aligned with opening delimiter.
      foo = long_function_name(var_one, var_two,
                               var_three, var_four)
      

      【讨论】:

        猜你喜欢
        • 2019-08-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-24
        • 1970-01-01
        • 1970-01-01
        • 2010-12-15
        • 1970-01-01
        相关资源
        最近更新 更多