2016-11-15 38 views
6

作爲問題問,裏面的工作爲什麼不下面的代碼工作:爲什麼不執行exec(「突破」)while循環

while True: 
     exec("break") 

我通過Python 3.5執行上述pycharm。 2控制檯。 我最初認爲這是一個上下文問題,但在閱讀文檔後,我還沒有接近理解爲什麼會出現此錯誤。

SyntaxError: 'break' outside loop 

感謝提前:)

編輯:我明白,這工作沒有執行exec()順便說一下,我很好奇,爲什麼它不會以exec工作(如需要我的情況它) - 全面的答案歡迎。沒有EXEC

+0

'exec'是一個函數,'break'應該直接在循環中。 – user2728397

回答

3

這是因爲exec()是無知的你周圍while循環。因此,exec()在您的示例中看到的唯一聲明是break。而不是使用exec("break"),只需按原樣使用break即可。

唯一訪問exec()函數有它的周圍範圍,是globals()locals()字典。 The documentation for exec()提供了exec()如何工作的一些見解:

此函數支持動態執行Python代碼。對象必須是字符串或代碼對象。如果它是一個字符串,則將該字符串解析爲一組Python語句,然後執行該語句(除非發生語法錯誤)。 [1]如果它是一個代碼對象,它只是被執行。在任何情況下,執行的代碼都應該作爲文件輸入有效(請參見參考手冊中的「文件輸入」部分)。請注意,即使在傳遞給exec()函數的代碼的上下文中,return和yield語句也可能不在函數定義之外使用。返回值是None。

在任何情況下,如果省略可選部件,則代碼將在當前範圍內執行。如果只提供全局變量,則它必須是一個字典,它將用於全局變量和局部變量。如果給定全局變量和局部變量,它們分別用於全局變量和局部變量。如果提供,本地人可以是任何映射對象。請記住,在模塊級別,全局變量和本地變量是相同的字典。如果exec獲取兩個單獨的對象作爲全局變量和局部變量,那麼代碼將被嵌入類定義中執行。

如果全局變量字典不包含鍵builtin的值,則對該內置模塊的內置字典的引用將插入到該鍵下。通過這種方式,您可以在將它傳遞給exec()之前,將自己的builtins字典插入到全局變量中,從而控制可執行代碼可用的內建函數。

+0

所以這是一個上下文問題?有沒有辦法在當前命名空間/上下文中使用exec執行? – Sighonide

+0

@Sighonide據我所知,沒有。 exec()只能訪問全局變量,而不能訪問語句。請問爲什麼你需要這個? –

+0

那是不幸的哈哈。我打算用它將字符串格式的命令傳遞給另一個進程,這將在該進程中操作循環和其他事物。 – Sighonide

0

嘗試突破():

while True: 
    break 
+0

OP說他需要知道原因。你的回答沒有解釋它。 – user2728397

+0

@leaf嗯,我明白他不能評論,但這是一個非常低質量的答案。 – user2728397

2

exec語句獨立於代碼的其餘部分運行一段代碼。

因此,該行:

exec("break") 

,無異於叫break突然冒出來,在一個腳本,沒有什麼事情發生,並在不存在環路。

調用break說法正確的做法是:

while True: 
    break 

編輯

從葉的評論讓我想想。

實際上,exec聲明不會從無處運行代碼。

>>> i = 12 
>>> exec("print(i)") 
12 

一個更好的答案,因爲據我所知,是exec運行在同一環境作爲原代碼的一段代碼,而是獨立於它。

這基本上意味着調用exec時刻存在的所有變量可用於由exec調用的代碼。但上下文都是新的,所以return,break,continue和其他需要上下文的語句將不起作用,除非創建了正確的上下文。

順便說一下,在談到exec時,我保留「聲明」一詞,但它已經成爲Python3中的一個函數,與print一樣。

+0

@leaf感謝您的思考;) –

+0

.....歡迎;) –

1

exec是一個內置的功能,

的Python堅持break應該發生內循環,而不是內部的function

什麼在你的代碼的情況是你把break一個function裏面是exec通過在循環內部調用的函數內執行 break,您無法擺脫循環。

對於防爆

>>> def func(): 
     break 
SyntaxError: 'break' outside loop 
>>> 
2

exec()是一個函數。假設該函數調用構成其自身的陳述(就像在你的例子)簡單,它可以通過以下方式之一結束:

  1. 功能正常返回 - 在這種情況下,根據下面的語句到控制流程執行;

  2. 引發異常/從功能拋出 - 在這種情況下,調用堆棧上匹配except條款(如果有的話)被執行

  3. 整個程序被終止,因爲該顯式調用退出( )或同等學歷 - 沒有什麼可執行的。

調用從內部exec()將修改的方式,是與該函數調用的語義的所描述的方面不兼容的程序執行流程的break(以及returnyield)。

注意the documentation on exec()包含在裏面exec()使用returnyield特別說明:

請注意,returnyield陳述可能不外部函數定義 甚至代碼的上下文中使用傳遞給 exec()函數。

類似的限制適用於break聲明(與它可能不被外部循環被使用的比較),我不知道爲什麼它沒有被列入的文件中。

+0

是的,'break'也應該直接在循環中,而不是像'exec'這樣的函數內部。 – user2728397