2011-04-19 67 views
1

有沒有比使用inspect模塊更清晰的方法來獲取方法的默認值?我想這樣做:默認方法python

class C(object): 
    def __init__(self,Type='generic',X=5,Y=500): 
     defaults=getDefaults() #not sure about this line 
     typeDefaults_X={'short':'1','long':'10'} 
     typeDefaults_Y={'large':2000,'small':100} 
     if X == defaults['X']: 
      X = typeDefaults_X.get(Type, defaults['X']) 
     if Y == defaults['Y']: 
      Y = typeDefaults_Y.get(Type, defaults['Y']) 

我知道我可以做到這一點:

defaults=dict(zip(inspect.getargspec(C.__init__).args[1:],inspect.getargspec(C.__init__).defaults)) 

但似乎如此可怕未Python的。

+0

有什麼意義?你想做什麼? – 2011-04-19 01:12:40

+1

你會想'=='而不是'is';例如注意'100000 + 1是100000 + 1'是假的,但是'100 + 1是100 + 1'是真的。 – ninjagecko 2011-04-19 01:32:48

+0

你的代碼說的是「如果我們不爲argN輸入任何內容,將其設置爲lookupTable [typeString];如果失敗,將其設置爲默認值」。不幸的是,這個接口沒有意義,因爲你只有1個typeString參數,但你的變量似乎都依賴於它,並且它們都有不同的鍵的單獨查找表。你想做什麼? – ninjagecko 2011-04-19 01:35:57

回答

1

這不是真的我清楚你正在嘗試做的。但是在該方法中,變量已經具有指定的默認值。但在我看來,在這種情況下你最好不要使用正式的默認參數。

class C(object): 

    def __init__(self, Type='generic', X=None, Y=None): 
     X = X or 5 
     Y = Y or 500 
     self.X, self.Y = { 
      "generic": (X, Y), 
      "short": (1, Y), 
      "long": (10, Y), 
      "large": (X, 2000), 
      "small": (X, 100), 
     }[Type] 

    def __str__(self): 
     return "X={0} Y={1}".format(self.X, self.Y) 


print(C()) 
print(C('short')) 
print(C('long')) 
print(C('large')) 
print(C('small')) 
print(C('small', 10)) 
print(C('small', 20, 20)) 

我覺得更清楚,但即使這樣可能有點難以遵循。您可能會重新考慮您的界面。

+0

謝謝,我認爲這可以工作。理想情況下,我想在這裏保留正式的默認參數(帶值)。我正在重新思考....也許孩子班? – 2011-04-19 18:04:51

+0

@亞當正是我在想什麼。 :-)通常,如果您看到基於某個標誌改變行爲的方法,它應該被重構爲子類。 – Keith 2011-04-19 18:49:14

0

它實際上比您想象的要糟糕。 Python區分位置參數與默認值和僅關鍵字參數。您的代碼不僅會在您沒有默認作爲第二或第三個參數的情況下失敗,而且如果您有可變長度的* args關鍵字,則代碼也會失敗。你也應該使用inspect.getfullargspec。

但是,根據help(inspect.getfullargspec),spec.defaults總是spec.args的最後一個元素。因此,你可以這樣做:

import inspect 
def getDefaults(func): 
    spec = inspect.getfullargspec(func) 
    numDefaults = len(spec.defaults) 
    return dict(zip(spec.args[-numDefaults:], spec.defaults), **spec.kwonlydefaults) 

基本上,這正是你所做的,但更一般。

沒有更好的辦法。 (當然你可以使用func.__defaultsfunc.__kwdefaults__func.__code__.co_*,但這些都是真正的hackish,似乎一種內部的,檢查是正確的做法。)

+0

附錄:這似乎實際上是'pythonic'的定義:有一種方法可以做到這一點;這並不是說它不能大規模改善,仍然是'pythonic' – ninjagecko 2011-04-19 01:18:02