Python 如何跳过inspect.getmembers中的缓存属性

Python 如何跳过inspect.getmembers中的缓存属性,python,Python,我有一个python类Foo,它将观察者注册到可观察对象。 我有几个类继承自Foo并填充观察者列表,每个类都有不同的观察者 由于与当前设计相关的原因,观察者列表在每个派生类\uuuu init\uuuuuuuuuuu中显式初始化,并且不能移动到可重写的方法(将从基类\uuuu init\uuuuuuuuuuu调用)。 因此,我无法在构造函数中调用observable.RegisterObserver(因为观察者列表尚未填充) 为了确保观察员已注册,我创建了observable as cached

我有一个python类Foo,它将观察者注册到可观察对象。 我有几个类继承自Foo并填充观察者列表,每个类都有不同的观察者

由于与当前设计相关的原因,观察者列表在每个派生类\uuuu init\uuuuuuuuuuu中显式初始化,并且不能移动到可重写的方法(将从基类\uuuu init\uuuuuuuuuuu调用)。

因此,我无法在构造函数中调用observable.RegisterObserver(因为观察者列表尚未填充)

为了确保观察员已注册,我创建了observable as cached属性。通过这种方式,我可以保证,没有人会在不先注册观察员的情况下直接进入现场

对my_observable的第一次调用应该发生在init完成之后。 问题是在基类init的末尾有一个inspect.getmembers调用。 inspect.getmembers()使用getattr,并以此计算缓存的\u属性

如果不满足某些条件(即,我们仍在初始化中),我尝试抛出AttributeError,但我不喜欢这种解决方案,如果有人以不同的方式实现派生类,它将失败。 有没有办法告诉inspect跳过缓存属性? 也可以使用可信的方法来判断init(派生类)是否完成

伪代码:

class Foo(object):
  def __init__(self):
    self._observers = []
    for _, member in inspect.getmembers(self):
      # do something with member
      continue

  @cached_property
  def my_observable:
    observable = Observable()
    observable.RegisterObservers(self._observers)
    return observable


class Bar(Foo):
  def __init__(self):
    super(Bar, self).__init__()
    self._observers = [MyObserver()]

找到了解决我问题的办法。 它并没有解决inspect.getmembers评估我的缓存属性的问题,但它实际上以更好的方式解决了设计问题

我将定义一个元类,它将覆盖调用,并调用类上的特定方法。 在元类中重写调用允许我们在返回新实例之前注入该步骤

所以它看起来像这样:

class MyMetaClass(type): 
  def __call__(cls, *args, **kwargs):
      """Called when the object is initialized."""
      obj = type.__call__(cls, *args, **kwargs)
      obj.FinalizeInit()
      return obj


class Foo(object):
  __metaclass__ = MyMetaClass
  def __init__(self):
    self._observers = []
    for _, member in inspect.getmembers(self):
      # do something with member
      continue
    self._observable = None

  def FinalizeInit(self):
    self._observable = Observable()
    self._observable.RegisterObservers(self._observers)

\uuuu init\uuuu
中使用一个标志怎么样?例如,最后将
initialized
设置为
True
,我考虑过了,但是派生类将调用super的init,然后才执行自己的init。。所以这个标志应该在派生类init中设置…我认为,为了防止通过硬编码实现错误,格式良好的文档更有用。。。由于您的用户也是程序员,他们应该正确地实现派生类。