我们正在尝试遵循PEP8格式化我们的Python代码并保持每行低于80个字符的指导原则。格式化SQLAlchemy代码
我们的SQLAlchemy行特别麻烦,有大量的链接方法和大量的复杂参数,逻辑和嵌套函数。
是否有任何特定的最佳实践来格式化Python SQLAlchemy的约束PEP8?
我发现的最接近的答案是here,但我所处理的代码远远更复杂。
我们正在尝试遵循PEP8格式化我们的Python代码并保持每行低于80个字符的指导原则。格式化SQLAlchemy代码
我们的SQLAlchemy行特别麻烦,有大量的链接方法和大量的复杂参数,逻辑和嵌套函数。
是否有任何特定的最佳实践来格式化Python SQLAlchemy的约束PEP8?
我发现的最接近的答案是here,但我所处理的代码远远更复杂。
pep-8不鼓励反斜杠,但对于SQLAlchemy代码,我不禁想到它们是最可读的,因为您可以将每个生成函数保留在自己的行的开头。如果括号内有很多参数,我会在个别行上分解它们。
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()
当然不要紧代码是如何复杂的是它,压痕模式可以为任何代码量进行下去,但是在Python我们要避免过多的嵌套。通常在使用Query时,会发生嵌套,因为您正在组合许多子查询。因此,绝对提前构建子查询:
subq = Session.query(
Bat.id,
func.foo(Bat.x, Bat.y).label('foo')
).\
filter(Bat.id==Bar.name).\
correlate(Bar).\
subquery()
subq2 = Session.query(Foo.id, Foo.bar).\
filter_by(flag>5).\
subquery()
result = Session.query(
subq.c.id,
subq.c.foo,
subq2.c.bar
).\
join(subq2,
and_(
subq.c.id > subq2.c.foo,
subq.bar == subq2.id
)
).\
order_by(subq.c.id, subq2.c.bar)
我会欢迎其他意见反斜杠的事情。
是的,无论你做什么,这些都会变得很讨厌,所以如果你能把这些结构分成更短的行,那肯定是这样。
当你不能的时候,你可以通过把整个RHS放在一个圆括号中去掉所有的反斜杠。然后,Python将正确地解析多行构造,而不用反斜杠,但也很难说这是否更好。在这样的情况下,我认为你只需要用你最好的判断,抓住你的鼻子并投入。
pep8有关反斜杠的说明的机会是什么(字面上,“这些应该优先使用反斜杠换行“)是唯一提及的)?如果他们不鼓励,为什么Python甚至拥有它们? – zzzeek 2012-02-28 19:45:50
我是类似于zzzeek在他的回答中指出的反斜杠的用户。 PEP8只是一个指导方针,当你违犯它时不要失眠!
不过,我也经常使用以下格式,在那里我已经偷zzzeek的第一个例子中的类型,轻度调整了它,并重新格式化:
q = Session.query(
Subkeyword.subkeyword_id,
Subkeyword.subkeyword_word,
)
q = q.filter_by(subkeyword_company_id=self.e_company_id) # first filter
q = q.filter_by(subkeyword_word=subkeyword_word) # 2nd filter
q = q.filter_by(subkeyword_active=True)
if filter_by_foo:
q = q.filter(Subkeyword.foo == True)
# Run the query (I usually wrap in a try block)...
subkeyword = q.one()
反复重新分配到q起初似乎有点讨厌,但我已经完成了。性能影响实际上是零。这种方式的一大优势是,您可以在尾部注释和注释行中混合使用,以记录您的查询(正如我对上面的无用添加所做的那样)。用反斜杠链接线限制你在这里。
格式的这种方式与逻辑触发修改吨,嵌入式标量选择等
作为另一示例配制大量查询时,特别干净,我有一个相当大(> 150线)CTE查询我在SQLAlchemy中生成的混合逻辑,别名和标签(这对生成的查询的可读性来说非常重要)混合了这两种方法。它的一个严重降低(血肉模糊)版本开始像下面的东西:
cte_init = session.\
query(
child1.foo.label("child1_foo"),
sa.literal(1).label("indent"), # can comment on non-slashed lines
child2.bar.label("child2bar"),
#comments between non-slashed lines ok, too
sa.func.MAX(toplevel.baz).label("max_baz"),
).\
select_from(top_level).\
join(child1,
child1.id == toplevel.fk_child1_id).\
join(child2.
child2.id == toplevel.fk_child2.id).\
filter(top_level.name == "bogus").\
cte(name = "cte", recursive = True)
if(use_filter_x):
cte_init = cte_init.filter_by(x = "whatever")
# etc (no, the above doesn't make any sense)...
在一般情况下,如果要确保新业务(如许多常见的SQL格式方案做)带领你行了,它保持很可读。不要害怕括号内的换行符。
这也带来了额外的好处,它使得'pdb' a * lot *更容易调试!因为每个过滤器都有自己的声明! – exhuma 2014-02-24 10:20:47
来到这里,希望有一个更好的解决方案,但我想我更喜欢括号环绕方式:
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()
)
这是很好的和明确的,并且避免了可怕的反斜杠。
pocoo团队风格指南中很好的反斜杠用法http://www.pocoo.org/internal/styleguide/ – estin 2012-02-28 12:04:59