如何编写适应成员类接口的容器/包装类?

发布于 2024-11-09 13:30:12 字数 781 浏览 2 评论 0原文

我正在编写一个包含另一个类的对象的类。目的是改变它的一些方法行为,同时能够扩展它的所有其他接口。我没有使用继承,因为内部类对象可能会消亡,而外部类需要能够用活动对象替换它而不破坏自身。

所以我有:

class Inner():
    def foo(): pass
    def goo(): pass

class Outer():
    self.inner = InnerFactory(innerType)
    def foo(): 
         try:
             self.inner.foo() 
         except:
             del self.inner
             self.inner = InnerFactory(innerType)
             self.inner.foo()

问题是如何扩展 goo 而不显式重写,因为我可能有大量我不知道的其他此类方法。

实际上,在阅读下面的一些反馈后,我意识到我没有使用很棒的函数getattr。但是,我不太明白为什么下面的建议似乎都使用如此复杂的版本。为什么不能这么简单:

def __getattr__( self, name ):
    if self.inner:
          return getattr( self.inner, name )
    else:
          raise Exception( 'attribute %s not found' % name ) 

I'm writing a class that wraps around an object of another class. The intend is to change some of its method behaviors while able to extend all of its other interfaces. I'm not using inheritance because the inner class object can die and outer class needs to be able to replace it with a live one without destroying itself.

so I have:

class Inner():
    def foo(): pass
    def goo(): pass

class Outer():
    self.inner = InnerFactory(innerType)
    def foo(): 
         try:
             self.inner.foo() 
         except:
             del self.inner
             self.inner = InnerFactory(innerType)
             self.inner.foo()

The question is how to extend goo w/o explicitly rewrite as I may have tons of other such methods I'm not aware of.

Actually after reading some of the feedbacks below, I realized I'm not using the great function getattr. However, I don't quite follow why the suggestions below all seem to use such a complicated version. Why can't it be as simple as:

def __getattr__( self, name ):
    if self.inner:
          return getattr( self.inner, name )
    else:
          raise Exception( 'attribute %s not found' % name ) 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

路弥 2024-11-16 13:30:13

我的解决方案类似于@khachik加上一些方法缓存。

  • 请注意,使用 __ getattr__ 很容易进入无限循环。
  • 另外,如果需要,您可能需要添加线程锁

代码未经测试,请将其视为伪代码。

class Outer(object):
    def __init__(self):
        self.method_cache = {}
        self.methods_to_override = ['foo', 'goo']

    def __getattr__(self, method_name):
        if method_name in self.methods_to_override:
            if method_name in self.method_cache:
                return self.method_cache[method_name]
            else:
                def wrapper(*args, **kw):
                    wrapped = getattr(self.inner, method_name)
                    try:
                        return wrapped(*args, **kw)
                    except InnerDiedError:
                        self.inner = self.InnerFactory(innerType)
                        wrapped = getattr(self.inner, method_name)
                        return wrapped(*args, **kw)

                self.method_cache[method_name] = wrapper
                return wrapper

My solution is similar to @khachik plus some method caching.

  • Be careful it's easy to get into infinite loop with __ getattr__.
  • Also you may want to add threading locks if needed

Code is untested treat it as pseudo code.

class Outer(object):
    def __init__(self):
        self.method_cache = {}
        self.methods_to_override = ['foo', 'goo']

    def __getattr__(self, method_name):
        if method_name in self.methods_to_override:
            if method_name in self.method_cache:
                return self.method_cache[method_name]
            else:
                def wrapper(*args, **kw):
                    wrapped = getattr(self.inner, method_name)
                    try:
                        return wrapped(*args, **kw)
                    except InnerDiedError:
                        self.inner = self.InnerFactory(innerType)
                        wrapped = getattr(self.inner, method_name)
                        return wrapped(*args, **kw)

                self.method_cache[method_name] = wrapper
                return wrapper
不忘初心 2024-11-16 13:30:12

类似下面的代码可以满足您的要求,但是:1)它很丑陋; 2)不是线程安全的; 3)它陷入循环,直到Inner中的某个方法引发异常(这不是由于实现而是由于发布的最初想法); 4)还有一些避免使用它的理由:)

class Inner:
  def foo(self):
    print "foo"
  def bar(self):
    print "bar"

class Outer:
  def __init__(self):
    self.inner = Inner()

  def __getattr__(self, name):
    ret = getattr(self.inner, name)
    def wrapper(*args):
      try:
        ret(*args)
      except:
        del self.inner
        self.inner = Inner()
        updated = self.__getattr__(name)
        updated(*args)

    return wrapper

  def blah(self):
    print "Blah"

outer = Outer()

outer.foo()
outer.bar()
outer.blah()
outer.nosuchattr()

Something like the code below does what you want, but: 1) it is ugly; 2) it is not thread safe; 3) it falls into a loop until some method from Inner raises an exception (this is not due to the implementation but due to the initial idea posted); 4) some more reasons to avoid using it :)

class Inner:
  def foo(self):
    print "foo"
  def bar(self):
    print "bar"

class Outer:
  def __init__(self):
    self.inner = Inner()

  def __getattr__(self, name):
    ret = getattr(self.inner, name)
    def wrapper(*args):
      try:
        ret(*args)
      except:
        del self.inner
        self.inner = Inner()
        updated = self.__getattr__(name)
        updated(*args)

    return wrapper

  def blah(self):
    print "Blah"

outer = Outer()

outer.foo()
outer.bar()
outer.blah()
outer.nosuchattr()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文