0
class Test:
    def print_some():
        print('Good')

由于类也是 的对象type,那么执行上述代码时是否创建了类对象?如果是,如何证明相同?

4

3 回答 3

1

是的,这是正确的。

实际上class关键字导致创建类型的实例typedef关键字也会发生同样的事情。它导致创建类型的实例Function

import types

class A:
    pass


def fn():
    pass

print(isinstance(fn, types.FunctionType))
print(isinstance(A, type))

“A”现在是“type”类型的一个实例。“fn”是“Function”类型的一个实例。

于 2020-11-15T09:23:41.467 回答
0

是的,class是定义对象的可执行语句。

>>> class Cls:
...     print("This is executed as part of the `class` statement")
...
This is executed as part of `class` statement
>>> isinstance(Cls, object)
True

Python 语言参考:类定义

一个类定义定义一个类对象 [...]
一个类定义是一个可执行的语句。


请注意,从技术上讲,创建对象class不需要该语句-元类可以返回现有对象。最突出的内置元类为每个.typeclass

于 2020-11-15T12:32:51.697 回答
0

当一个类定义(ClassA例如 的)第一次被执行时:

  • 创建一个type对象来保存类定义。
  • 在当前命名空间中引入了一个ClassA名称(取决于类定义存在的位置)。该名称指向这个新type对象。

请注意,在上面,“执行类定义”与执行该类范围内定义的任何函数不同。当我们说“正在执行类定义”时,它只是意味着解释器试图理解类的全部内容(它的成员、属性等)。当这种情况发生时,类的任何功能都不会被执行——甚至不会__init__()

示范:

(演示何时创建类对象,以及结果会发生什么)

模块_a.py:

print ("Global print() from mod_a")

class ClassA:
    print ("Class-level print from ClassA")
    
    def __init__(self):
        print ("Inside ClassA.__init__()")

模块_b.py:

my_globals = globals()
print (f"Before import, len(my_globals) is: {len(my_globals)}")
if "ClassA" not in my_globals:
    print ("Before import, ClassA doesn't exist in globals of mod_b")
else:
    print (type(ClassA))

from mod_a import *

my_globals = globals()

print (f"导入后,len(my_globals) is: {len(my_globals)}") if "ClassA" not in my_globals: print ("导入后,ClassA 在全局变量中不存在") else: print ("After导入,名称 'ClassA' 存在") print (f"type(ClassA) is: {type(ClassA)}")

ClassB = ClassA  # The name ClassB is now an alias for the same type object
                 # that the name ClassA points to
ClassB()

输出(执行时mod_b.py):

Before import, len(my_globals) is: 5
Before import, ClassA doesn't exist in globals of mod_b  <-- print() in mod_b before import
Global print() from mod_a                                <-- print() in mod_a during import
Class-level print from ClassA                            <-- print() in mod_a during import
After import, len(my_globals) is: 6
After import, name 'ClassA' exists                       <-- print() in mod_b after import
type(ClassA) is: <class 'type'>                          <-- print() in mod_b after import
Inside ClassA.__init__()                                 <-- print() triggered by ClassB(), from __init__() of ClassA

上述输出的注意事项:

从上面的输出中,我们可以看到:

  1. 直到语句在. _ ClassA_globalmod_bfrom mod_a import *mod_b
  2. import语句执行后,名称ClassA存在于 的global命名空间中mod_b,并指向 类型的对象type
  3. 在赋值语句之后ClassB = ClassA,名称ClassAClassB都引用同一个对象。
  4. 从这里开始,名称就没有什么“特殊”或“原始”了ClassA——我们可以使用名称ClassB来进行实例化,而不是使用名称ClassA
  5. 通过执行 a del ClassA,我们甚至可以在 的命名空间中使名称ClassA未定义,并继续使用别名(但我没有在上面的演示中包含最后一点)globalmod_bClassB

文献参考:

Python 执行模型的一些相关摘录:

  1. Python 程序由代码块构成。块是作为一个单元执行的一段 Python 程序文本。以下是块:模块、函数体和类定义
  2. 名称指的是对象。名称由名称绑定操作引入。
  3. 以下构造绑定名称:函数的形式参数、导入语句、类和函数定义(这些在定义块中绑定类或函数名称)
  4. 如果名称绑定在模块级别,则它是一个全局变量。
于 2020-11-15T12:10:15.603 回答