2014-03-06 95 views
0

我在這裏有一些有趣的請求。假設我有一個名爲Object的類,它有兩個方法,func1()和func2()。第二種方法調用func1(),儘管我希望能夠改變func1()的函數定義,以便能夠區分從func2()內被調用作爲我的Object類的獨立方法,就像這樣:在一個類內調用python函數

obj = Object() 
obj.func1() 

我可以簡單地創建函數的兩個版本(一個私有方法,用於FUNC2()來使用,並且用戶能夠訪問一個公共的方法;是的,我知道,在蟒蛇真的有不是私人的,但是我認爲正常的命名約定,我可以明確表示它只是一個內部函數)。但是這需要相當多的冗餘,而且我想盡可能避免。有沒有人可以推薦這種類型的機制或策略?

例如,我知道如果我希望我的整個腳本object.py執行一組特定的代碼(如果只作爲獨立腳本運行的話)(即它不會被導入到另一個腳本的頂部),我會做:

if __name__ == "__main__": 
    ... 
    code to run if standalone 
    ... 

我想知道是否有一個類的方法類似的策略。

+1

這是不可能的,不可能以非hacky的方式。你爲什麼覺得你需要這樣做?除了創建單獨的方法之外,另一種可能性是向函數添加一個參數,func2可以在調用它來指示「內部」使用時使用該參數。 – BrenBarn

+1

訣竅是將冗餘代碼分解爲兩個可以使用的單獨「通用」函數。 – mgilson

+0

我覺得我需要這樣做,因爲以某種方式調用,我想生成終端輸出,而如果此功能在內部調用,我希望它放棄打印到終端。 – astromax

回答

1

您可以使用sys._getframe()並根據來電者決定要做什麼。 f_code.co_name的函數返回

import sys 

class MyClass(object): 
    def func1(self): 
     frame = sys._getframe(1) 
     if frame.f_code.co_name == 'func2': 
      print "called from func2" 
     else: 
      print "called from elsewhere" 
    def func2(self): 
     self.func1() 

c = MyClass() 
c.func1() 
c.func2() 
+0

你願意做一個準系統的例子嗎? 2個實現這個功能的功能? – astromax

+0

@astromax看到的例子添加到我的答案 – wolfrevo

+0

偉大的,這正是我需要的!謝謝!既然你先回答我想我必須給你對號。 – astromax

2

您也可以使用inspect這樣的:

import inspect 

def func2(): 
    if inspect.stack()[1][3] == "func1": 
     #...do something... 
    else: 
     #...do something else... 

def func1(): 
    return func2() 

詳情請參見官方文檔:

http://docs.python.org/2/library/inspect.html

+0

太棒了,這正是我一直在尋找的!謝謝! – astromax

1

通過閱讀您的意見,似乎你的實際問題是這樣的:你有一個打印輸出的方法。如果用戶調用代碼,那麼您希望將該輸出打印到終端。如果代碼是通過其他方法在內部調用的,則不希望輸出被打印。

@mgilson建議的debug arg是一個不錯的選擇,但您寧願用戶不知道該選項,無論出於何種原因。

另一種方法是在函數調用期間使函數包裝器重定向stdout,然後再恢復它。事情是這樣的:

import os 
import sys 

def suppress_print(f, *args, **kwargs): 
    """Call the function f, but print to the null device 
    instead of the screen.""" 
    old_stdout = sys.stdout 
    sys.stdout = open(os.devnull, 'w') 

    result = f(*args, **kwargs) 

    sys.stdout = old_stdout 

    return result 

class Foo: 

    def bar(self): 
     print "This is a test." 
     return 42 

    def baz(self): 
     return suppress_print(self.bar) 


foo = Foo() 

# this should print to the terminal 
foo.bar() 

# this shouldn't 
foo.baz() 

之後,當內部調用函數,你suppress_print紙包起來,然後輸出將被壓扁。請注意,這實際上是一個使用上下文管理器的好地方,但我將其留作進一步的練習...