繁体   English   中英

如何从__init__内部删除__init__外部定义的类属性?

[英]How to delete class attributes defined outside the __init__ from within __init__?

Foo class

class Foo():
    def __init__(self):
        del self.foo

    def foo(self):
        pass

实例化时, raise s AttributeError: Foo instance has no attribute 'foo' objectclass Foo(object) )派生Foo raise AttributeError: 'Foo' object attribute 'foo' is read-only 使用delattr(self, "foo")也无济于事。

执行以下操作也不会从Foo的实例中删除该属性:

class Foo():
    def __init__(self):
        self.foo = None
        del self.foo

    def foo(self):
        pass

>>> Foo().foo
<bound method Foo.foo of <__main__.Foo instance at 0x00000000042EA248>>

目的:

我基本上想在满足某些条件的情况下,从给定class的实例中完全删除/或使某些属性无法访问。

有什么建议么?

class Foo(object):
    def __init__(self):
        self.foo = None   # This masks the foo method on the instance `self`
    def foo(self):
        pass

foo = Foo()
print(foo.foo)
# None
print(foo.foo())
# TypeError: 'NoneType' object is not callable

但是,您确定要设计吗? 也许改为定义Foo子类,并实例化之前选择正确的类...

class Base(object):
    def common_method(self): pass

class Foo(Base):
    def foo(self): pass

class AltFoo(Base):
    def alt(self): pass

def make_foo():
    if somecondition:
        return Foo()
    eles:
        return AltFoo()

问题是您要删除的是一个方法,而方法没有存储在实例上,而是存储在类上。

因此,您的实例Foo()实际上没有属性foo 当您执行Foo().foo ,它将在Foo上找到foo 因此,关于self ,没有什么可删除的,因为属性不在self

如果类定义了方法(或任何类属性) foo ,则无法从单个实例中将其删除。 最好的办法是使用一些__getattribute__黑客程序使其引发异常。 但是,这会给每个Foo实例上的每个属性访问带来性能Foo

为什么您觉得需要这样做?

foo不是Foo实例的属性,而是Foo 对象的属性。

当您使用Foo().foo ,该行将创建一个新的Foo实例,然后在该实例中查找名称foo 该实例没有foo属性,因此查找回溯到该实例的类Foo 这就是绑定在类块中的名称的工作方式。 它们在类对象上创建属性,并且仅通过此查找回退机制间接影响实例。 这就是普通方法调用的工作方式-对于具有10个方法和1000个实例的类,我们不需要10,000个方法对象!

在实例上获取属性的唯一方法是,如果某些代码在引用实例后直接在实例上分配该属性,如典型的self.name = something __init__ self.name = something模式。

因此,无法使用del从一个实例中摆脱foo 您可以del Foo.foo从类del Foo.foo其删除,但这会影响所有实例。 在初始化一个特定实例时,放入__init__方法没有任何意义。

您可以通过在self上定义foo来掩盖它; 那么该实例将具有较高的优先级,并且实例之间的实例可能会有所不同(但是,如果您del它,则foo将再次回到foo类。或者您可以使用__getattribute__之类的通用属性访问钩子进行一些检查,有时还可以充当如果foo不存在,或者您可以完全放弃foo作为类属性,并在需要时将其添加到每个实例中,而不要存在时将其删除。

您可以尝试以下方法:

class Foo(object):
 def __init__(self):
  setattr(self,"foo", None)
 def foo(self):
  pass

>>> Foo().foo
>>>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM