标签归档:pep8

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

问题:如何在Python中打破一系列链接方法?

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

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()

我不喜欢它的外观(不太可读),但是在这种情况下,我没有更好的主意将行数限制为79个字符。有没有更好的方法来破解它(最好没有反斜杠)?

I have a line of the following code (don’t blame for naming conventions, they are not mine):

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()

I don’t like how it looks like (not too readable) but I don’t have any better idea to limit lines to 79 characters in this situation. Is there a better way of breaking it (preferably without backslashes)?


回答 0

您可以使用其他括号:

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()
    )

You could use additional parenthesis:

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()
    )

回答 1

在这种情况下,最好使用连续行字符代替括号。随着方法名称变长以及方法开始采用参数,对这种样式的需求变得更加明显:

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()

PEP 8旨在以一种常识的方式进行解释,并兼顾实用性和美观性。很高兴违反任何导致难看或难以阅读代码的PEP 8准则。

话虽如此,如果您经常发现自己与PEP 8不符,则可能表明存在一些可读性问题超出了对空白的选择:-)

This is a case where a line continuation character is preferred to open parentheses. The need for this style becomes more obvious as method names get longer and as methods start taking arguments:

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()

PEP 8 is intend to be interpreted with a measure of common-sense and an eye for both the practical and the beautiful. Happily violate any PEP 8 guideline that results in ugly or hard to read code.

That being said, if you frequently find yourself at odds with PEP 8, it may be a sign that there are readability issues that transcend your choice of whitespace :-)


回答 2

我个人的选择是:

子关键字= Session.query(
    Subkeyword.subkeyword_id,
    Subkeyword.subkeyword_word,
)。过滤(
    subkeyword_company_id = self.e_company_id,
    subkeyword_word = subkeyword_word,
    subkeyword_active =真实,
)。之一()

My personal choice would be:

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()

回答 3

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

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()

Just store the intermediate result/object and invoke the next method on it, e.g.

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()

回答 4

根据Python语言参考,
您可以使用反斜杠。
或简单地打破它。如果括号未配对,则python不会将其视为一行。在这种情况下,以下行的缩进无关紧要。

According to Python Language Reference
You can use a backslash.
Or simply break it. If a bracket is not paired, python will not treat that as a line. And under such circumstance, the indentation of following lines doesn’t matter.


回答 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()

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

It’s a bit of a different solution than provided by others but a favorite of mine since it leads to nifty metaprogramming sometimes.

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()

This is a nice technique for building searches. Go through a list of conditionals to mine from your complex query form (or string-based deductions about what the user is looking for), then just explode the dictionary into the filter.


回答 6

您似乎在使用SQLAlchemy,如果为true,则sqlalchemy.orm.query.Query.filter_by()方法采用多个关键字参数,因此您可以这样编写:

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()

但这会更好:

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

You seems using SQLAlchemy, if it is true, sqlalchemy.orm.query.Query.filter_by() method takes multiple keyword arguments, so you could write like:

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()

But it would be better:

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

回答 7

我喜欢将参数缩进两个块,将语句缩进一个块,如下所示:

for image_pathname in image_directory.iterdir():
    image = cv2.imread(str(image_pathname))
    input_image = np.resize(
            image, (height, width, 3)
        ).transpose((2,0,1)).reshape(1, 3, height, width)
    net.forward_all(data=input_image)
    segmentation_index = net.blobs[
            'argmax'
        ].data.squeeze().transpose(1,2,0).astype(np.uint8)
    segmentation = np.empty(segmentation_index.shape, dtype=np.uint8)
    cv2.LUT(segmentation_index, label_colours, segmentation)
    prediction_pathname = prediction_directory / image_pathname.name
    cv2.imwrite(str(prediction_pathname), segmentation)

I like to indent the arguments by two blocks, and the statement by one block, like these:

for image_pathname in image_directory.iterdir():
    image = cv2.imread(str(image_pathname))
    input_image = np.resize(
            image, (height, width, 3)
        ).transpose((2,0,1)).reshape(1, 3, height, width)
    net.forward_all(data=input_image)
    segmentation_index = net.blobs[
            'argmax'
        ].data.squeeze().transpose(1,2,0).astype(np.uint8)
    segmentation = np.empty(segmentation_index.shape, dtype=np.uint8)
    cv2.LUT(segmentation_index, label_colours, segmentation)
    prediction_pathname = prediction_directory / image_pathname.name
    cv2.imwrite(str(prediction_pathname), segmentation)

有多行导入的推荐格式吗?

问题:有多行导入的推荐格式吗?

我已经阅读了在python中编码多行导入的三种方法

带斜杠:

from Tkinter import Tk, Frame, Button, Entry, Canvas, Text, \
    LEFT, DISABLED, NORMAL, RIDGE, END

复制语句:

from Tkinter import Tk, Frame, Button, Entry, Canvas, Text
from Tkinter import LEFT, DISABLED, NORMAL, RIDGE, END

带括号:

from Tkinter import (Tk, Frame, Button, Entry, Canvas, Text,
    LEFT, DISABLED, NORMAL, RIDGE, END)

此语句是否有推荐的格式或更简洁的方法?

I have read there are three ways for coding multi-line imports in python

With slashes:

from Tkinter import Tk, Frame, Button, Entry, Canvas, Text, \
    LEFT, DISABLED, NORMAL, RIDGE, END

Duplicating senteces:

from Tkinter import Tk, Frame, Button, Entry, Canvas, Text
from Tkinter import LEFT, DISABLED, NORMAL, RIDGE, END

With parenthesis:

from Tkinter import (Tk, Frame, Button, Entry, Canvas, Text,
    LEFT, DISABLED, NORMAL, RIDGE, END)

Is there a recomended format or a more elegant way for this statements?


回答 0

就个人而言,导入多个组件并按字母顺序对它们进行括号处理。像这样:

from Tkinter import (
    Button,
    Canvas,
    DISABLED,
    END,
    Entry,
    Frame,
    LEFT,
    NORMAL,
    RIDGE,
    Text,
    Tk,
)

这具有额外的优势,即可以轻松查看每个提交或PR中已添加/删除了哪些组件。

总的来说,尽管这是个人喜好,但我建议您选择最适合自己的方式。

Personally I go with parentheses when importing more than one component and sort them alphabetically. Like so:

from Tkinter import (
    Button,
    Canvas,
    DISABLED,
    END,
    Entry,
    Frame,
    LEFT,
    NORMAL,
    RIDGE,
    Text,
    Tk,
)

This has the added advantage of easily seeing what components have been added / removed in each commit or PR.

Overall though it’s a personal preference and I would advise you to go with whatever looks best to you.


回答 1

您的示例似乎源于PEP 328。在那里,正是针对这个问题提出了括号符号,所以我可能会选择这个。

Your examples seem to stem from PEP 328. There, the parenthesis-notation is proposed for exactly this problem, so probably I’d choose this one.


回答 2

我将使用PEP328的括号符号,并在括号之前和之后添加换行符:

from Tkinter import (
    Tk, Frame, Button, Entry, Canvas, Text, 
    LEFT, DISABLED, NORMAL, RIDGE, END
)

这是Django使用的格式:

from django.test.client import Client, RequestFactory
from django.test.testcases import (
    LiveServerTestCase, SimpleTestCase, TestCase, TransactionTestCase,
    skipIfDBFeature, skipUnlessAnyDBFeature, skipUnlessDBFeature,
)
from django.test.utils import (
    ignore_warnings, modify_settings, override_settings,
    override_system_checks, tag,
)

I would go with the parenthesis notation from the PEP328 with newlines added before and after parentheses:

from Tkinter import (
    Tk, Frame, Button, Entry, Canvas, Text, 
    LEFT, DISABLED, NORMAL, RIDGE, END
)

This is the format which Django uses:

from django.test.client import Client, RequestFactory
from django.test.testcases import (
    LiveServerTestCase, SimpleTestCase, TestCase, TransactionTestCase,
    skipIfDBFeature, skipUnlessAnyDBFeature, skipUnlessDBFeature,
)
from django.test.utils import (
    ignore_warnings, modify_settings, override_settings,
    override_system_checks, tag,
)

回答 3

通常对于Tkinter,只使用from Tkinter import *模块就可以了,因为该模块只会导出明显是小部件的名称。

PEP 8没有列出这种情况下的任何约定,因此我想您应该决定什么是最佳选择。一切都与可读性有关,因此请选择任何可以使您清楚地表明要从单个模块导入内容的东西。

由于在您的范围内提供了所有这些名称,因此我个人认为选项2最清晰,因为您可以看到最佳的导入名称。然后,您甚至可以将其拆分成更多的部分,以将彼此属于的那些名称组合在一起。在您的示例中,我可能将和分开放置Tk,因为它们将小部件分组在一起,而将和分开放置则是它们在视图中较小的组件。FrameCanvasButtonText

Usually with Tkinter, it is okay to just use from Tkinter import * as the module will only export names that are clearly widgets.

PEP 8 does not list any conventions for such a case, so I guess it is up to you to decide what is the best option. It is all about readability, so choose whatever makes it clear that you are importing stuff from a single module.

As all those names are made available in your scope, I personally think that options 2 is the most clearest as you can see the imported names the best. You then could even split it up more to maybe group those names together that belong with each other. In your example I might put Tk, Frame and Canvas separately as they group widgets together, while having Button and Text separately as they are smaller components in a view.


将Python代码转换为符合PEP8的工具

问题:将Python代码转换为符合PEP8的工具

我知道有一些工具可以验证您的Python代码是否符合PEP8,例如,既有在线服务又有python模块

但是,我找不到可以我的Python文件转换为自包含的PEP8有效Python文件的服务或模块。有人知道是否有吗?
我认为这是可行的,因为PEP8完全是关于代码的外观,对吧?

I know there are tools which validate whether your Python code is compliant with PEP8, for example there is both an online service and a python module.

However, I cannot find a service or module which can convert my Python file to a self-contained, PEP8 valid Python file. Does anyone know if there are any?
I assume it’s feasible since PEP8 is all about the appearance of the code, right?


回答 0

不幸的是,“ pep8风暴”(整个项目)有几个负面影响:

  • 很多合并冲突
  • 打破git的责备
  • 使代码审查困难

作为替代方案(感谢@yp的想法),我编写了一个小程序包,该程序仅自动pepep8s自上次提交/分支以来一直在处理的那些行:

基本上使项目 比您发现的要好

pip install pep8radius

假设您已经完成工作master并准备提交:

# be somewhere in your project directory
# see the diff with pep, see the changes you've made since master
pep8radius master --diff
# make those changes
pep8radius master --diff --in-place

或者清除自上次提交以来已提交的新行:

pep8radius --diff
pep8radius --diff --in-place

# the lines which changed since a specific commit `git diff 98f51f`
pep8radius 98f51f --diff

基本上pep8radius是将autopep8应用于git / hg diff输出中的行(来自最后一个共享commit)。

该脚本当前可与git和hg一起使用,如果您使用其他方法并希望它起作用,请发表评论/问题/ PR

Unfortunately “pep8 storming” (the entire project) has several negative side-effects:

  • lots of merge-conflicts
  • break git blame
  • make code review difficult

As an alternative (and thanks to @y-p for the idea), I wrote a small package which autopep8s only those lines which you have been working on since the last commit/branch:

Basically leaving the project a little better than you found it:

pip install pep8radius

Suppose you’ve done your work off of master and are ready to commit:

# be somewhere in your project directory
# see the diff with pep, see the changes you've made since master
pep8radius master --diff
# make those changes
pep8radius master --diff --in-place

Or to clean the new lines you’ve commited since the last commit:

pep8radius --diff
pep8radius --diff --in-place

# the lines which changed since a specific commit `git diff 98f51f`
pep8radius 98f51f --diff

Basically pep8radius is applying autopep8 to lines in the output of git/hg diff (from the last shared commit).

This script currently works with git and hg, if your using something else and want this to work please post a comment/issue/PR!


回答 1

您可以使用autopep8!在您自己泡杯咖啡的同时,该工具会愉快地删除所有那些不会改变代码含义的讨厌的PEP8违规行为。

通过pip安装它:

pip install autopep8

将此应用到特定文件:

autopep8 py_file --in-place

或对您的项目(递归地),verbose选项为您提供了一些进展的反馈

autopep8 project_dir --recursive --in-place --pep8-passes 2000 --verbose

注意:有时默认的100次通过还不够,我将其设置为2000,因为它相当高,它将捕获除最麻烦的文件以外的所有文件(一旦发现没有可解决的pep8违规行为,它将停止通过)…

此时,我建议重新测试并进行提交!

如果要“完全”符合PEP8:我使用的一种策略是如上所述运行autopep8,然后运行PEP8,它会打印其余的违规行为(文件,行号以及其他内容):

pep8 project_dir --ignore=E501

并手动更改它们(例如E712s-与布尔值比较)。

注意:autopep8提供了一个--aggressive参数(以无情地“修复”这些改变含义的违规行为),但是请注意,如果您确实使用激进的方法,则可能必须调试…(例如,在numpy / pandas中,True == np.bool_(True)但不能True is np.bool_(True)!)

您可以检查每种类型(前后)有多少次违规:

pep8 --quiet --statistics .

注意:我认为E501(行太长)是一种特殊情况,因为您的代码中可能会有很多这样的代码,有时autopep8无法纠正这些代码。

例如,我将此技术应用于了熊猫代码库。

You can use autopep8! Whilst you make yourself a cup of coffee this tool happily removes all those pesky PEP8 violations which don’t change the meaning of the code.

Install it via pip:

pip install autopep8

Apply this to a specific file:

autopep8 py_file --in-place

or to your project (recursively), the verbose option gives you some feedback of how it’s going:

autopep8 project_dir --recursive --in-place --pep8-passes 2000 --verbose

Note: Sometimes the default of 100 passes isn’t enough, I set it to 2000 as it’s reasonably high and will catch all but the most troublesome files (it stops passing once it finds no resolvable pep8 infractions)…

At this point I suggest retesting and doing a commit!

If you want “full” PEP8 compliance: one tactic I’ve used is to run autopep8 as above, then run PEP8, which prints the remaining violations (file, line number, and what):

pep8 project_dir --ignore=E501

and manually change these individually (e.g. E712s – comparison with boolean).

Note: autopep8 offers an --aggressive argument (to ruthlessly “fix” these meaning-changing violations), but beware if you do use aggressive you may have to debug… (e.g. in numpy/pandas True == np.bool_(True) but not True is np.bool_(True)!)

You can check how many violations of each type (before and after):

pep8 --quiet --statistics .

Note: I consider E501s (line too long) are a special case as there will probably be a lot of these in your code and sometimes these are not corrected by autopep8.

As an example, I applied this technique to the pandas code base.


回答 2

@Andy Hayden很好地概述了autopep8。除此之外,还有一个名为pep8ify的软件包,它也可以执行相同的操作。

但是,这两个软件包都只能消除棉绒错误,但不能格式化代码。

little = more[3:   5]

上面的代码在经过pep8化后仍然保持不变。但是代码看起来还不太好。您可以使用诸如yapf之类的格式化程序,即使代码是PEP8兼容的,也可以格式化代码。上面的代码将被格式化为

little = more[3:5]

有时这甚至会破坏您的手动格式。例如

BAZ = {
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12]
}

将被转换为

BAZ = {[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]}

但是您可以告诉它忽略某些部分。

BAZ = {
   [1, 2, 3, 4],
   [5, 6, 7, 8],
   [9, 10, 11, 12]
}  # yapf: disable

取自我的旧博客文章:自动PEP8和格式化Python代码!

@Andy Hayden gave good overview of autopep8. In addition to that there is one more package called pep8ify which also does the same thing.

However both packages can remove only lint errors but they cannot format code.

little = more[3:   5]

Above code remains same after pep8ifying also. But the code doesn’t look good yet. You can use formatters like yapf, which will format the code even if the code is PEP8 compliant. Above code will be formatted to

little = more[3:5]

Some times this even destroys Your manual formatting. For example

BAZ = {
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12]
}

will be converted to

BAZ = {[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]}

But You can tell it to ignore some parts.

BAZ = {
   [1, 2, 3, 4],
   [5, 6, 7, 8],
   [9, 10, 11, 12]
}  # yapf: disable

Taken from my old blog post: Automatically PEP8 & Format Your Python Code!


回答 3

如果您使用的是eclipse + PyDev,则只需从PyDev的设置中激活autopep8:Windows-> Preferences->在搜索过滤器中键入’autopep8’。

选中“使用autopep8.py进行代码格式化?” ->好

现在,eclipse的CTRL-SHIFT-F代码格式应该使用autopep8来格式化代码:)

If you’re using eclipse + PyDev you can simply activate autopep8 from PyDev’s settings: Windows -> Preferences -> type ‘autopep8’ in the search filter.

Check the ‘use autopep8.py for code formatting?’ -> OK

Now eclipse’s CTRL-SHIFT-F code formatting should format your code using autopep8 :)


回答 4

我对python和代码风格的不同工具进行了广泛的研究。有两种类型的工具:linters-分析您的代码并给出有关错误使用的代码样式的警告并显示有关如何修复它的建议,以及code formatter-在保存文件时,它将使用PEP样式重新设置文档格式。

因为重新格式化必须更加准确-如果重新格式化您不希望的内容变得无用-它们覆盖的PEP所占比例较小,因此棉绒显示的更多。

它们都具有不同的配置权限-例如,在所有规则中都可以配置pylinter(您可以打开/关闭每种类型的警告),根本无法配置黑色。

以下是一些有用的链接和教程:

说明文件:

短绒(按受欢迎程度排序):

代码格式化程序(按流行程度排序):

I made wide research about different instruments for python and code style. There are two types of instruments: linters – analyzing your code and give some warnings about bad used code styles and showing advices how to fix it, and code formatters – when you save your file it re-format your document using PEP style.

Because re-formatting must be more accurate – if it remorfat something that you don’t want it became useless – they cover less part of PEP, linters show much more.

All of them have different permissions for configuring – for example, pylinter configurable in all its rules (you can turn on/off every type of warnings), black unconfigurable at all.

Here are some useful links and tutorials:

Documentation:

Linters (in order of popularity):

Code formatters (in order of popularity):


回答 5

有许多。

IDE通常具有一些内置的格式化功能。IntelliJ Idea / PyCharm确实具有这种功能,Eclipse的Python插件也是如此,依此类推。

有些格式化程序/分类符可以针对多种语言。https://coala.io是一个很好的例子。

然后是单目的工具,其他答案中提到了许多工具。

自动重新格式化的一种特定方法是将文件解析为AST树(不删除注释),然后将其转储回文本(意味着不保留任何原始格式)。例如:https://github.com/python/black

There are many.

IDEs usually have some formatting capability built in. IntelliJ Idea / PyCharm does, same goes for the Python plugin for Eclipse, and so on.

There are formatters/linters that can target multiple languages. https://coala.io is a good example of those.

Then there are the single purpose tools, of which many are mentioned in other answers.

One specific method of automatic reformatting is to parse the file into AST tree (without dropping comments) and then dump it back to text (meaning nothing of the original formatting is preserved). Example of that would be https://github.com/python/black.


PEP 8,为什么关键字参数或默认参数值的’=’周围没有空格?

问题:PEP 8,为什么关键字参数或默认参数值的’=’周围没有空格?

为什么PEP 8建议不要=在关键字参数或默认参数值中使用空格

这是否与=在Python代码中建议在每出现的其他地方推荐空格不一致?

怎么:

func(1, 2, very_long_variable_name=another_very_long_variable_name)

优于:

func(1, 2, very_long_variable_name = another_very_long_variable_name)

Python的BDFL与讨论/解释的任何链接将不胜感激。

请注意,这个问题更多的是关于kwargs而不是默认值,我只是使用了PEP 8中的措词。

我不是在征求意见。我要问这个决定背后的原因。这更像是在问我为什么要在C程序中{if语句使用同一行,而不是是否应该使用它。

Why does PEP 8 recommend not having spaces around = in a keyword argument or a default parameter value?

Is this inconsistent with recommending spaces around every other occurrence of = in Python code?

How is:

func(1, 2, very_long_variable_name=another_very_long_variable_name)

better than:

func(1, 2, very_long_variable_name = another_very_long_variable_name)

Any links to discussion/explanation by Python’s BDFL will be appreciated.

Mind, this question is more about kwargs than default values, i just used the phrasing from PEP 8.

I’m not soliciting opinions. I’m asking for reasons behind this decision. It’s more like asking why would I use { on the same line as if statement in a C program, not whether I should use it or not.


回答 0

我猜这是因为关键字参数与变量赋值本质上是不同的。

例如,有很多这样的代码:

kw1 = some_value
kw2 = some_value
kw3 = some_value
some_func(
    1,
    2,
    kw1=kw1,
    kw2=kw2,
    kw3=kw3)

如您所见,将变量分配给名称完全相同的关键字参数是完全有意义的,因此可以提高可读性,使它们看不到空格。更容易认识到我们正在使用关键字参数,而不是为其本身分配变量。

同样,参数往往在同一行中,而赋值通常每个都在各自的行中,因此节省空间可能是一个重要问题。

I guess that it is because a keyword argument is essentially different than a variable assignment.

For example, there is plenty of code like this:

kw1 = some_value
kw2 = some_value
kw3 = some_value
some_func(
    1,
    2,
    kw1=kw1,
    kw2=kw2,
    kw3=kw3)

As you see, it makes complete sense to assign a variable to a keyword argument named exactly the same, so it improves readability to see them without spaces. It is easier to recognize that we are using keyword arguments and not assigning a variable to itself.

Also, parameters tend to go in the same line whereas assignments usually are each one in their own line, so saving space is likely to be an important matter there.


回答 1

我不会使用very_long_variable_name作为默认参数。所以考虑一下:

func(1, 2, axis='x', angle=90, size=450, name='foo bar')

在此:

func(1, 2, axis = 'x', angle = 90, size = 450, name = 'foo bar')

同样,将变量用作默认值也没有多大意义。也许某些常量变量(实际上不是常量),在这种情况下,我将使用全为大写的名称,以描述性的方式表示,但尽可能简短。所以没有another_very _…

I wouldn’t use very_long_variable_name as a default argument. So consider this:

func(1, 2, axis='x', angle=90, size=450, name='foo bar')

over this:

func(1, 2, axis = 'x', angle = 90, size = 450, name = 'foo bar')

Also, it doesn’t make much sense to use variables as default values. Perhaps some constant variables (which aren’t really constants) and in that case I would use names that are all caps, descriptive yet short as possible. So no another_very_…


回答 2

有优点也有缺点。

我非常不喜欢PPE8兼容代码的读取方式。我不very_long_variable_name=another_very_long_variable_name接受比人类更具可读性 的论点very_long_variable_name = another_very_long_variable_name。人们不是这样阅读的。这是额外的认知负担,尤其是在没有语法突出显示的情况下。

但是,这有很大的好处。如果遵守间隔规则,则使使用工具专门搜索参数更加有效。

There are pros and cons.

I very much dislike how PEP8 compliant code reads. I don’t buy into the argument that very_long_variable_name=another_very_long_variable_name can ever be more human readable than very_long_variable_name = another_very_long_variable_name. This is not how people read. It’s an additional cognitive load, particularly in the absence of syntax highlighting.

There is a significant benefit, however. If the spacing rules are adhered to, it makes searching for parameters exclusively using tools much more effective.


回答 3

IMO省略了用于args的空间,从而提供了更清晰的arg / value对可视分组。看起来不那么混乱。

IMO leaving out the spaces for args provides cleaner visual grouping of the arg/value pairs; it looks less cluttered.


回答 4

我认为有几个原因,尽管我可能只是在进行合理化:

  1. 它节省了空间,允许更多的函数定义和调用适合一行,并为参数名称本身节省了更多空间。
  2. 通过将每个关键字和值连接在一起,可以更轻松地用逗号后的空格分隔不同的参数。这意味着您可以快速查看提供的参数数量。
  3. 这样,语法便与可能具有相同名称的变量分配不同。
  4. 此外,该语法(甚至更多)不同于相等检查a == b,相等检查也可以是调用内的有效表达式。

I think there are several reasons for this, although I might just be rationalizing:

  1. It saves space, allowing more function definitions and calls to fit on one line and saving more space for the argument names themselves.
  2. By joining each keyword and value, you can more easily separate the different arguments by the space after the comma. This means you can quickly eyeball how many arguments you’ve supplied.
  3. The syntax is then distinct from variable assignments, which may have the same name.
  4. Additionally, the syntax is (even more) distinct from equality checks a == b which can also be valid expressions inside a call.

回答 5

对我来说,它使代码更具可读性,因此是一个很好的约定。

我认为变量分配和函数关键字分配在样式方面的主要区别在于=,前者在一行上应该只有一个,而通常有多个=

如果没有其他考虑,我们宁愿foo = 42使用foo=42,因为后者不是等号通常的格式,并且因为前者在视觉上很好地用空格分隔了变量和值。

但是,当有一行中的多个任务,我们更f(foo=42, bar=43, baz=44)f(foo = 42, bar = 43, baz = 44),因为前者在视觉上与分离空白的几个任务,而后者则没有,使得它有点难以看到的关键字/值对。

这里是把它的另一种方式:还有就是约定背后的一致性。一致性是这样的:通过空格使“最高分离级别”在视觉上更加清晰。较低级别的分隔不是(因为它将与分隔较高级别的空白混淆)。对于变量分配,最高的分隔级别是变量和值之间。对于功能关键字分配,最高的分隔级别是各个分配本身之间的分隔。

For me it makes code more readable and is thus a good convention.

I think the key difference in terms of style between variable assignments and function keyword assignments is that there should only be a single = on a line for the former, whereas generally there are multiple =s on a line for the latter.

If there were no other considerations, we would prefer foo = 42 to foo=42, because the latter is not how equals signs are typically formatted, and because the former nicely visually separates the variable and value with whitespace.

But when there are multiple assignments on one line, we prefer f(foo=42, bar=43, baz=44) to f(foo = 42, bar = 43, baz = 44), because the former visually separates the several assignments with whitespace, whereas the latter does not, making it a bit harder to see where the keyword/value pairs are.

Here’s another way of putting it: there is a consistency behind the convention. That consistency is this: the “highest level of separation” is made visually clearer via spaces. Any lower levels of separation are not (because it would be confused with the whitespace separating the higher level). For variable assignment, the highest level of separation is between variable and value. For function keyword assignment, the highest level of separation is between the individual assignments themselves.


python中列表推导或生成器表达式的行连续

问题:python中列表推导或生成器表达式的行连续

您应该如何分解很长的清单理解力?

[something_that_is_pretty_long for something_that_is_pretty_long in somethings_that_are_pretty_long]

我还看到某个地方的人不喜欢使用’\’来分隔行,但从不理解为什么。这是什么原因呢?

How are you supposed to break up a very long list comprehension?

[something_that_is_pretty_long for something_that_is_pretty_long in somethings_that_are_pretty_long]

I have also seen somewhere that people that dislike using ‘\’ to break up lines, but never understood why. What is the reason behind this?


回答 0

[x
 for
 x
 in
 (1,2,3)
]

效果很好,因此您几乎可以随心所欲。我个人更喜欢

 [something_that_is_pretty_long
  for something_that_is_pretty_long
  in somethings_that_are_pretty_long]

\不能被很好理解的原因是它出现在一行的末尾,要么不突出,要么需要额外的填充,当行长改变时必须固定它:

x = very_long_term                     \
  + even_longer_term_than_the_previous \
  + a_third_term

在这种情况下,请使用括号:

x = (very_long_term
     + even_longer_term_than_the_previous
     + a_third_term)
[x
 for
 x
 in
 (1,2,3)
]

works fine, so you can pretty much do as you please. I’d personally prefer

 [something_that_is_pretty_long
  for something_that_is_pretty_long
  in somethings_that_are_pretty_long]

The reason why \ isn’t appreciated very much is that it appears at the end of a line, where it either doesn’t stand out or needs extra padding, which has to be fixed when line lengths change:

x = very_long_term                     \
  + even_longer_term_than_the_previous \
  + a_third_term

In such cases, use parens:

x = (very_long_term
     + even_longer_term_than_the_previous
     + a_third_term)

回答 1

我不反对:

variable = [something_that_is_pretty_long
            for something_that_is_pretty_long
            in somethings_that_are_pretty_long]

\在这种情况下,您不需要。总的来说,我认为人们避免\因为它有点丑陋,但是如果不是最后一件事,它也会给您带来麻烦(请确保没有空格后跟)。我认为使用它比不使用它要好得多,这样可以减少行长。

由于\在上述情况下或对于带括号的表达式不是必需的,所以我实际上很少需要使用它。

I’m not opposed to:

variable = [something_that_is_pretty_long
            for something_that_is_pretty_long
            in somethings_that_are_pretty_long]

You don’t need \ in this case. In general, I think people avoid \ because it’s slightly ugly, but also can give problems if it’s not the very last thing on the line (make sure no whitespace follows it). I think it’s much better to use it than not, though, in order to keep your line lengths down.

Since \ isn’t necessary in the above case, or for parenthesized expressions, I actually find it fairly rare that I even need to use it.


回答 2

在处理多个数据结构的列表时,也可以使用多个缩进。

new_list = [
    {
        'attribute 1': a_very_long_item.attribute1,
        'attribute 2': a_very_long_item.attribute2,
        'list_attribute': [
            {
                'dict_key_1': attribute_item.attribute2,
                'dict_key_2': attribute_item.attribute2
            }
            for attribute_item
            in a_very_long_item.list_of_items
         ]
    }
    for a_very_long_item
    in a_very_long_list
    if a_very_long_item not in [some_other_long_item
        for some_other_long_item 
        in some_other_long_list
    ]
]

请注意,它还如何使用if语句过滤到另一个列表。将if语句放到自己的行中也是有用的。

You can also make use of multiple indentations in cases where you’re dealing with a list of several data structures.

new_list = [
    {
        'attribute 1': a_very_long_item.attribute1,
        'attribute 2': a_very_long_item.attribute2,
        'list_attribute': [
            {
                'dict_key_1': attribute_item.attribute2,
                'dict_key_2': attribute_item.attribute2
            }
            for attribute_item
            in a_very_long_item.list_of_items
         ]
    }
    for a_very_long_item
    in a_very_long_list
    if a_very_long_item not in [some_other_long_item
        for some_other_long_item 
        in some_other_long_list
    ]
]

Notice how it also filters onto another list using an if statement. Dropping the if statement to its own line is useful as well.


排序Python`import x`和`from x import y`语句的正确方法是什么?

问题:排序Python`import x`和`from x import y`语句的正确方法是什么?

Python风格指南建议对进口组这样的:

导入应按以下顺序分组:

  1. 标准库导入
  2. 相关第三方进口
  3. 本地应用程序/特定于库的导入

但是,它没有提及应如何布置两种不同的进口方式的内容:

from foo import bar
import foo

对它们进行排序有多种方法(假设所有这些导入都属于同一组):

  • 首先from..import,然后import

    from g import gg
    from x import xx
    import abc
    import def
    import x
    
  • 首先import,然后from..import

    import abc
    import def
    import x
    from g import gg
    from x import xx
    
  • 按模块名称的字母顺序,忽略导入的类型

    import abc
    import def
    from g import gg
    import x
    from xx import xx
    

PEP8没有提到此命令的首选顺序,某些IDE的“清除导入”功能可能只是该工具的开发人员所做的任何事情。

我正在寻找另一个PEP来澄清这一点,或从BDFL(或另一个Python核心开发人员)那里获得相关的评论/电子邮件请不要发布主观答案来说明您的个人偏好。

The python style guide suggests to group imports like this:

Imports should be grouped in the following order:

  1. standard library imports
  2. related third party imports
  3. local application/library specific imports

However, it does not mention anything how the two different ways of imports should be laid out:

from foo import bar
import foo

There are multiple ways to sort them (let’s assume all those import belong to the same group):

  • first from..import, then import

    from g import gg
    from x import xx
    import abc
    import def
    import x
    
  • first import, then from..import

    import abc
    import def
    import x
    from g import gg
    from x import xx
    
  • alphabetic order by module name, ignoring the kind of import

    import abc
    import def
    from g import gg
    import x
    from xx import xx
    

PEP8 does not mention the preferred order for this and the “cleanup imports” features some IDEs have probably just do whatever the developer of that feature preferred.

I’m looking for another PEP clarifying this or a relevant comment/email from the BDFL (or another Python core developer). Please don’t post subjective answers stating your own preference.


回答 0

进口商品通常按字母顺序排序,并在PEP 8的不同位置进行描述。

按字母顺序排序的模块更易于阅读和搜索。毕竟python都是关于可读性的。另外,更容易验证是否导入了某些内容,并避免了重复的导入

PEP 8中没有关于排序的任何信息,因此所有关于选择所用内容的信息都是如此。

根据知名站点和存储库中也很少使用的参考文献,按字母顺序排序是这种方式。

例如:

import httplib
import logging
import random
import StringIO
import time
import unittest
from nova.api import openstack
from nova.auth import users
from nova.endpoint import cloud

要么

import a_standard
import b_standard

import a_third_party
import b_third_party

from a_soc import f
from a_soc import g
from b_soc import d

Reddit官方存储库还指出,通常应使用PEP-8导入顺序。但是有一些补充是

for each imported group the order of imports should be:
import <package>.<module> style lines in alphabetical order
from <package>.<module> import <symbol> style in alphabetical order

参考文献:

PS:isort实用程序会自动对您的导入进行排序。

Imports are generally sorted alphabetically and described in various places beside PEP 8.

Alphabetically sorted modules are quicker to read and searchable. After all python is all about readability. Also It is easier to verify that something is imported, and avoids duplicated imports

There is nothing available in PEP 8 regarding sorting.So its all about choice what you use.

According to few references from reputable sites and repositories also popularity, Alphabetical ordering is the way.

for eg like this:

import httplib
import logging
import random
import StringIO
import time
import unittest
from nova.api import openstack
from nova.auth import users
from nova.endpoint import cloud

OR

import a_standard
import b_standard

import a_third_party
import b_third_party

from a_soc import f
from a_soc import g
from b_soc import d

Reddit official repository also states that, In general PEP-8 import ordering should be used. However there are a few additions which is

for each imported group the order of imports should be:
import <package>.<module> style lines in alphabetical order
from <package>.<module> import <symbol> style in alphabetical order

References:

PS: the isort utility automatically sorts your imports.


回答 1

根据CIA的内部编码约定(WikiLeaks Vault 7泄漏的一部分),python导入应分为三类:

  1. 标准库导入
  2. 第三方进口
  3. 特定于应用程序的导入

在这些组中,应按字典顺序对导入进行排序,而忽略大小写:

import foo
from foo import bar
from foo.bar import baz
from foo.bar import Quux
from Foob import ar

According to the CIA’s internal coding conventions (part of the WikiLeaks Vault 7 leak), python imports should be grouped into three groups:

  1. Standard library imports
  2. Third-party imports
  3. Application-specific imports

Imports should be ordered lexicographically within these groups, ignoring case:

import foo
from foo import bar
from foo.bar import baz
from foo.bar import Quux
from Foob import ar

回答 2

PEP 8对此一无所获。关于这一点,没有约定,这并不意味着Python社区需要绝对定义一个。对于一个项目而言,选择可能会更好,而对于另一个项目而言,则是最糟糕的……这是一个偏好设置的问题,因为每种解决方案都有其优缺点。但是,如果要遵循约定,则必须遵守引用的主要顺序:

  1. 标准库导入
  2. 相关第三方进口
  3. 本地应用程序/特定于库的导入

例如,Google在此页面建议导入应按字典类别在每个类别(标准/第三方/您的)中进行排序。但是在Facebook,Yahoo和其他地方,这可能是另一种惯例…

The PEP 8 says nothing about it indeed. There’s no convention for this point, and it doesn’t mean the Python community need to define one absolutely. A choice can be better for a project but the worst for another… It’s a question of preferences for this, since each solutions has pro and cons. But if you want to follow conventions, you have to respect the principal order you quoted:

  1. standard library imports
  2. related third party imports
  3. local application/library specific imports

For example, Google recommend in this page that import should be sorted lexicographically, in each categories (standard/third parties/yours). But at Facebook, Yahoo and whatever, it’s maybe another convention…


回答 3

我强烈建议reorder-python-imports。它遵循已接受答案的第二个选项,并且还集成到pre-commit中,这非常有帮助。

I highly recommend reorder-python-imports. It follows the 2nd option of the accepted answer and also integrates into pre-commit, which is super helpful.


回答 4

所有import x语句应按的值排序x,所有from x import y语句应按的值x按字母顺序排序,并且已排序的from x import y语句组必须遵循已排序的import x语句组。

import abc
import def
import x
from g import gg
from x import xx
from z import a

All import x statements should be sorted by the value of x and all from x import y statements should be sorted by the value of x in alphabetical order and the sorted groups of from x import y statements must follow the sorted group of import x statements.

import abc
import def
import x
from g import gg
from x import xx
from z import a

回答 5

我觉得已接受的答案有点太冗长。这是TLDR:

在每个分组中,应按照每个模块的完整包装路径,按字典顺序对导入进行排序,而忽略大小写

Google代码样式指南

因此,第三个选项是正确的:

import abc
import def
from g import yy  # changed gg->yy for illustrative purposes
import x
from xx import xx

I feel like the accepted answer is a bit too verbose. Here is TLDR:

Within each grouping, imports should be sorted lexicographically, ignoring case, according to each module’s full package path

Google code style guide

So, the third option is correct:

import abc
import def
from g import yy  # changed gg->yy for illustrative purposes
import x
from xx import xx

Python注释中的“#noqa”是什么意思?

问题:Python注释中的“#noqa”是什么意思?

在搜索Python项目时,我发现有几行用注释# noqa

import sys
sys.path.append(r'C:\dev')
import some_module   # noqa

noqa在Python 中是什么意思?它仅适用于Python吗?

While searching through a Python project, I found a few lines commented with # noqa.

import sys
sys.path.append(r'C:\dev')
import some_module   # noqa

What does noqa mean in Python? Is it specific to Python only?


回答 0

添加# noqa到一行表示该linter(自动检查代码质量的程序)不应检查该行。代码可能已生成的任何警告都将被忽略。

该行可能对短毛绒“看起来不好”,但由于某种原因,开发人员理解并打算将其放在那里。

有关更多信息,请参见Flake8文档,以选择和忽略违规

Adding # noqa to a line indicates that the linter (a program that automatically checks code quality) should not check this line. Any warnings that code may have generated will be ignored.

That line may have something that “looks bad” to the linter, but the developer understands and intends it to be there for some reason.

For more information, see the Flake8 documentation for Selecting and Ignoring Violations.


回答 1

noqa = NO-QA(无质量保证)

在Python编程中通常引用它来忽略PEP8警告。

简而言之,linter程序将忽略末尾带有#noqa的行,并且不会发出任何警告。

noqa = NO-QA (NO Quality Assurance)

It’s generally referred in Python Programming to ignore the PEP8 warnings.

In simple words, lines having #noqa at the end will be ignored by the linter programs and they won’t raise any warnings.


回答 2

你知道吗?甚至Guido van Rossum(Python的创建者):D 之前也问过这个问题。

有点词源# noqa

它曾经是“ nopep8”,但是当Flake8和Pep8想要一个普通的限定词时,@ florentx像“ No Quality Assurance”(iirc)中一样建议“ NoQA”,并且卡住了。

一些基本用法# noqa(与flake8):

  • # flake8: noqa:跳过包含此行的文件
  • 最后包含# noqa评论的:将不会发出警告
  • # noqa: <error>,例如# noqa: E234 最后:忽略一行中的 特定错误
    • 可以给出多个错误代码,以逗号分隔
    • 代码列表之前的冒号

You know what? Even Guido van Rossum (the creator of Python) asked this question before :D

A bit Etymology of # noqa:

It used to be “nopep8” but when Flake8 and Pep8 wanted a common qualifier @florentx suggested “NoQA” as in “No Quality Assurance” (iirc) and it stuck.

Some basic usages of # noqa (with flake8):

  • # flake8: noqa: files that contain this line are skipped
  • lines that contain a # noqa comment at the end: will not issue warnings
  • # noqa: <error>, e.g., # noqa: E234 at the end: ignore specific errors on a line
    • multiple error codes can be given, separated by comma
    • the colon before the list of codes is required

如何编写符合PEP8的很长的字符串并防止E501

问题:如何编写符合PEP8的很长的字符串并防止E501

正如PEP8建议将python程序的规则保持在80列以下,我该如何使用长字符串来遵守该规则,即

s = "this is my really, really, really, really, really, really, really long string that I'd like to shorten."

我如何将其扩展到以下行,即

s = "this is my really, really, really, really, really, really" + 
    "really long string that I'd like to shorten."

As PEP8 suggests keeping below the 80 column rule for your python program, how can I abide to that with long strings, i.e.

s = "this is my really, really, really, really, really, really, really long string that I'd like to shorten."

How would I go about expanding this to the following line, i.e.

s = "this is my really, really, really, really, really, really" + 
    "really long string that I'd like to shorten."

回答 0

隐式串联可能是最干净的解决方案:

s = "this is my really, really, really, really, really, really," \
    " really long string that I'd like to shorten."

编辑在反思我同意,托德的建议,请使用括号,而不是续行是所有他给出的理由更好。我唯一的犹豫是将带括号的字符串与元组混淆是相对容易的。

Implicit concatenation might be the cleanest solution:

s = "this is my really, really, really, really, really, really," \
    " really long string that I'd like to shorten."

Edit On reflection I agree that Todd’s suggestion to use brackets rather than line continuation is better for all the reasons he gives. The only hesitation I have is that it’s relatively easy to confuse bracketed strings with tuples.


回答 1

另外,由于相邻的字符串常量是自动连接的,因此您也可以这样编码:

s = ("this is my really, really, really, really, really, really, "  
     "really long string that I'd like to shorten.")

请注意没有加号,我在示例格式之后添加了额外的逗号和空格。

我个人不喜欢反斜杠,并且我记得在某处读到它的使用实际上已被弃用,而倾向于这种更明确的形式。记住“显式胜于隐式”。

我认为反斜杠不太清楚,用处也不大,因为这实际上是在换行符的转义。如果有必要在行末尾添加注释。可以使用串联的字符串常量来做到这一点:

s = ("this is my really, really, really, really, really, really, " # comments ok
     "really long string that I'd like to shorten.")

我使用Google搜索“ python行长”来返回PEP8链接作为第一个结果,同时还链接到另一个有关该主题的StackOverflow帖子:“ 为什么Python PEP-8应该指定最大行长为79个字符?

另一个很好的搜索词组是“ python行连续”。

Also, because neighboring string constants are automatically concatenated, you can code it like this too:

s = ("this is my really, really, really, really, really, really, "  
     "really long string that I'd like to shorten.")

Note no plus sign, and I added the extra comma and space that follows the formatting of your example.

Personally I don’t like the backslashes, and I recall reading somewhere that its use is actually deprecated in favor of this form which is more explicit. Remember “Explicit is better than implicit.”

I consider the backslash to be less clear and less useful because this is actually escaping the newline character. It’s not possible to put a line end comment after it if one should be necessary. It is possible to do this with concatenated string constants:

s = ("this is my really, really, really, really, really, really, " # comments ok
     "really long string that I'd like to shorten.")

I used a Google search of “python line length” which returns the PEP8 link as the first result, but also links to another good StackOverflow post on this topic: “Why should Python PEP-8 specify a maximum line length of 79 characters?

Another good search phrase would be “python line continuation”.


回答 2

我认为您的问题中最重要的词是“建议”。

编码标准很有趣。通常,他们提供的指南在编写时有很好的基础(例如,大多数终端无法在一行上显示> 80个字符),但是随着时间的推移,它们在功能上已过时,但仍然严格遵守。我想您在这里需要做的是权衡“打破”该特定建议与代码的可读性和可维护性的相对优点。

抱歉,这不能直接回答您的问题。

I think the most important word in your question was “suggests”.

Coding standards are funny things. Often the guidance they provide has a really good basis when it was written (e.g. most terminals being unable to show > 80 characters on a line), but over time they become functionally obsolete, but still rigidly adhered to. I guess what you need to do here is weigh up the relative merits of “breaking” that particular suggestion against the readability and mainatinability of your code.

Sorry this doesn’t directly answer your question.


回答 3

您丢失了一个空格,并且可能需要换行符,即。一个\

s = "this is my really, really, really, really, really, really" +  \
    " really long string that I'd like to shorten."

甚至:

s = "this is my really, really, really, really, really, really"  \
    " really long string that I'd like to shorten."

Parens也可以代替行继续,但是您可能会冒险有人认为您打算创建一个元组而忘记了逗号。举个例子:

s = ("this is my really, really, really, really, really, really"
    " really long string that I'd like to shorten.")

与:

s = ("this is my really, really, really, really, really, really",
    " really long string that I'd like to shorten.")

使用Python的动态类型,代码可能会以任何一种方式运行,但是会产生与您不想要的结果相同的错误结果。

You lost a space, and you probably need a line continuation character, ie. a \.

s = "this is my really, really, really, really, really, really" +  \
    " really long string that I'd like to shorten."

or even:

s = "this is my really, really, really, really, really, really"  \
    " really long string that I'd like to shorten."

Parens would also work instead of the line continuation, but you risk someone thinking you intended to have a tuple and had just forgotten a comma. Take for instance:

s = ("this is my really, really, really, really, really, really"
    " really long string that I'd like to shorten.")

versus:

s = ("this is my really, really, really, really, really, really",
    " really long string that I'd like to shorten.")

With Python’s dynamic typing, the code may run either way, but produce incorrect results with the one you didn’t intend.


回答 4

反斜杠:

s = "this is my really, really, really, really, really, really" +  \
    "really long string that I'd like to shorten."

或包裹在括号中:

s = ("this is my really, really, really, really, really, really" + 
    "really long string that I'd like to shorten.")

Backslash:

s = "this is my really, really, really, really, really, really" +  \
    "really long string that I'd like to shorten."

or wrap in parens:

s = ("this is my really, really, really, really, really, really" + 
    "really long string that I'd like to shorten.")

回答 5

这些都是很好的答案,但是我找不到能帮助我编辑“隐式连接”字符串的编辑器插件,因此我编写了一个程序包使它更容易使用。

在pip(安装段落)上,如果有人在徘徊这个旧线程想要将其签出。格式化html格式的多行字符串(压缩空格,为新段落添加两个换行符,不必担心行之间的空格)。

from paragraphs import par


class SuddenDeathError(Exception):
    def __init__(self, cause: str) -> None:
        self.cause = cause

    def __str__(self):
        return par(
            f""" Y - e - e - e - es, Lord love you! Why should she die of
            {self.cause}? She come through diphtheria right enough the year
            before. I saw her with my own eyes. Fairly blue with it, she
            was. They all thought she was dead; but my father he kept ladling
            gin down her throat till she came to so sudden that she bit the bowl
            off the spoon. 

            What call would a woman with that strength in her have to die of
            {self.cause}? What become of her new straw hat that should have
            come to me? Somebody pinched it; and what I say is, them as pinched
            it done her in."""
        )


raise SuddenDeathError("influenza")

变成…

__main__.SuddenDeathError: Y - e - e - e - es, Lord love you! Why should she die of influenza? She come through diphtheria right enough the year before. I saw her with my own eyes. Fairly blue with it, she was. They all thought she was dead; but my father he kept ladling gin down her throat till she came to so sudden that she bit the bowl off the spoon.

What call would a woman with that strength in her have to die of influenza? What become of her new straw hat that should have come to me? Somebody pinched it; and what I say is, them as pinched it done her in.

一切都轻松地与(Vim)’gq’对齐

These are all great answers, but I couldn’t find an editor plugin that would help me with editing “implicitly concatenated” strings, so I wrote a package to make it easier on me.

On pip (install paragraphs) if whoever’s wandering this old thread would like to check it out. Formats multi-line strings the way html does (compress whitespace, two newlines for a new paragraph, no worries about spaces between lines).

from paragraphs import par


class SuddenDeathError(Exception):
    def __init__(self, cause: str) -> None:
        self.cause = cause

    def __str__(self):
        return par(
            f""" Y - e - e - e - es, Lord love you! Why should she die of
            {self.cause}? She come through diphtheria right enough the year
            before. I saw her with my own eyes. Fairly blue with it, she
            was. They all thought she was dead; but my father he kept ladling
            gin down her throat till she came to so sudden that she bit the bowl
            off the spoon. 

            What call would a woman with that strength in her have to die of
            {self.cause}? What become of her new straw hat that should have
            come to me? Somebody pinched it; and what I say is, them as pinched
            it done her in."""
        )


raise SuddenDeathError("influenza")

becomes …

__main__.SuddenDeathError: Y - e - e - e - es, Lord love you! Why should she die of influenza? She come through diphtheria right enough the year before. I saw her with my own eyes. Fairly blue with it, she was. They all thought she was dead; but my father he kept ladling gin down her throat till she came to so sudden that she bit the bowl off the spoon.

What call would a woman with that strength in her have to die of influenza? What become of her new straw hat that should have come to me? Somebody pinched it; and what I say is, them as pinched it done her in.

Everything lines up easily with (Vim) ‘gq’


回答 6

使用a \可以将语句扩展到多行:

s = "this is my really, really, really, really, really, really" + \
"really long string that I'd like to shorten."

应该管用。

With a \ you can expand statements to multiple lines:

s = "this is my really, really, really, really, really, really" + \
"really long string that I'd like to shorten."

should work.


回答 7

我倾向于使用一些此处未提及的方法来指定大字符串,但这是针对非常特定的场景的。YMMV …

  • 多行文本,通常带有格式化标记(不是您所要的,但仍然有用):

    error_message = '''
    I generally like to see how my helpful, sometimes multi-line error
    messages will look against the left border.
    '''.strip()
  • 通过您喜欢的任何字符串插值方法逐段增加变量:

    var = 'This is the start of a very,'
    var = f'{var} very long string which could'
    var = f'{var} contain a ridiculous number'
    var = f'{var} of words.'
  • 从文件中读取。PEP-8不会限制文件中字符串的长度;只是您的代码行。:)

  • 使用蛮力或您的编辑器使用换行符将字符串拆分为可换行,然后删除所有换行符。(类似于我列出的第一种技术):

    foo = '''
    agreatbigstringthatyoudonotwanttohaveanyne
    wlinesinbutforsomereasonyouneedtospecifyit
    verbatimintheactualcodejustlikethis
    '''.replace('\n', '')

I tend to use a couple of methods not mentioned here for specifying large strings, but these are for very specific scenarios. YMMV…

  • Multi-line blobs of text, often with formatted tokens (not quite what you were asking, but still useful):

    error_message = '''
    I generally like to see how my helpful, sometimes multi-line error
    messages will look against the left border.
    '''.strip()
    
  • Grow the variable piece-by-piece through whatever string interpolation method you prefer:

    var = 'This is the start of a very,'
    var = f'{var} very long string which could'
    var = f'{var} contain a ridiculous number'
    var = f'{var} of words.'
    
  • Read it from a file. PEP-8 doesn’t limit the length of strings in a file; just the lines of your code. :)

  • Use brute-force or your editor to split the string into managaeble lines using newlines, and then remove all newlines. (Similar to the first technique I listed):

    foo = '''
    agreatbigstringthatyoudonotwanttohaveanyne
    wlinesinbutforsomereasonyouneedtospecifyit
    verbatimintheactualcodejustlikethis
    '''.replace('\n', '')
    

回答 8

可用选项:

  • 反斜杠"foo" \ "bar"
  • 加号后跟反斜杠"foo" + \ "bar"
  • 括号
    • ("foo" "bar")
    • 加号的括号("foo" + "bar")
    • PEP8,E502:括号之间的反斜杠是多余的

避免

避免用逗号括起来:("foo", "bar")定义一个元组。


>>> s = "a" \
... "b"
>>> s
'ab'
>>> type(s)
<class 'str'>
>>> s = "a" + \
... "b"
>>> s
'ab'
>>> type(s)
<class 'str'>
>>> s = ("a"
... "b")
>>> type(s)
<class 'str'>
>>> print(s)
ab
>>> s = ("a",
... "b")
>>> type(s)
<class 'tuple'>
>>> s = ("a" + 
... "b")
>>> type(s)
<class 'str'>
>>> print(s)
ab
>>> 

Available options:

  • backslash: "foo" \ "bar"
  • plus sign followed by backslash: "foo" + \ "bar"
  • brackets:
    • ("foo" "bar")
    • brackets with plus sign: ("foo" + "bar")
    • PEP8, E502: the backslash is redundant between brackets

Avoid

Avoid brackets with comma: ("foo", "bar") which defines a tuple.


>>> s = "a" \
... "b"
>>> s
'ab'
>>> type(s)
<class 'str'>
>>> s = "a" + \
... "b"
>>> s
'ab'
>>> type(s)
<class 'str'>
>>> s = ("a"
... "b")
>>> type(s)
<class 'str'>
>>> print(s)
ab
>>> s = ("a",
... "b")
>>> type(s)
<class 'tuple'>
>>> s = ("a" + 
... "b")
>>> type(s)
<class 'str'>
>>> print(s)
ab
>>> 

回答 9

如果您必须插入一个长字符串文字并希望flake8关闭,则可以使用它的关闭指令。例如,在测试例程中,我定义了一些伪造的CSV输入。我发现将其分割成行的更多行会造成极大的混乱,因此我决定添加# noqa: E501以下内容:

csv_test_content = """"STATION","DATE","SOURCE","LATITUDE","LONGITUDE","ELEVATION","NAME","REPORT_TYPE","CALL_SIGN","QUALITY_CONTROL","WND","CIG","VIS","TMP","DEW","SLP","AA1","AA2","AY1","AY2","GF1","MW1","REM"
"94733099999","2019-01-03T22:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","050,1,N,0010,1","22000,1,9,N","025000,1,9,9","+0260,1","+0210,1","99999,9","24,0000,9,1",,"0,1,02,1","0,1,02,1","01,99,1,99,9,99,9,99999,9,99,9,99,9","01,1","SYN05294733 11/75 10502 10260 20210 60004 70100 333 70000="
"94733099999","2019-01-04T04:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","090,1,N,0021,1","22000,1,9,N","025000,1,9,9","+0378,1","+0172,1","99999,9","06,0000,9,1",,"0,1,02,1","0,1,02,1","03,99,1,99,9,99,9,99999,9,99,9,99,9","03,1","SYN04294733 11/75 30904 10378 20172 60001 70300="
"94733099999","2019-01-04T22:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","290,1,N,0057,1","99999,9,9,N","020000,1,9,9","+0339,1","+0201,1","99999,9","24,0000,9,1",,"0,1,02,1","0,1,02,1",,"02,1","SYN05294733 11970 02911 10339 20201 60004 70200 333 70000="
"94733099999","2019-01-05T22:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","200,1,N,0026,1","99999,9,9,N","000100,1,9,9","+0209,1","+0193,1","99999,9","24,0004,3,1",,"1,1,02,1","1,1,02,1","08,99,1,99,9,99,9,99999,9,99,9,99,9","51,1","SYN05294733 11/01 82005 10209 20193 69944 75111 333 70004="
"94733099999","2019-01-08T04:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","070,1,N,0026,1","22000,1,9,N","025000,1,9,9","+0344,1","+0213,1","99999,9","06,0000,9,1",,"2,1,02,1","2,1,02,1","04,99,1,99,9,99,9,99999,9,99,9,99,9","02,1","SYN04294733 11/75 40705 10344 20213 60001 70222="
"""  # noqa: E501

If you must insert a long string literal and want flake8 to shut up, you can use it’s shutting up directives. For example, in a testing routine I defined some fake CSV input. I found that splitting it over more lines that it had rows would be mightily confusing, so I decided to add a # noqa: E501 as follows:

csv_test_content = """"STATION","DATE","SOURCE","LATITUDE","LONGITUDE","ELEVATION","NAME","REPORT_TYPE","CALL_SIGN","QUALITY_CONTROL","WND","CIG","VIS","TMP","DEW","SLP","AA1","AA2","AY1","AY2","GF1","MW1","REM"
"94733099999","2019-01-03T22:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","050,1,N,0010,1","22000,1,9,N","025000,1,9,9","+0260,1","+0210,1","99999,9","24,0000,9,1",,"0,1,02,1","0,1,02,1","01,99,1,99,9,99,9,99999,9,99,9,99,9","01,1","SYN05294733 11/75 10502 10260 20210 60004 70100 333 70000="
"94733099999","2019-01-04T04:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","090,1,N,0021,1","22000,1,9,N","025000,1,9,9","+0378,1","+0172,1","99999,9","06,0000,9,1",,"0,1,02,1","0,1,02,1","03,99,1,99,9,99,9,99999,9,99,9,99,9","03,1","SYN04294733 11/75 30904 10378 20172 60001 70300="
"94733099999","2019-01-04T22:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","290,1,N,0057,1","99999,9,9,N","020000,1,9,9","+0339,1","+0201,1","99999,9","24,0000,9,1",,"0,1,02,1","0,1,02,1",,"02,1","SYN05294733 11970 02911 10339 20201 60004 70200 333 70000="
"94733099999","2019-01-05T22:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","200,1,N,0026,1","99999,9,9,N","000100,1,9,9","+0209,1","+0193,1","99999,9","24,0004,3,1",,"1,1,02,1","1,1,02,1","08,99,1,99,9,99,9,99999,9,99,9,99,9","51,1","SYN05294733 11/01 82005 10209 20193 69944 75111 333 70004="
"94733099999","2019-01-08T04:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","070,1,N,0026,1","22000,1,9,N","025000,1,9,9","+0344,1","+0213,1","99999,9","06,0000,9,1",,"2,1,02,1","2,1,02,1","04,99,1,99,9,99,9,99999,9,99,9,99,9","02,1","SYN04294733 11/75 40705 10344 20213 60001 70222="
"""  # noqa: E501

回答 10

我过去使用过textwrap.dedent。这有点麻烦,所以我现在更喜欢连续行,但是如果您真的想要块缩进,我认为这很棒。

示例代码(其中修剪将去除带有切片的第一个“ \ n”):

import textwrap as tw
x = """\
       This is a yet another test.
       This is only a test"""
print(tw.dedent(x))

说明:

dedent根据换行之前第一行文本中的空格来计算缩进。如果您想对其进行调整,则可以使用该re模块轻松地重新实现它。

此方法有局限性,因为很长的行可能仍然比您想要的更长,在这种情况下,其他将字符串连接起来的方法更合适。

I’ve used textwrap.dedent in the past. It’s a little cumbersome so I prefer line continuations now but if you really want the block indent, I think this is great.

Example Code (where the trim is to get rid of the first ‘\n’ with a slice):

import textwrap as tw
x = """\
       This is a yet another test.
       This is only a test"""
print(tw.dedent(x))

Explanation:

dedent calculates the indentation based on the white space in the first line of text before a new line. If you wanted to tweak it, you could easily reimplement it using the re module.

This method has limitations in that very long lines may still be longer than you want in which case other methods that concatenate strings is more suitable.


为什么PEP-8指定的最大行长为79个字符?[关闭]

问题:为什么PEP-8指定的最大行长为79个字符?[关闭]

为什么在这个千年中,Python PEP-8应该指定最大行长度为79个字符?

在阳光下几乎每个代码编辑器都可以处理更长的行。包装应该是内容消费者的选择,而不是内容创建者的责任。

在这个年龄段,是否有(合理的)充分理由坚持使用79个字符?

Why in this millennium should Python PEP-8 specify a maximum line length of 79 characters?

Pretty much every code editor under the sun can handle longer lines. What to do with wrapping should be the choice of the content consumer, not the responsibility of the content creator.

Are there any (legitimately) good reasons for adhering to 79 characters in this age?


回答 0

PEP-8的许多价值在于阻止人们参数无关紧要的格式化规则,并继续编写良好的,一致的格式化代码。当然,没有人真的认为79是最佳选择,但是将其更改为99或119或您首选的行长都没有明显的好处。我认为选择是这样的:遵循规则并找到值得争取的理由,或者提供一些数据来证明可读性和生产率如何随行长而变化。后者将非常有趣,并且我有很大的机会改变人们的想法。

Much of the value of PEP-8 is to stop people arguing about inconsequential formatting rules, and get on with writing good, consistently formatted code. Sure, no one really thinks that 79 is optimal, but there’s no obvious gain in changing it to 99 or 119 or whatever your preferred line length is. I think the choices are these: follow the rule and find a worthwhile cause to battle for, or provide some data that demonstrates how readability and productivity vary with line length. The latter would be extremely interesting, and would have a good chance of changing people’s minds I think.


回答 1

保持您的代码对人类可读,而不仅仅是机器可读。许多设备仍然一次只能显示80个字符。此外,它能够通过并排设置多个窗口,使屏幕较大的人更容易执行多项任务。

可读性也是强制行缩进的原因之一。

Keeping your code human readable not just machine readable. A lot of devices still can only show 80 characters at a time. Also it makes it easier for people with larger screens to multi-task by being able to set up multiple windows to be side by side.

Readability is also one of the reasons for enforced line indentation.


回答 2

我是一个程序员,每天必须处理大量代码。开源以及内部开发的东西。

作为一名程序员,我发现一次打开多个源文件很有用,并且经常在(宽屏)监视器上组织桌面,以便两个源文件并排。我可能两者都在编程,或者只是阅读其中一项,而另一种则在编程。

当这些源文件之一的宽度大于120个字符时,我会感到不满意和沮丧,因为这意味着我无法舒适地将一行代码放在屏幕上。它将格式设置换行。

我之所以说“ 120”,是因为这会导致我对超出范围的代码感到恼火。在输入了这么多字符之后,您应该为了便于阅读而将行分开,更不用说编码标准了。

我在编写代码时会考虑80列。只是这样,当我确实在该边界上泄漏时,这并不是一件坏事。

I am a programmer who has to deal with a lot of code on a daily basis. Open source and what has been developed in house.

As a programmer, I find it useful to have many source files open at once, and often organise my desktop on my (widescreen) monitor so that two source files are side by side. I might be programming in both, or just reading one and programming in the other.

I find it dissatisfying and frustrating when one of those source files is >120 characters in width, because it means I can’t comfortably fit a line of code on a line of screen. It upsets formatting to line wrap.

I say ‘120’ because that’s the level to which I would get annoyed at code being wider than. After that many characters, you should be splitting across lines for readability, let alone coding standards.

I write code with 80 columns in mind. This is just so that when I do leak over that boundary, it’s not such a bad thing.


回答 3

我相信那些研究版式的人会告诉您,每行66个字符应该是长度上最易读的宽度。即使这样,如果您需要通过ssh会话远程调试机器,大多数终端默认为80个字符,而79个恰好适合,在这种情况下尝试使用任何更宽的设备将是一个真正的痛苦。使用vim +屏幕作为日常环境的开发人员数量也将令您感到惊讶。

I believe those who study typography would tell you that 66 characters per a line is supposed to be the most readable width for length. Even so, if you need to debug a machine remotely over an ssh session, most terminals default to 80 characters, 79 just fits, trying to work with anything wider becomes a real pain in such a case. You would also be suprised by the number of developers using vim + screen as a day to day environment.


回答 4

在A4纸上,默认尺寸下的等宽字体打印为80列乘66行。

Printing a monospaced font at default sizes is (on A4 paper) 80 columns by 66 lines.


回答 5

这就是为什么我喜欢80个字符的原因:在工作中,我使用Vim,并在运行于1680×1040的监视器上一次处理两个文件(我不记得了)。如果行数不再长,即使使用自动换行,我也很难读取文件。不用说,我讨厌处理别人的代码,因为他们喜欢排长队。

Here’s why I like the 80-character with: at work I use Vim and work on two files at a time on a monitor running at, I think, 1680×1040 (I can never remember). If the lines are any longer, I have trouble reading the files, even when using word wrap. Needless to say, I hate dealing with other people’s code as they love long lines.


回答 6

由于空格在Python中具有语义含义,因此某些自动换行方法可能会产生不正确或模棱两可的结果,因此需要有一定的限制以避免这些情况。自从我们使用电传打字机以来,标准的行长为80个字符,因此79个字符似乎是一个非常安全的选择。

Since whitespace has semantic meaning in Python, some methods of word wrapping could produce incorrect or ambiguous results, so there needs to be some limit to avoid those situations. An 80 character line length has been standard since we were using teletypes, so 79 characters seems like a pretty safe choice.


回答 7

我同意贾斯汀。详细来说,人很难阅读过长的代码行,并且某些人的控制台宽度每行只能容纳80个字符。

推荐使用样式,以确保尽可能多的人在尽可能多的平台上尽可能舒适地阅读您编写的代码。

I agree with Justin. To elaborate, overly long lines of code are harder to read by humans and some people might have console widths that only accommodate 80 characters per line.

The style recommendation is there to ensure that the code you write can be read by as many people as possible on as many platforms as possible and as comfortably as possible.


回答 8

因为如果将其推到第80列之外,则意味着您正在编写的代码行很长且很复杂,执行了太多操作(因此您应该重构),或者缩进太多了(因此您应该重构)。

because if you push it beyond the 80th column it means that either you are writing a very long and complex line of code that does too much (and so you should refactor), or that you indented too much (and so you should refactor).


如何在PyCharm中设置最大行长?

问题:如何在PyCharm中设置最大行长?

我在Windows上使用PyCharm,并且想要更改设置以将最大行长限制为79字符,而不是默认的120字符限制。

我在哪里可以更改PyCharm中每行的最大字符数?

I am using PyCharm on Windows and want to change the settings to limit the maximum line length to 79 characters, as opposed to the default limit of 120 characters.

Where can I change the maximum amount of characters per line in PyCharm?


回答 0

这是我的Pycharm的屏幕截图。所需设置在以下路径中:File -> Settings -> Editor -> Code Style -> General: Right margin (columns)

Here is screenshot of my Pycharm. Required settings is in following path: File -> Settings -> Editor -> Code Style -> General: Right margin (columns)


回答 1

对于Mac上的PyCharm 2018.1:

首选项(+ ,),然后Editor -> Code Style

对于Windows上的PyCharm 2018.3:

文件->设置(Ctrl+ Alt+ S),然后Editor -> Code Style

要遵循PEP-8,请将其设置Hard wrap at为80。

For PyCharm 2018.1 on Mac:

Preferences (+,), then Editor -> Code Style:

For PyCharm 2018.3 on Windows:

File -> Settings (Ctrl+Alt+S), then Editor -> Code Style:

To follow PEP-8 set Hard wrap at to 80.


回答 2

对于PyCharm 4

文件>>设置>>编辑器>>代码样式:右边距(列)

建议:查看该标签中的其他选项,它们非常有帮助

For PyCharm 4

File >> Settings >> Editor >> Code Style: Right margin (columns)

suggestion: Take a look at other options in that tab, they’re very helpful


回答 3

您甚至可以为HTML 设置单独的右边距。在指定路径下:

文件>>设置>>编辑器>>代码样式>> HTML >>其他选项卡>>右页边距(列)

这非常有用,因为通常HTML和JS的一行通常比Python长。:)

You can even set a separate right margin for HTML. Under the specified path:

File >> Settings >> Editor >> Code Style >> HTML >> Other Tab >> Right margin (columns)

This is very useful because generally HTML and JS may be usually long in one line than Python. :)


回答 4

对于任何人,或者对于我自己,如果我重新加载计算机,在进行代码重新格式化时这对谁都不起作用,那么还有一个附加选项可在editor-> code style-> python下检查:确保未超出正确的边距。选择此选项后,格式将生效。

For anyone, or myself if I reload my machine, who this is not working for when you do a code reformat there is an additional option to check under editor->code style->python : ensure right margin is not exceeded. Once this was selected the reformat would work.


回答 5

对于PyCharm 2017

我们可以按照以下步骤进行操作:文件>>设置>>编辑器>>代码样式。

然后在键入时为Hard Wrap&提供值Visual Guides for wrapping,勾选复选框。

注意:也请查看其他标签。Python,HTML,JSON等

For PyCharm 2017

We can follow below: File >> Settings >> Editor >> Code Style.

Then provide values for Hard Wrap & Visual Guides for wrapping while typing, tick the checkbox.

NB: look at other tabs as well, viz. Python, HTML, JSON etc.