2016-09-13 69 views
1

我正在python 3.x中寫一個python腳本,我需要重新定義print函數。當我在我的口譯員那裏工作時,它工作正常。但是當我使用相同的代碼創建一個函數時,它會發出錯誤。重定義打印功能不能在一個函數內工作

這裏是我的代碼:

list = ["print('Wow!')\n", "print('Great!')\n", "print('Epic!')\n"] 
old_print = print 

def print(s): 
    global catstr 
    catstr += s 

catstr = "" 
for item in list: 
    s = item 
    exec(s) 
print = old_print 

catstr 
>> 'Wow!Great!Epic!' 

正如你可以看到我已經得到了我想要的結果:'Wow!Great!Epic!'

現在我讓使用相同的代碼的函數:

def execute(list): 
    old_print = print 
    def print(s): 
     global catstr 
     catstr += s 
    catstr = "" 
    for item in list: 
     s = item 
     exec(s) 
    print = old_print 
    return catstr 

現在當我使用以下代碼運行此功能:

list = ["print('Wow!')\n", "print('Great!')\n", "print('Epic!')\n"] 

execute(list) 

我得到以下錯誤:

old_print = print 
UnboundLocalError: local variable 'print' referenced before assignment 

有誰知道爲什麼這是不是一個函數內的工作?
任何建議如何解決它將不勝感激。

+0

這是第一行,你定義打印在函數中,作爲一個函數,你在使用old_print等什麼? –

+1

你的問題的目的是什麼?或者這只是出於好奇? – BPL

+0

@BPL這是直接相關的作爲他們昨天問的後續問題[這裏](http://stackoverflow.com/questions/39460882/how-to-get-execution-of-python-print-statements-as-a -string) – idjaw

回答

2

所有你需要的是外地和所有已創建欄catstr其他變量忘記:

def execute(lst): 
    def print(s): 
     nonlocal catstr 
     catstr += s 
    catstr = "" 
    for item in lst: 
     s = item 
     exec(s) 
    return catstr 

這就給了你:

In [1]: paste 
def execute(lst): 
    def print(s): 
     nonlocal catstr 
     catstr += s 
    catstr = "" 
    for item in lst: 
     s = item 
     exec(s) 
    return catstr 

## -- End pasted text -- 

In [2]: list = ["print('Wow!')\n", "print('Great!')\n", "print('Epic!')\n"] 

In [3]: execute(lst) 
Out[3]: 'Wow!Great!Epic!' 

凡是發生在功能本地的功能,所以你不必擔心重置任何東西。如果您確實想要設置打印參考,則可以使用old_print = __builtins__.print

如果你想擁有你的函數打印,而無需打印通話使用__builtins__.print做印刷:

def execute(lst): 
    catstr = "" 
    def print(s): 
     nonlocal catstr 
     catstr += s 
    for s in lst: 
     exec(s) 
    __builtins__.print(catstr) 
+1

謝謝!它的工作:) – Elisha512

+0

不用擔心,我添加了一個變化,行爲像印刷即它返回None,只是打印 –

2

譯員不會識別print作爲內置函數,除非您特別說明。而不是宣佈它是全球性的,只需將其刪除(感謝Padraic Cunningham):當地print將採用您所需的定義,並且全球從未受到影響。

您還有一個前向參考問題catstr。下面的代碼會引出所需的輸出。

catstr = "" 
def execute(list): 

    def print(s): 
     global catstr 
     catstr += s 

    for item in list: 
     s = item 
     exec(s) 
    print = old_print 
    return catstr 

list = ["print('Wow!')\n", "print('Great!')\n", "print('Epic!')\n"] 

print (execute(list)) 
+0

剛剛刪除'old_print = print'等..會給你完全相同的輸出 –

+1

對!本地**打印**不會影響內置。 – Prune

1

你的問題已經被修剪和帕德里克·坎寧安答覆中已經解決,這裏是另一種替代的方式來實現(我猜)你想要什麼:

import io 
from contextlib import redirect_stdout 

g_list = ["print('Wow!')\n", "print('Great!')\n", "print('Epic!')\n"] 


def execute(lst): 
    with io.StringIO() as buf, redirect_stdout(buf): 
     [exec(item) for item in lst] 
     return buf.getvalue() 


def execute_modified(lst): 
    result = [] 
    for item in lst: 
     with io.StringIO() as buf, redirect_stdout(buf): 
      exec(item) 
      result.append(buf.getvalue()[:-1]) 

    return "".join(result) 


print(execute(g_list)) 
print('-' * 80) 
print(execute_modified(g_list)) 

輸出:

Wow! 
Great! 
Epic! 

-------------------------------------------------------------------------------- 
Wow!Great!Epic! 
+0

這將所有的數據放在不同的行,*期望的結果*是「哇!偉大!史詩!」 –

+0

@PadraicCunningham你讓我在那裏:P。我編輯了我的答案......雖然我對我提出的解決方案並不滿意,但歡迎提供建議 – BPL