[英]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.