如何从__init__中删除__init__之外定义的类属性?

时间:2013-07-23 08:28:21

标签: python attributes

class Foo

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

    def foo(self):
        pass

实例化raise s AttributeError: Foo instance has no attribute 'foo'时。从Fooobjectclass Foo(object) s 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的实例中完全删除/或使某些属性无法访问,只要满足某些条件。

有什么建议吗?

4 个答案:

答案 0 :(得分:2)

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()

答案 1 :(得分:1)

问题是你要删除的是一个方法,方法没有存储在实例上,它们存储在类中。

因此,您的实例Foo()实际上没有属性foo。执行Foo().foo后,它会在foo上找到Foo。因此self上没有要删除的内容,因为该属性不在self上。

如果类定义了一个方法(或任何类属性)foo,则无法从单个实例中删除它。你能做的最好的事情就是使用一些__getattribute__ hackery来引发异常。但是,这会对每个Foo实例上的每个属性访问产生性能影响。

为什么你觉得有必要这样做?

答案 2 :(得分:0)

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

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

方式,您将获得实例上的属性,如果某些代码在实例引用后直接在实例上为分配,就像在self.name = something中的典型__init__模式。

因此,无法使用del从一个实例中删除foo;您可以del Foo.foo将其从类中删除,但这会影响所有实例。对于初始化一个特定实例的__init__方法而言,这并不合理。

您可以通过在foo上定义self来屏蔽它;那么一个优先级并且它可以因实例而异(但是如果你del那么它foo再次开始回到类foo。或者你可以使用通用属性访问像__getattribute__这样的钩子进行一些检查,有时表现得好像foo不存在。或者你可以完全摆脱foo作为类属性,并将其添加到每个实例当你想要它而不是删除它时。

答案 3 :(得分:0)

你可以试试这个:

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

>>> Foo().foo
>>>