在很长一段时间内收回Python并希望刷新一些概念,我希望这个问题不错。
说我有一个非常简单的类,如下所示:
class myClass:
def __init__(self):
self.myProp = 2
如果我使用括号实例化,一切都按预期工作:
>>> a = myClass()
>>> a.myProp
2
但是,如果我不在上面两行使用括号,即:
>>> a = myClass
我收到以下错误:
>>> a.myProp
Traceback (most recent call last):
File "<pyshell#45>", line 1, in <module>
a.myProp
AttributeError: class myClass has no attribute 'myProp'
如果我打印对象,
>>> a = myClass
>>> a
我得到了
<class __main__.myClass at 0x0275C538>
似乎a
是该类的一个实例,但不知何故未初始化。
在其他语言中,如果尝试将类实例强制转换为对象而不进行初始化(例如在C#中,myClass a = new myClass();
将正常工作但myClass a = new myClass;
将返回编译错误),我会期望编译错误。
所以我的问题是:从技术上讲,什么是没有括号的对象a = myClass
?
答案 0 :(得分:7)
a
是类本身 - 在python中,类是第一类对象 1 。您可以将它们作为参数传递,将它们别名为不同的名称(就像您在示例中所做的那样),然后您可以使用当前命名空间中的任何引用实例。
a = myClass # a and myClass identical at this point. The interpretter won't care which you use.
a_instance = a() # instance of myClass
def make_instance(cls):
return cls()
another_instance = make_instance(a)
yet_another_instance = make_instance(myClass)
你看,python没有任何“编译时检查”,因为真的 - 没有编译时间。 Python代码在运行时处解释。是的,您可以在导入时弹出SyntaxError
,但这仍然是在运行时。
1 没有双关语
答案 1 :(得分:6)
它是对类本身的引用,而不是对类实例的引用。请注意区别:
>>> a = myClass
>>> a
<class __main__.myClass at 0x10cd1de20>
>>> b = myClass()
>>> b
<__main__.myClass instance at 0x10cd8efc8>
答案 2 :(得分:3)
Python中的所有内容都是一个对象,因此是一个类的实例,包括类。操作类或将它们作为变量传递没有什么特别之处。因此,引用同一对象的变量a
和MyClass
,只是MyClass
的对象。
>>> class R: pass # In Python 2, you would need class R(object): pass
>>> r = R()
现在我们有两个变量R
和r
。 r
是类R
的一个实例。这里的诀窍是R
是类type
的一个实例,这就是我们将R
称为类的原因。 r
和R
都是object
的实例,这就是我们将它们都称为对象的原因。 R
是类object
的子类,因为R
是一个类。
>>> isinstance(R, type)
True
>>> isinstance(r, R)
True
>>> issubclass(R, object)
True
>>> isinstance(r, object)
True
>>> isinstance(type, object)
True
>>> isinstance(type, type)
True
每个Python对象都是object
的实例,每个Python类都是object
的子类,每个Python类都是type
的实例。
请注意,我所说的在Python 3和Python 2“新风格”类中都是正确的。不要关心Python旧式类。