繁体   English   中英

传递和处理函数参数的最佳方法

[英]Best approach to pass and handle arguments to function

经过一些阅读,我发现自己正在努力使用两种不同的方法将一个参数列表传递给一个函数。 我读了一些迹象。 这就是我到目前为止所知道的:

实际代码:

file 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,所以,对不起代码中的任何错误。

还有一件重要的事情是,大多数变量都是从数据库中检索出来的,所以它们并不是一成不变的。

我真的不建议定义def version_check(*args):等函数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数据类型。 它允许您指定一个元组,其中的项目可以通过关键字进行寻址,并且可以生成一些非常干净,优雅的代码。

有许多方法,取决于这些参数代表什么。

  1. 如果它们只是一个参数包(特别是如果有些是可选的),请使用关键字参数

     myargs = {'iserver':'server','login':'username','password':'Pa2230rd'} version_get(**myargs) 
  2. 如果它们用自己的状态表示某些东西,那么使用

    1. 如果参数表示您的函数正在修改的单个状态,则接受对象构造函数中的参数并生成该类的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()类,它只知道服务器,登录名和密码,以及一个ConnectionProxy()类,它具有Connection所有方法,但转发到另一个Connection对象。 这允许您分离proxy*参数,这意味着您的version_*函数可能不知道他们是否正在使用代理。

  3. 如果您的参数只是状态并且没有适合它们的任何方法,请考虑使用namedtuple() 这将像一个更聪明的元组(包括元组解包,切片等),对现有代码的影响最小,同时仍然更容易使用。

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

您可以创建实例对象或定义类。 例如

file 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM