2012-10-11 102 views
5

經過一番閱讀後,我發現自己正在努力用兩種不同的方法將參數列表傳遞給函數。我讀了一些跡象。這就是我想通了,至今:傳遞和處理函數參數的最佳方法

實際代碼:

文件caller.py:

import worker 
worker.version_check(iserver,login,password,proxyUser,proxyPass, 
    proxyServer,packageInfo) 

worker.version_get(iserver,login,password,proxyUser,proxyPass, 
    proxyServer,packageInfo) 

worker.version_send(iserver,login,password,proxyUser,proxyPass, 
    proxyServer,packageInfo) 

文件:worker.py:

def version_check(iserver,login,password,proxyUser,proxyPass,proxyServer,service): 
    #code and more code 

def version_get(iserver,login,password,proxyUser,proxyPass,proxyServer,service): 
    #code and more code 

def version_send(iserver,login,password,proxyUser,proxyPass,proxyServer,service): 
    #code and more code 

現在我有:

file caller.py:

import worker 
args = (env, family, host, password, prefix, proxyServer, 
     proxyUser, proxyPass, option, jokerVar 
     ) 
worker.version_check(*args) 
worker.version_get(*args) 
worker.version_send(*args) 

文件:worker.py:

def version_check(*args): 
    env = args[0] 
    family = args[1] 
    host = args[2] 
    password = args[3] 
    prefix = args[4] 
    proxyServer = args[5] 
    proxyUser = args[6] 
    proxyPass = args[7] 
    option = args[8] 
    jokerVar = args[9] 

    #code and more code 

def version_get((*args): 
    env = args[0] 
    family = args[1] 
    host = args[2] 
    password = args[3] 
    prefix = args[4] 
    proxyServer = args[5] 
    proxyUser = args[6] 
    proxyPass = args[7] 
    option = args[8] 
    jokerVar = args[9] 

    #code and more code 

def version_send(*args): 
    env = args[0] 
    family = args[1] 
    host = args[2] 
    password = args[3] 
    prefix = args[4] 
    proxyServer = args[5] 
    proxyUser = args[6] 
    proxyPass = args[7] 
    option = args[8] 
    jokerVar = args[9] 

    #code and more code 

使用老方法(實際的代碼),我相信這是更「友好」來稱呼在只有一條線的功能(你可以在worker.py看到)。但是,使用新方法,我認爲代碼變得更加廣泛,因爲對於每個函數,我必須定義所有相同的變量。但這是最佳做法嗎?我仍然在慢速學習Python,所以,對於代碼中的任何錯誤感到抱歉。

而且一件重要的事情是,大部分變量都是從數據庫中檢索出來的,所以它們並不穩定。

+5

一般來說,當你結束了與許多參數的函數,你需要考慮你的設計更多一些。傳遞一個對象比那麼多參數要好? –

+0

@MartijnPieters有可能給我一個例子嗎?同時我會嘗試在s.o上找到它。和python文檔。 –

+1

這組參數代表什麼?可以命名嗎?如果是這樣,使它成爲一個名爲tuple或自定義類來保存該信息,那麼你有一個對象來傳遞,而不是x個單獨的參數。 –

回答

6

我真的不建議定義諸如def version_check(*args):除非您特別需要到的功能。快速,沒有閱讀來源:參數的順序是什麼?你如何爲proxyServer指定一個默認值?請記住,「明確比隱含更好」。

的一個時間我經常從規則偏離是,當我包裝像另一個功能:

def foo(bar): 
    print 'Bar:', bar 

def baz(qux, *args): 
    print 'Qux:', qux 
    foo(*args) 

我從來沒有做這樣一個簡單的例子,但假設foo是從功能我的控制之外的第三方軟件包有很多默認值,關鍵字參數等。在這種情況下,我寧願將參數解析爲Python而不是自己嘗試。

就個人而言,我會寫像類:

class Worker(object): 
    def __init__(iserver,login,password,proxyUser,proxyPass,proxyServer,service): 
     self.iserver = iserver 
     self.login = login 
     self.password = password 
     self.proxyUser = proxyUser 
     self.proxyPass = proxyPass 
     self.proxyServer = proxyServer 
     self.service = service 

    def version_check(self): ... 

    def version_get(self): ... 

    def version_send(self): ... 

然後在客戶端,寫:

from worker import Worker 

w = Worker(iserver,login,password,proxyUser,proxyPass,proxyServer,service) 
w.version_check() 
w.version_get() 
w.version_send() 

如果你真的需要有很多的參數寫入功能,而不是把這個狀態封裝在一個類中 - 這是一種更典型的Pythonic方法 - 然後考慮最近的Python版本的namedtuple數據類型。它可以讓你指定一個元組,其中的項目可以通過關鍵字尋址,並且可以製作一些非常乾淨優雅的代碼。

+0

+1!這是一個很好的答案。你給出了同樣的解決方案(將函數和數據封裝在一個類中),並給出了一個非常明確的解釋,說明爲什麼原始版本不好。 – Blckknght

+0

+1你也可以[創建多個對象](http://stackoverflow.com/questions/12844963/best-approach-to-pass-and-handle-arguments-to-function#comment17382149_12844963) – jfs

+0

@Blckknght謝謝!我試試。 :-) –

0

您可以創建對象的實例或定義一個類。例如

文件caller.py:

import worker 

info=object() 
info.env=0 
info.family='something' 
info.host='something' 
info.password='***' 
info.prefix='' 
info.proxyServer='' 
info.proxyUser='' 
info.proxyPass='' 
info.option='' 
info.jokerVar='' 

worker.version_check(info) 
worker.version_get(info) 
worker.version_send(info) 

文件worker.py:

def version_check(info): 
    #you may access values from info 
    #code and more code 

def version_get(info): 
    #code and more code 

def version_send(info): 
    #code and more code 
+0

你不能直接在'object'上設置任意屬性。可以使用'class Info:pass'來代替。無論如何,這個approuch並不比使用關鍵字參數更好,參見[@Francis'答案中的項目1](http://stackoverflow.com/a/12847386/4279) – jfs

2

有很多方法,取決於這些參數代表什麼。

  1. 如果他們只是參數(尤其是如果有些是可選擇的)一個抓鬥袋,使用關鍵字參數

    myargs = {'iserver':'server','login':'username','password':'Pa2230rd'} 
    version_get(**myargs) 
    
  2. 如果他們代表了自己的狀態的一些事情,然後使用

    1. 如果參數代表一個國家,你的FUNC蒸發散正在修改,然後接受在對象構造函數中的參數,使您version_*方法該類的功能:

      class Version(object): 
          def __init__(self,iserver,login,password, 
             proxyUser,proxyPass,proxyServer,service): 
           self.iserver = iserver 
           self.login = login 
           #etc 
          def check(self): 
           self.iserver 
          def get(self): 
           pass 
          #etc 
      myversion = Version('iserver','login',...) 
      myversion.check() 
      
    2. 如果你擁有某種資源的這些參數代表的功能僅僅是使用,在這種情況下,使用一個單獨的類,並提供其作爲一個對象參數到您的功能:

      class Connection(Object): 
          def __init__(self, iserver, ...): 
           self.iserver # etc 
      
      myconn = Connection('iserver',...) 
      
      version_check(myconn) 
      
    3. 最有可能的,這是兩個不同的資源,應該是兩班。在這種情況下,你可以結合這些方法:

      #Connection() class as above 
      class Version(object): 
          def __init__(self, connection): 
           self.connection = connection 
          def check(self): 
           self.connection.iserver # .... 
      
      myconn = Connection('iserver', ...) 
      conn_versioner = Version(myconn) 
      conn_versioner.check() 
      
    4. 可能的話,你的論點代表多個對象(例如,一個連接和一個透明代理對象),在這種情況下,嘗試創建具有最小的公共對象像version_*這樣的接口方法需要使用對象組合來封裝由其他參數表示的狀態。

      舉例來說,如果你有代理連接,您可以創建一個Connection()類,它只是知道服務器,登錄名和密碼,並且具有Connection的所有方法ConnectionProxy()類,但轉發到另一個Connection對象。這使您可以分開參數proxy*,這意味着您的功能可能不知道他們是否使用代理服務器。

  3. 如果你的論點是隻是狀態,沒有適當的給他們的任何方法,可以考慮使用namedtuple()。這將像一個更聰明的元組(包括元組拆包,切片等),並且對現有代碼的影響最小,同時仍然更易於使用。

    Connection = namedtuple('Connection', 'iserver login password etc') 
    myconn = Connection('iserver', 'loginname', 'passw3rd') 
    version_check(*myconn) 
    
相關問題