如何在一行中写多个语句?

183

我了解Python中的推导式,但它们似乎很难“阅读”。按我的理解,一个推导式可以完成与以下代码相同的操作:

for i in range(10): if i == 9: print('i equals 9')

这段代码比现有的推导式易于阅读,但我注意到一行中不能有两个冒号:。这使我想到:

是否有办法将以下示例放到一行中?

try:
    if sam[0] != 'harry':
        print('hello',  sam)
except:
    pass

这样的东西会很棒:

try: if sam[0] != 'harry': print('hellp',  sam)
except:pass

但是我再次遇到了冲突的:

我也想知道是否有一种方法可以运行try(或类似的东西)而不需要except。看起来完全没有意义,我需要在那里放置except:pass。这是浪费的一行代码。


它为什么会抛出异常? - Ignacio Vazquez-Abrams
3
"Sam[2]可能不存在。这只是一个假设性的例子。谢谢。" - Rhys
5
在Python中,理解(comprehension)是一种不同的概念。把所有东西都放在一行里并不是理解。 - Felix Kling
我知道这个问题。谢谢。我只是在演示如何更好地理解,但由于冒号是我的问题/疑问的根源,所以无法实现。 - Rhys
只需使用\n换行符,并使用空格进行缩进。 - user3210045
显示剩余3条评论
15个回答

187

很遗憾,你想要的在Python中是不可能实现的(这使得Python对于命令行单行程序几乎没有用处)。即使显式使用括号也无法避免语法异常。你可以采用一系列简单语句,用分号隔开来解决问题:

for i in range(10): print "foo"; print "bar"

但是一旦你添加了一个引入缩进块的结构(比如if),你就需要换行。此外,

for i in range(10): print "i equals 9" if i==9 else None

是合法的,可能接近您想要的内容。

如果您仍然决定使用一行代码,请参见 elecprog 的答案。

至于 try ... except 这个东西:如果没有 except,它会完全无用。 try 表示“我想运行这段代码,但可能会引发异常”。如果您不关心异常,则省略 try。但是,一旦您将其放入其中,就表示“我想处理潜在的异常”。然后,pass 表示您不希望具体处理它。但这意味着您的代码将继续运行,否则它将无法运行。


1
有趣的是,我认为你后面的例子最接近我正在寻找的答案。谢谢。 - Rhys
6
对于“try:”语句,Python的语法规则不允许你没有配套的“except”子句。我通常会将try-except语句封装到一个函数中,然后调用该函数,例如:“if (checkint(s))...” 和 “def checkint(s): try: int(s)\nreturn True\nexcept: return False”。这样做可以避免语法错误。 - ThomasH
1
ThomasH,我希望你的评论是某个问题的答案,这样我就可以点赞了。太好了。 - Ivan X
8
@ThomasH说:“这使得Python几乎无法用于命令行单行程序”,但这并不妨碍我。95%的情况下不需要换行,而其余通过\n实现。以下是需要翻译的代码内容:python -c "exec\"print 'A' \nfor i in 1,2,3: print i \"" - kxr
3
这确实回答了问题,但语言本身由于没有能力而自我批评。你在抨击传达信息的人。 - WestCoastProjects
显示剩余16条评论

74
您可以使用内置的exec语句,例如:
exec("try: \n \t if sam[0] != 'harry': \n \t\t print('hello',  sam) \nexcept: pass")

其中 \n 表示换行符,而 \t 则是缩进(一个制表符)。
同时,您需要计算使用的空格,以确保缩进完全匹配。

然而,正如其他答案所说,这当然只能在真正必须将其放在一行上时才使用。

exec 语句非常危险(尤其是在构建 Web 应用程序时),因为它允许执行任意 Python 代码。


6
谢谢!这个应该标记为正确答案,因为它实际上有效,不像其他答案。但是,当然,在必要的情况下才这样做!然而,我确实需要这个语法,因为我必须将脚本输入到一个固定的单行文本框中。 - Sanjay Manohar
谢谢!救命稻草!我在脚本中不使用这个,但在交互式 shell 中,这对于调试非常有用...我经常简单地退出交互式 shell 并重新启动它以获得一个干净的环境,然后我必须重复某些步骤,即导入一个模块、运行一些函数,然后使用特定的函数进行一些测试。所以,我正在寻找一种方法将“导入一个模块、运行一些函数”放在一行中,这样我就可以快速从历史记录中调用它并运行它(而不是从历史记录中调用 5 个不同的项目)+1 - oneindelijk
exec("try: \n if sam[0] != 'harry': print('hello', sam) \nexcept: pass") - kxr
谢谢kxr :) (我使用了你的想法来改进答案) - eprovst

27

现在你可以只使用分号。但是,你不能使用if/elif/else语句、for/while循环,也不能定义函数。主要用途是在使用导入的模块时,你不必定义任何函数或使用任何if/elif/else/for/while语句/循环。

这里有一个例子,它获取歌曲的艺术家、歌曲名称,并搜索Genius的歌词:

import bs4, requests; song = input('Input artist then song name\n'); print(bs4.BeautifulSoup(requests.get(f'https://genius.com/{song.replace(" ", "-")}-lyrics').text,'html.parser').select('.lyrics')[0].text.strip())

11

我不鼓励这样做,但是如果你在命令行上,只有Python,并且真的需要一个一行代码的解决方案,你可以这样做:

python -c "$(echo -e "a=True\nif a : print(1)")"

在此,我们正在评估Python代码之前进行预处理\n

这太过于hacky了!不要编写这样的代码。


9

对于一个以python -c为导向的解决方案,并且您使用Bash shell,您可以像这个示例一样拥有一个简单的单行语法:

假设您想要执行类似以下内容的操作(与您的示例非常相似,包括except: pass指令):

python -c  "from __future__ import print_function\ntry: import numpy; print( numpy.get_include(), end='\n' )\nexcept:pass\n" OUTPUT_VARIABLE __numpy_path

这样做将无法成功并产生以下错误
  File "<string>", line 1
    from __future__ import print_function\ntry: import numpy; print( numpy.get_include(), end='\n' )\nexcept:pass\n
                                                                                                                  ^
SyntaxError: unexpected character after line continuation character `

这是因为Bash和Python之间存在竞争,解释转义字符\n。为了解决这个问题,可以使用$'string' Bash语法,在Python解释之前强制执行Bash解释\n
为了让示例更具挑战性,我在Python打印调用中添加了一个典型的end=..\n..规范:最终您将能够同时使用Bash和Python的\n解释,每个都在其关注的文本片段上运行。所以最后的正确解决方案是这样的:
python -c  $'from __future__ import print_function\ntry:\n import numpy;\n print( numpy.get_include(), end="\\n" )\n print( "Hello" )\nexcept:pass\n' OUTPUT_VARIABLE __numpy_path

这将产生正确的干净输出,没有错误:
/Softs/anaconda/lib/python3.7/site-packages/numpy/core/include
Hello

注意:这也适用于基于exec的解决方案,因为问题仍然是相同的(Bash和Python解释器的竞争)。

注意2:可以通过将一些\n替换为一些;来解决问题,但它不会始终有效(取决于Python结构),而我的解决方案允许始终将任何经典多行Python程序“单行化”。

注意3:当进行单行处理时,我们始终要注意Python空格和缩进,因为实际上我们在这里并不严格地“单行化”,而是在Bash和Python之间进行适当的混合管理\n转义序列。这就是我们如何处理任何经典多行Python程序的方法。解决方案示例也说明了这一点。


8

我建议不要这样做...

你所描述的并不是一个理解。

Python代码PEP 8风格指南,我推荐使用,对于复合语句有以下说明:

  • Compound statements (multiple statements on the same line) are generally discouraged.

Yes:

      if foo == 'blah':
          do_blah_thing()
      do_one()
      do_two()
      do_three()

Rather not:

      if foo == 'blah': do_blah_thing()
      do_one(); do_two(); do_three()
以下是一个示例理解,以区分它们:

这里是一个样本理解,以区分它们:

>>> [i for i in xrange(10) if i == 9]
[9]

3

实际上这是可能的 ;-)

# Not PEP 8 compatible^
sam = ['Sam',]
try: print('hello', sam) if sam[0] != 'harry' else rais
except: pass

你可以在Python中做很丑的事情,比如:

def o(s):return ''.join([chr(ord(n) + (13 if 'Z' < n < 'n' or 'N' > n else -13)) if n.isalpha() else n for n in s])

这是一个同时提供 ROT13 Caesar加密的函数。


“else raise” 正确吗? - Peter Mortensen
应该是 raise 吗?(在 else 之后。) - Peter Mortensen

1

也许需要使用 "and" 或者 "or"。

在 false 后,我们需要写 "or"。

在 true 后,我们需要写 "and"。

例如:

n = 0

def returnsfalse():
    global n
    n = n + 1
    print("false %d" % (n))
    return False

def returnstrue():
    global n
    n = n + 1
    print("true %d" % (n))
    return True

n = 0
returnsfalse() or returnsfalse() or returnsfalse() or returnstrue() and returnsfalse()

结果:

false 1
false 2
false 3
true 4
false 5

或者像这样。
(returnsfalse() or true) and (returnstrue() or true) and ...

我通过在Google上搜索“如何在一行Python中放置多个语句”来到这里。它没有直接回答问题,但也许其他人需要这个。


1

有一个可能与 PEP 8 兼容的解决方案。

if, else 的解决方案

[print("i equals 9") for i in range(10) if i == 9]

使用列表生成式代替if, else
我认为这可能是一个有用的技巧,已经由ThomasH的评论提出。因此,这是一个严肃的解决方案。 try, except的解决方案。
print("hello", sam) \
    if "sam" in locals() \
    and hasattr(sam, "__getitem__") \
    and 0 < len(sam) \
    and sam[0] != "harry" \
    else None

尝试使用内联if语句处理expect的行为。这行代码专门处理sam[0]的存在,因此无法解决其他通用的try, except情况。

这是一行代码 (=w=)。虽然如果完全写成一行,可能会太长以违背PEP 8 E501。所以这是一个有趣的解决方案。

  • "sam" in locals checks if sam is a valid variable in the current environment;

  • hasattr(sam, "__getitem__") checks if variable sam could be indexed by sam[n];

  • 0 < len(sam) checks if sam have more than zero items;

  • then check sam[0] != "harry".

  • Warning: This should work when type(sam) == list. Other cases were not tested. If you are sure that sam is a list, then the code would not be too lengthy:

    print("hello", sam) if 0 < len(sam) and sam[0] != "harry" else None
    

附加内容

正如其他回答所述(例如,Johnsyweb表示),不推荐在一行上使用多个语句(PEP 8 E701)。因此,对于任何可能的Pythonic(PEP 8)解决方案,单行代码可能必须避免显式 if, elsetry, except

正如Thomash的另一个评论所述,try, except 的更好解决方案应该使用包装函数。这将添加另外一行代码;但是,调用函数不仅可以检查 sam 还可以检查其他变量:

def check_harry(name):
    try:
        print("hello", name) if name[0] != "harry" else None
    except (NameError, TypeError, IndexError):
        pass

check_harry(uncle)
check_harry(sam)

这可能是一个更为严肃的解决方案。请注意,由于PEP 8 E722的缘故,不建议使用裸露的except。尽管这行强制性的except: pass看起来像是浪费时间(我通常也同意 T_T),但其中涉及到一些代码风格的考虑。

1
如果您不想使用 try 和 except,则有解决方案。
如果您正在尝试从列表中打印“hello”如果其中包含“harry”,则解决方案为:
'hello' if 'harry' in sam else ''

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接