簡體   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