2012-08-14 40 views
4

我要完成什麼定義函數:動態有不同的簽名

dct = {'foo':0, 'bar':1, 'baz':2} 
def func(**dct): 
    pass 
#function signature is now func(foo=0, bar=1, baz=2) 

然而,**語法明顯衝突拓展業務的字典(就是我想要做的),並宣佈持有參數之間關鍵字參數(我不想做的)。

這可能嗎?

回答

5

根據我對您的要求的解釋 - 您希望動態定義一個功能,其簽名與運行時提供的dict的內容相匹配 - 這裏有兩個問題,這使得它不切實際。

  1. 如果參數是在運行時定義的,函數如何引用變量?您是否打算在運行時構建函數體?
  2. dict s爲無序的,所以你不能可靠地使用它們來定義位置參數

我懷疑這是一個XY problem。如果你能解釋你想達到的目標,那麼或許我們可以得到更好的幫助。

然而,假設你想使用dict,其中一個方法來實現這一目標是使用decorators指定默認的關鍵字參數。例如:

def defaultArgs(default_kw): 
    "decorator to assign default kwargs" 
    def wrap(f): 
     def wrapped_f(**kwargs): 
      kw = {} 
      kw.update(default_kw) # apply defaults 
      kw.update(kwargs) # apply from input args 
      f(**kw) # run actual function with updated kwargs 
     return wrapped_f 
    return wrap 

然後,您可以使用此裝飾指定默認的關鍵字參數給需要只有關鍵字參數的函數:

defaults = {'foo':0, 'bar':1, 'baz':2} 

@defaultArgs(defaults) 
def func(**kwargs): 
    print kwargs # args accessible via the kwargs dict 

結果:

func() # prints {'baz': 2, 'foo': 0, 'bar': 1} 
func(foo=2) # prints {'baz': 2, 'foo': 2, 'bar': 1} 

params = {'bar':1000, 'hello':'world'} 
func(**params) # prints {'baz': 2, 'foo': 0, 'bar': 1000, 'hello': 'world'} 

請注意,您不能使用位置參數:

func(1, 2, 3) # raises TypeError 
+0

感謝您的回答,它幫助我完成了我想要做的事情。正如你所說,我認爲它是一個XY問題;我只是以錯誤的方式去做事。自從上次我記得類似這樣的事情發生時,我第一次在編程和學習Java的初學者,然後因爲沒有轉向而感到憤怒,這真讓我感到有些驚訝。聲明(當我的問題有其他更好的解決方案時)。 – Lanaru 2012-08-14 16:36:14

+1

很高興你找到了解決方案!我們都處於這個位置,有時只需要溫和地提醒我們退後一步,重新解決問題。 – 2012-08-14 16:49:50

0

我真的不知道你打算在這裏完成什麼。以下作品(排序):

def func(**dct): 
    pass 

dct = {'foo':0, 'bar':1, 'baz':2} 
func(**dct) 

你打算如何在功能使用foobarbaz如果他們動態創建?如果您提供一些關於您實際嘗試完成的更多細節,我們可能會更有幫助。