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

2024-09-26 22:51:41 发布

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

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

由于与当前设计相关的原因,观察者列表在每个派生类\uu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

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

为了确保观察者已注册,我创建了observable as cached属性。这样我就可以保证,没有人会直接进入现场,而不是先注册观察员

对我的\u observate的第一个调用应该在init完成之后发生。 问题是在基类init的末尾有一个inspect.getmembers调用。 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()]

Tags: self列表属性fooinitdefclass观察者
1条回答
网友
1楼 · 发布于 2024-09-26 22:51:41

找到了解决我问题的办法。 它不能解决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)

相关问题 更多 >

    热门问题