3

有没有办法从父类中存在的子类中删除属性?

在下面的例子中

class A(object):
    foo = 1
    bar = 2

class B(A):
    pass

# <desired code here>

b = B()
assert hasattr(b, 'bar') == False

我们可以编写任何代码来使断言通过吗?

4

3 回答 3

5
class A(object):
    foo = 1
    bar = 2


class B(A):
    @property
    def bar(self):
        raise AttributeError


>>> b = B()
>>> b.bar

Traceback (most recent call last):
  File "<pyshell#17>", line 1, in <module>
    b.bar
  File "<pyshell#15>", line 4, in bar
    raise AttributeError
AttributeError
于 2013-05-25T12:00:21.850 回答
1

当我不希望在 dir(A) 中列出特定属性(在本例中为“bar”)时,这对我有用。

class A(object):
    
    foo = 1
    bar = 2


class B(A):
    def ___init__(self):
    
        self.delete()
    
    def delete(self):
        delattr(self, 'bar')

基本上,在子类 B 中创建一个方法(删除),删除该属性并将其放入构造函数中。

于 2022-01-29T01:55:33.863 回答
0

是的,使用描述符的魔力。请参阅我的博客文章。简洁版本:

class nosubclasses(object):
    def __init__(self, f, cls):
        self.f = f
        self.cls = cls
    def __get__(self, obj, type=None):
        if type == self.cls:
            if hasattr(self.f, '__get__'):
                return self.f.__get__(obj, type)
            return self.f
        raise AttributeError

例子:

In [2]: class MyClass(object):
   ...:     x = 1
   ...:

In [3]: MyClass.x = nosubclasses(MyClass.x, MyClass)

In [4]: class MySubclass(MyClass):
   ...:     pass
   ...:

In [5]: MyClass.x
Out[5]: 1

In [6]: MyClass().x
Out[6]: 1

In [80]: MySubclass.x
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-80-2b2f456dd101> in <module>()
----> 1 MySubclass.x

<ipython-input-51-7fe1b5063367> in __get__(self, obj, type)
      8                 return self.f.__get__(obj, type)
      9             return self.f
---> 10         raise AttributeError

AttributeError:

In [81]: MySubclass().x
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-81-93764eeb9948> in <module>()
----> 1 MySubclass().x

<ipython-input-51-7fe1b5063367> in __get__(self, obj, type)
      8                 return self.f.__get__(obj, type)
      9             return self.f
---> 10         raise AttributeError

AttributeError:

但正如评论者@delnan 指出的那样,这违反了 Liskov 可替代性原则。我的博客文章中的动机是有根据的,因为该属性没有描述对象本身。但总的来说,这首先打破了能够进行子类化的重点,这实际上就是拥有类的重点。

顺便说一句,我的答案和@jamylak 的区别在于,在@jamylak 的答案中,属性是按子类删除的。如果你做了一个class C(A),它仍然会有这个bar属性。在我的回答中,类本身(实际上是属性)不允许子类拥有该属性,因此一举一动,所有子类都没有它。

于 2013-06-12T01:41:13.970 回答