禁用类实例方法

2024-05-07 20:05:02 发布

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

如何根据条件快速禁用类实例中的所有方法?我天真的解决方案是使用__getattr__重写,但是当函数名已经存在时,就不会调用它。在

class my():
    def method1(self):
        print 'method1'
    def method2(self):
        print 'method2'
    def __getattr__(self, name):
        print 'Fetching '+str(name)
        if self.isValid():
            return getattr(self, name)
    def isValid(self):
        return False
if __name__ == '__main__':
    m=my()
    m.method1()

Tags: 实例方法nameselfreturnifmydef
1条回答
网友
1楼 · 发布于 2024-05-07 20:05:02

实际上,您要做的等效操作实际上是重写__getattribute__,它将为每个属性访问调用。除此之外,还要注意:根据every的定义,这包括对__getattribute__自身主体内的self.isValid的调用,因此您必须使用一些迂回的路径来访问该属性(type(self).isValid(self)应该可以工作,例如,因为它从类而不是从实例获取属性)。在

这指向了一个可怕的术语混乱:这是不是禁用“来自类的方法”,而是来自一个实例,尤其与classmethods无关。如果您确实希望在类的基础上而不是在实例的基础上以类似的方式工作,您需要创建一个自定义元类,并重写元类上的__getattribute__(这是当您在标题和文本中要求访问类的属性时调用的元类,而不是像您实际所做的那样在实例上访问属性时调用的元类,这是迄今为止比较正常和常见的案例)。在

编辑:一种完全不同的方法可能是使用一种特殊的python路径来实现State设计模式:类交换。E、 g.:

class _NotValid(object):
  def isValid(self):
    return False
  def setValid(self, yesno):
    if yesno:
      self.__class__ = TheGoodOne

class TheGoodOne(object):
  def isValid(self):
    return True
  def setValid(self, yesno):
    if not yesno:
      self.__class__ = _NotValid
  # write all other methods here

只要您可以适当地调用setValid,这样对象的__class__被适当地切换,这是非常快速和简单的本质上,对象的{}是找到所有对象方法的地方,所以通过切换它,您可以整体地切换在给定时间存在于对象上的方法集。但是,如果您绝对坚持必须“及时”执行有效性检查,也就是说,在查找对象的方法的那一刻,这就行不通了。在

在这和__getattribute__之间的一个中间方法是引入一个额外的间接层次(通常认为这是所有问题的解决方案;-),大致如下:

^{pr2}$

这比__getattribute__更惯用,因为它依赖于这样一个事实,即__getattr__只为在其他方式中找不到的属性调用,因此对象可以在其__dict__中保存正常状态(数据),并且访问这些状态时不会产生任何大的开销;只有方法调用才支付indirection的额外开销。如果任何状态需要在无效对象上保持可访问状态,_Valid类实例可以将部分或全部状态保持在各自的self._actualobject中(因此,无效状态禁用方法,但不能访问数据属性;如果需要,从Q中不清楚,但是这种方法提供了一种免费的额外可能性)。这个习惯用法比__getattribute__更不容易出错,因为可以在方法中更直接地访问状态(而不触发有效性检查)。在

如前所述,该解决方案创建一个循环引用循环,这可能会在垃圾收集方面带来一些开销。{如果一个最简单的问题是从一个Python应用程序的一个最简单的模块中删除循环},如果这是一个最简单的问题,那么通常使用循环的方法。 (例如,使_Valid类实例的_actualobject属性成为对将该实例作为其^{属性的对象的引用)。在

相关问题 更多 >