5

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

实际代码:

文件调用者.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

现在我有:

文件调用者.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,因此,对于代码中的任何错误,我深表歉意。

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

4

3 回答 3

6

我真的不建议定义函数,def version_check(*args):除非你特别需要。快速,无需阅读源代码:参数的顺序是什么?如何为 proxyServer 指定默认值?请记住,“显式胜于隐式”。

我经常偏离该规则的一次是当我包装另一个函数时:

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

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

对于这样一个简单的例子,我永远不会这样做,但假设foo是一个来自我无法控制的第 3 方包的函数,其中包含许多默认值、关键字参数等。在这种情况下,我宁愿将参数解析到 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()

如果您确实需要编写带有大量参数的函数,而不是将该状态封装在一个类中(这是一种更典型的 Python 方式),那么请考虑最近 Python 版本中的namedtuple数据类型。它允许您指定一个元组,其中项目可通过关键字寻址,并且可以编写一些非常干净、优雅的代码。

于 2012-10-11T17:40:57.727 回答
2

There are many approaches, depending on what those arguments represent.

  1. If they are just a grab-bag of arguments (especially if some are optional), use keyword arguments:

    myargs = {'iserver':'server','login':'username','password':'Pa2230rd'}
    version_get(**myargs)
    
  2. If they represent some thing with its own state, then use classes:

    1. If the arguments represent a single state that your functions are modifying, then accept the arguments in the object constructor and make your version_* methods functions of that class:

      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. If you have some kind of resource those arguments represent that your functions are merely using, in that case use a separate class, and supply it as an object parameter to your functions:

      class Connection(Object):
          def __init__(self, iserver, ...):
              self.iserver # etc
      
      myconn = Connection('iserver',...)
      
      version_check(myconn)
      
    3. Most likely, these are two different resources and should be two classes. In this case you can combine these approaches:

      #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. Possibly, your arguments represent more than one object (e.g., a connection and a transparent proxy object) In that case, try to create an object with the smallest public interface methods like version_* would need and encapsulate the state represented by the other arguments using object composition.

      For example, if you have proxy connections, you can create a Connection() class which just knows about server, login and password, and a ConnectionProxy() class which has all the methods of a Connection, but forwards to another Connection object. This allows you to separate the proxy* arguments, and means that your version_* functions can be ignorant of whether they're using a proxy or not.

  3. If your arguments are just state and don't have any methods proper to them, consider using a namedtuple(). This will act like a smarter tuple (including tuple unpacking, slicing, etc) and have minimal impact on your existing code while still being easier to use.

    Connection = namedtuple('Connection', 'iserver login password etc')
    myconn = Connection('iserver', 'loginname', 'passw3rd')
    version_check(*myconn)
    
于 2012-10-11T19:50:19.573 回答
0

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

文件调用者.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
于 2012-10-11T17:31:57.953 回答