繁体   English   中英

列出在Python 3中具有嵌套ifs的理解变量范围

[英]list comprehension variable scope with nested ifs in python 3

基于这个答案和事实,列表理解不再在Python 3.x中“泄漏”其变量了,我如何在Python 3中实现/重写此表达式?

>>> import sys
>>> sys.version[:5]
'3.6.5'
>>> import psutil
>>> psutil.__version__
'5.4.7'
>>> [port.laddr.port for proc in psutil.process_iter(attrs=['name']) if 'sshd' in proc.info['name'] if any([port.status == psutil.CONN_LISTEN for port in proc.connections()])]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <listcomp>
NameError: name 'port' is not defined

首先,从风格上说,列表理解是很不容易的。 试图阅读它的人完全无法理解。 缩进是您的朋友,而代码行的数量也不是问题。 更改缩进使其更具可读性:

ports = [
    port.laddr.port
    for proc in psutil.process_iter(attrs=['name'])
    if 'sshd' in proc.info['name']
    if any([port.status == psutil.CONN_LISTEN for port in proc.connections()])
]

现在,问题变得很明显。 列表推导不会泄漏其在Python 3中的作用域。在ports列表推导之外(如果它不会因NameError而失败),将没有名为proc对象。

就是说,您确实会收到名称错误,因为对any的调用中的列表理解不会泄漏其范围。 没有任何port变量会在父列表理解之外进行转义,并且会出现NameError

其次,要解决您的问题,您可能应该完全避免列表理解。 您试图在一个语句中做太多事情 创建ports列表。 for循环中遍历您的进程,并根据所需的逻辑进行append

展示:

ports = []
def validate_proc(proc):
    return any(
        port.status == psutil.CONN_LISTEN
        for port in proc.connections()
    )
for proc in in psutil.process_iter(attrs=['name']):
    if not 'sshd' in proc.info['name']:
        continue
    if not validate_proc(proc):
        continue
    for port in proc.connections():
        ports.append(port.laddr.port)

在这里,我假设如果任何端口都符合给定条件,则您需要给定进程的所有端口,否则就不希望它们。 这就是我阅读您的理解的方式。 如果这不是您想要的,那么我可以更改它。 (这是为什么应避免使用大列表理解的具体示例。)

您可以使用适当限定的理解来查找相关端口,而不是使用any期望列表理解变量泄漏出去的方法。

我将其分为两个理解层,因此适合我的大脑。

procs = [proc for proc in psutil.process_iter(attrs=['name'])
         if 'sshd' in proc.info['name']]
ports = [port.latter.port for proc in procs
         for port in proc.connections() if port.status==psutil.CONN_LISTEN]

print(ports)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM