如何在Python中打破一系列链式方法?

Jul*_*era 126 python coding-style pep8

我有一行以下代码(不要责怪命名约定,它们不是我的):

subkeyword = Session.query(
    Subkeyword.subkeyword_id, Subkeyword.subkeyword_word
).filter_by(
    subkeyword_company_id=self.e_company_id
).filter_by(
    subkeyword_word=subkeyword_word
).filter_by(
    subkeyword_active=True
).one()
Run Code Online (Sandbox Code Playgroud)

我不喜欢它的样子(不要太可读),但我没有任何更好的主意来限制这种情况下,行79个字符.是否有更好的方法来打破它(最好没有反斜杠)?

sth*_*sth 235

您可以使用其他括号:

subkeyword = (
        Session.query(Subkeyword.subkeyword_id, Subkeyword.subkeyword_word)
        .filter_by(subkeyword_company_id=self.e_company_id)
        .filter_by(subkeyword_word=subkeyword_word)
        .filter_by(subkeyword_active=True)
        .one()
    )
Run Code Online (Sandbox Code Playgroud)

  • 不确定这里额外缩进的理由是什么; 我认为这个解决方案读起来也是如此,悬挂线只缩进一次而后面的凹槽根本没有. (22认同)
  • 在我看来,双缩进在这里是有用的,因为它在视觉上与正常的缩进块不同.当被其他代码包围时,这更加明显,它是一个包裹的单行. (4认同)

Ray*_*ger 53

这种情况下,行连续字符优先打开括号.当方法名称变得更长并且方法开始采用参数时,对这种风格的需求变得更加明显:

subkeyword = Session.query(Subkeyword.subkeyword_id, Subkeyword.subkeyword_word) \
                    .filter_by(subkeyword_company_id=self.e_company_id)          \
                    .filter_by(subkeyword_word=subkeyword_word)                  \
                    .filter_by(subkeyword_active=True)                           \
                    .one()
Run Code Online (Sandbox Code Playgroud)

PEP 8旨在通过常识和对实用和美丽的关注来解释.高兴地违反任何导致丑陋或难以阅读的代码的PEP 8指南.

话虽这么说,如果你经常发现自己与PEP 8不一致,这可能表明存在超出你选择的空白的可读性问题:-)

  • 我没有看到这个解决方案如何能够更好地应对"因为方法名称变得越来越长,并且方法开始采用参数",而不是"在外部包裹中"或"在每个开放式paren之后和每个关闭之前的线路中断"解决方案.实际上它在处理这个问题时更糟糕,因为(至少如此处所示)它需要对每个悬挂线进行更深的缩进. (10认同)
  • 过滤器调用的缩进太多。这里 1 个制表符或 4 个空格就足够了。还有“\”的对齐...您按住空格键多少秒?一般来说,我反对所有需要你敲击空格键的方式,就像没有明天一样。 (3认同)
  • 对 PEP8 的很好的参考!对齐所有“.filter”调用的一个恼人的问题是,如果您将“subkeyword”更改为“sub_keyword”,您现在必须修复**每一行**的缩进,只是因为您更改了变量名称。当风格实际上阻碍了可维护性时就不好了...... (3认同)
  • 反斜杠上的+1并在此特定情况下对齐链接过滤器.这种情况也出现在Django中,并且这种方式最具可读性 - 但在其他任何情况下,我觉得括号内的短语都是优越的(不要遭受"我的反斜杠之后是否有空格?"问题).也就是说,用短语括起来可以用来达到同样的效果 - 但它会让你在阅读Python的过程中进入Lisp阅读模式,我觉得这很困难. (2认同)
  • 后来,PEP8读到“包裹长行的首选方法是在括号,方括号和花括号内使用Python的隐含行连续。通过将表达式包装在括号中,可以将长行折断成多行。应优先使用反斜杠。行继续。” — [Python.org](https://www.python.org/dev/peps/pep-0008/#indentation)继续讨论何时反斜杠可能合适 (2认同)

pko*_*och 15

我个人的选择是:

subkeyword = Session.query(
    Subkeyword.subkeyword_id,
    Subkeyword.subkeyword_word,
).filter_by(
    subkeyword_company_id=self.e_company_id,
    subkeyword_word=subkeyword_word,
    subkeyword_active=True,
).one()

  • 我同意如果有多个参数被传入,但当 0 或 1 个参数很常见时,它看起来很难看。例如:https://gist.github.com/andybak/b23b6ad9a68c7e1b794d (2认同)
  • 是的,这种风格有退化的情况(就像任何风格一样)。我不会打破所有开放的括号。这些都不让我高兴,但这里有一些案例:https://gist.github.com/pkoch/8098c76614765750f769 (2认同)

Ivo*_*ijk 12

只需存储中间结果/对象并在其上调用下一个方法,例如

q = Session.query(Subkeyword.subkeyword_id, Subkeyword.subkeyword_word)
q = q.filter_by(subkeyword_company_id=self.e_company_id)
q = q.filter_by(subkeyword_word=subkeyword_word)
q = q.filter_by(subkeyword_active=True)
subkeyword = q.one()
Run Code Online (Sandbox Code Playgroud)

  • 这适用于像查询这样的东西,但作为一般模式,我不太确定.例如,当链接在Beautiful Soup中时,例如`team_members = soup.find(class _ ='section team').find_all('ul').find_all('li')`,每个`.find的返回值(.. .)`call不符合`team_members`的含义. (9认同)
  • @TaylorEdmiston 当然,您可以为部分结果使用不同的名称。类似 `section = soup.find(class_='section team')` 和 `team_members = section.find_all('ul').find_all('li')` 之类的东西。 (2认同)

Árn*_*son 5

它与其他人提供的解决方案略有不同,但却是我的最爱,因为它有时会导致漂亮的元编程。

base = [Subkeyword.subkeyword_id, Subkeyword_word]
search = {
    'subkeyword_company_id':self.e_company_id,
    'subkeyword_word':subkeyword_word,
    'subkeyword_active':True,
    }
subkeyword = Session.query(*base).filter_by(**search).one()
Run Code Online (Sandbox Code Playgroud)

这是构建搜索的好方法。遍历一个条件列表,从复杂的查询表单中挖掘(或基于字符串的关于用户正在查找的内容的推断),然后将字典分解到过滤器中。

  • 很好的解决方案。️ 虽然没有明确回答这个问题,但它揭示了程序员有时如何尝试解决他们不需要的_痛苦_和问题(此处:不可读的过滤器链)。这种“痛苦”是更深层次原因的症状信号(通常是概念上、结构上、设计问题,甚至命名问题)。例如,您的字典“search”具有“谓词”或“匹配器”的有意义的目的,概念上类似于[QBE](https://en.wikipedia.org/wiki/Query_by_Example#As_a_general_technique):它匹配所有属性),就像SQL“哪里..和..”。 (2认同)