2016-08-20 189 views
2

導入模塊的內置功能,我有一個應用程序,我想,當情況發生時替換某些功能,例如:改寫從導入模塊

condition_check.py:

Flag = True 
import ctypes # An included library with Python install. 
import inspect 
def MsgBox(msg): 
    ctypes.windll.user32.MessageBoxA(0, msg, 'MsgBox', 1) 
def check(): 
    global print 
    if Flag: 
     def print(msg): 
       MsgBox(msg) 
    else: 
     pass 

爲主。潘岳:

## works 
from condition_check import * 
MsgBox('this is msgbox') 
print('this is a print') 

## does not work 
import condition_check 
condition_check.MsgBox('this is msgbox') 
print('this is a print') 

我明白condition_check.py是壓倒一切的自己的print代替main.py「 s print。我相信檢查庫可用於此目的,但我無法查找一個示例。

+1

不要有條件覆蓋定義過。這似乎是一個聰明的伎倆,但它肯定會破壞事物,或者至少混淆下一個必須查看代碼的人(包括你)。如果Flag:MsgBox(message)else:print(message)''好得多。變量名'Flag'也是沒有意義的,如果你是Python的新手,忘記了'global',它將會讓你陷入困境。 – msw

+0

不幸的是我打算main.py不知道它使用的某些函數被覆蓋。 – user1502776

回答

1

我假設你正在使用Python 3.如果你是,你只需要設置內置模塊的屬性。

import builtins 
import ctypes 

original = builtins.print 
Flag = True 

def MsgBox(msg): 
    ctypes.windll.user32.MessageBoxA(0, msg, 'MsgBox', 1) 

def check(): 
    if Flag: 
     builtins.print = MsgBox 
    else: 
     builtins.print = original 

我會注意,但是,有兩件事情:

  1. Flag是不是有兩個原因一個好聽的名字:,它是不是在所有的描述。一面旗幟僅僅意味着它是TrueFalse;它沒有說明它的用途。 Python的官方風格指南(PEP 8)推薦使用snake_case,而不使用PascalCase作爲常規變量。 PascalCase只能用於類。

  2. PEP 8不推薦使用通配符導入(from <module> import *),因爲它們使命名空間中的名稱不清楚,導致讀者和自動化工具混淆。 (幾乎與Imports一節中的確切引用相同。)

  3. 您不需要覆蓋print函數。更好的方法是重寫sys.stdout到控制通向哪裏流:

    import ctypes 
    import sys 
    
    def MsgBox(msg): 
        ctypes.windll.user32.MessageBoxA(0, msg, 'MsgBox', 1) 
    
    class Printer: 
        def __init__(self, original, alternate, use_alternate): 
         self.original = original 
         self.alternate = alternate 
         self.use_alternate = use_alternate 
    
        def write(self, msg): 
         if self.use_alternate: 
          return self.alternate(msg) 
         return self.original(msg) 
    
    sys.stdout = printer = Printer(sys.stdout.write, MsgBox, True) 
    

    你的標誌,然後printer.use_alternate。除了易於控制之外,這也與Python 2兼容,即使Python 2 print是一個聲明。這確實有保持該print添加新行的輕微的缺點,但一個隨時可以使用的東西的alternatelambda msg: MsgBox(msg.strip())

+0

感謝您擴大我的評論。儘管如此,我對你建議的sys.stdout的覆蓋感到困惑。一旦掌握了一個打印機實例,'printer.write(msg)'不會比'遠處的操作'更重要嗎?您的建議獲得90%的方式,然後使用全球範圍確保混淆。 (無論如何+1) – msw

+1

@msw:當然'printer.write(msg)'更清晰,但OP在對他不想'main'的問題的評論中提到。py'知道它的消息正在被重定向。 – zondo

+0

至於全局變量,我不認爲這是一個必要的問題。類和函數通常是全局的。全局變量的問題是當它們泄漏到其他名稱空間中時。但是,例如,正確導入的'condition_check'將使用'condition_check.printer.use_alternate = False'。我沒有看到這個問題。 – zondo