簡體   English   中英

從 Python 中的子類中刪除屬性

[英]Remove attribute from subclass in Python

有沒有辦法從父類中存在的子類中刪除屬性?

在下面的例子中

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

class B(A):
    pass

# <desired code here>

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

我們可以編寫任何代碼來使斷言通過嗎?

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

是的,使用描述符的魔力。 請參閱我的博客文章 簡潔版本:

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屬性。 在我的回答中,類本身(實際上是屬性)不允許子類擁有該屬性,因此一舉一動,所有子類都沒有它。

當我不希望在 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 中創建一個方法(刪除),刪除該屬性並將其放入構造函數中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM