Python用class和access class instan修饰函数

2024-04-20 13:37:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个Python类,它将执行到服务器的远程连接。因为有几个协议(TCP/IP,HTTP)可以访问相同的数据,这些协议都可以根据情况(性能问题,…)来使用,所以我想使用这个类作为封装实现的不同函数的装饰器。你知道吗

我的班级是这样的:

class RemoteConnection(object):
      def __init__(self, function):
         self.function = function
         self.results = None

      def __call__(self, *args):
         self.function(self, *args)

      def setResults(*args):
         self.results = args


 @RemoteConnection
 def performTCPConnection(instance, username, password):
       #...perform connection
       instance.setResults(results) #set the results of the connection (a query)
       return instance

 @RemoteConnection
 def performHTTPConnection(instance, username, password):
       #...perform connection
       #and so on

  if __name__ == '__main__':
        performTCPConnection("admin", "admin") #OR
        #performHTTPConnection("admin, "admin")

以后的参数(不仅仅是用户名和密码,这些只是示例)应通过使用argparse或其他方式提供给程序。你知道吗

如果我这样调用程序,__init__()-方法会因为decorator而被调用两次。另外,在调用__call__-方法之前调用performTCPConnection-函数。我现在想要的是,RemoteConnection类的实例由performTCPConnection-函数返回给main函数中的一个变量。你知道吗

如果我这样做:

foo = perfprmTCPConnection("admin","admin")
print foo

没有打印到标准输出。你知道吗

如果我尝试访问performTCPConnection函数中的实例,如下所示:

   @RemoteConnection
   def performTCPConnection(instance, username, password):
   #...perform connection
   instance.setResults(results) #set the results of the connection (a query)
    print instance
   return instance

类似<__main__.ServerConnection object at 0x7f4803516fd0>的内容被写入标准输出。你知道吗

我的想法有点来自Java世界,就像实现一个策略模式一样。你知道吗

不幸的是,直到现在我还没有找到一个很好的解释来解释这种行为。这也是一个好的设计方法吗?你知道吗


Tags: theinstance函数selfadmindefusernameargs
3条回答

我发现了错误,忘记了在调用中返回修饰函数的结果。你知道吗

这解决了问题:

class RemoteConnection(object):
  def __init__(self, function):
     self.function = function
     self.results = None

  def __call__(self, *args):
     return self.function(self, *args) #here was the problem!

  def setResults(*args):
     self.results = args

我肯定会说这不是一个好的设计。这是一种在不使用继承机制的情况下有效地获得继承的聪明方法,但是它是非标准的、非直观的,而且没有必要,因为有更直接的方法来完成这一切。你知道吗

@zmo的答案显示了如何正确设置派生类。但我甚至不会这么做:考虑将连接器对象与类本身分离,并像这样设置类签名:

class RemoteConnection(object):
    def __init__(self, connector):
        self.connection = connector

然后您只需引用右连接器来实例化它:

conn = RemoteConnection(TCPConnector(user, password))

这样RemoteConnection封装了与协议无关的函数,而与协议相关的部分是独立的函数或对象(如果愿意,可以从公共类派生)。如果在连接的生命周期内需要连接器,则保存连接器对象以便稍后调用。如果不是,那么TCPConnection就可以返回您现在拥有的results值。你知道吗

如果我照你写的做,我相信你设计得太过了。基本上,使用decorator的策略将严格等同于:

def performTCPConnection(username, password):
   instance = RemoteConnection()
   #...perform connection
   instance.setResults(results) #set the results of the connection (a query)
   return instance

但是读到你想要的东西,你还没到。因为如果我理解了模式中RemoteConnection类的用途,那就是在调用.function()方法时延迟连接。你知道吗

所以你想要的实际上是:

def prepareTCPConnection(username, password):
    rc = RemoteConnection()
    def connection_handler():
        # perform the connection, and setup results
        rc.setResults(results)
    rc.function = connection_handler
    return rc

显然,你必须适当地调整RemoteConnection。你知道吗

在这里,您要做的是利用内部函数(和闭包)来定义一个函数,以便在程序流中稍后方便的时候调用。你知道吗

但老实说,您可以通过使用简单的子类以一种更简单的方式实现这一点:

class PerformConnection():
    def __init__(self, username, password):
        self.username = username
        self.password = password

    def perform(self):
        raise NotImplementedError

class PerformConnectionTCP(PerformConnection):
    def perform(self):
        # do what you got to do here...
        return results

然后你可以做:

if __name__ == "__main__":
    instance = PerformConnectionTCP('admin', 'admin')
    instance.perform()

相关问题 更多 >