检查self.__class__
的目的是什么?我找到了一些创建抽象接口类的代码,然后检查它的self.__class__
本身是否存在,例如。
class abstract1 (object):
def __init__(self):
if self.__class__ == abstract1:
raise NotImplementedError("Interfaces can't be instantiated")
那是什么目的? 是要检查这个类是否属于它自己的类型?
代码来自NLTK的http://nltk.googlecode.com/svn/trunk/doc/api/nltk.probability-pysrc.html#ProbDistI
答案 0 :(得分:22)
self.__class__
是对当前实例的类型的引用。
对于abstract1
的实例,那就是abstract1
类本身,这是你不想要的抽象类。抽象类仅用于子类化,而不是直接创建实例:
>>> abstract1()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __init__
NotImplementedError: Interfaces can't be instantiated
对于abstract1
的子类的实例,self.__class__
将是对特定子类的引用:
>>> class Foo(abstract1): pass
...
>>> f = Foo()
>>> f.__class__
<class '__main__.Foo'>
>>> f.__class__ is Foo
True
在此处抛出异常就像在代码中的其他位置使用assert
语句一样,它可以防止您犯下愚蠢的错误。
请注意, pythonic 测试实例类型的方法是使用type()
function代替{em>身份测试can be shadowed by a class attribute 1}} operator:
is
class abstract1(object):
def __init__(self):
if type(self) is abstract1:
raise NotImplementedError("Interfaces can't be instantiated")
应优先于type()
,因为后者abc
。
对于自定义类,使用等式测试没有什么意义,self.__class__
基本上都是作为身份测试实现的。
Python还包括一个标准库,用于定义抽象基类,称为{{3}}。它允许您将方法和属性标记为抽象,并拒绝创建尚未重新定义这些名称的任何子类的实例。
答案 1 :(得分:1)
你在那里发布的代码是no-op; self.__class__ == c1
不是条件的一部分,因此对布尔值进行了求值,但结果没有做任何事情。
您可以尝试创建一个抽象基类,以检查self.__class__
是否等于抽象类而不是假设子(通过if语句),以防止抽象的实例化基类本身由于开发人员的错误。
答案 2 :(得分:1)
我会说有些人会这样做:
class Foo(AbstractBase):
def __init__(self):
super(Foo, self).__init__()
# ...
即使基础是抽象的,你也不希望基数的__init__
抛出NotImplementedError
。嘿,也许它甚至做了一些有用的事情?
答案 3 :(得分:1)
那是什么目的?是要检查这个类是否属于它自己的类型?
是的,如果你试图构造一个Abstract1
类型的对象,它会抛出该异常,告诉你不允许你这样做。
答案 4 :(得分:0)
线索在类的名称“abstract1”中,并在错误中。这是一个抽象类,意思是一个旨在被子类化的类。每个子类都将提供自己的行为。抽象类本身用于记录接口,即实现接口的类应该具有的方法和参数。它并不意味着自己实例化,测试用于判断我们是在类本身还是子类中。
请参阅Julien Danjou撰写的article中的抽象类部分。
答案 5 :(得分:0)
在Python 3中,使用type()
检查类型或使用__class__
将返回相同的结果。
class C:pass
ci=C()
print(type(ci)) #<class '__main__.C'>
print(ci.__class__) #<class '__main__.C'>
我最近检查了implementation中的@dataclass
装饰器(Raymond Hettinger直接参与了该项目),他们正在使用__class__
来引用类型。
因此使用__class__
:)