Python的执行顺序是“自上而下、逐行执行”,但要结合具体语句的类型(如定义、表达式、导入、类定义等)来理解。
test5.py
print("test5module: start executing")
x = 10
def func():
print("test5module: func called")
class MyModClass:
print("test5module: MyModClass body executing")
def __init__(self):
print("test5module: MyModClass __init__")
print("test5module: end executing")
test.py
print("main: script start")
import sys # 标准库
import test5 # 导入自定义模块
from test5 import func # 只导入mymodule中的func
import math as m # 标准库,取别名
try:
import numpy as np # 第三方库(如果有安装)
except ImportError:
np = None
print("main: after imports")
class Demo:
print("Demo class: class body executing")
# 类变量
class_var = 100
# 魔术方法
def __new__(cls, *args, **kwargs):
print("Demo.__new__ called")
instance = super().__new__(cls)
return instance
def __init__(self, value):
print("Demo.__init__ called")
self.value = value # 实例变量
# 实例方法
def instance_method(self):
print("Demo.instance_method: value =", self.value)
# 类方法
@classmethod
def class_method(cls):
print("Demo.class_method: class_var =", cls.class_var)
# 静态方法
@staticmethod
def static_method():
print("Demo.static_method called")
# 魔术方法
def __call__(self, x):
print(f"Demo.__call__({x}) called")
print("main: after class definition")
def main():
print("main: in main() function")
# 实例化对象
d = Demo(42)
d.instance_method()
d.class_method()
Demo.class_method()
d.static_method()
Demo.static_method()
# 使用魔术方法
d(99) # 调用__call__
# 访问类变量和实例变量
print("d.value =", d.value)
print("Demo.class_var =", Demo.class_var)
# 使用导入的模块/函数
func()
print("math.sqrt(16) =", m.sqrt(16))
if np:
print("np.arange(3) =", np.arange(3))
if __name__ == "__main__":
print("main: __name__ == '__main__'")
main()
print(“main: script start”) 立即输出。
import sys:标准库,导入后可用,顶层无输出。
import mymodule:首次导入,解释器进入mymodule.py
,顶层代码逐行执行,输出如下:
mymodule: start executing
mymodule: MyModClass body executing
mymodule: end executing
from mymodule import func:模块已导入,不重复执行顶层代码,只是把func指向主程序空间。
import math as m:标准库导入,顶层无输出。
import numpy as np:如果有安装则导入,否则np=None。
print(“main: after imports”) 输出。
main: __name__ == '__main__'
,然后执行main()
。main: in main() function
Demo.__new__
(输出Demo.__new__ called
)Demo.__init__
(输出Demo.__init__ called
)Demo.instance_method: value = 42
Demo.class_method: class_var = 100
Demo.static_method called
Demo.__call__
,输出Demo.__call__(99) called
d.value = 42
、Demo.class_var = 100
mymodule: func called
math.sqrt(16) = 4.0
np.arange(3) = [0 1 2]
main: script start
mymodule: start executing
mymodule: MyModClass body executing
mymodule: end executing
main: after imports
Demo class: class body executing
main: after class definition
main: __name__ == '__main__'
main: in main() function
Demo.__new__ called
Demo.__init__ called
Demo.instance_method: value = 42
Demo.class_method: class_var = 100
Demo.class_method: class_var = 100
Demo.static_method called
Demo.static_method called
Demo.__call__(99) called
d.value = 42
Demo.class_var = 100
mymodule: func called
math.sqrt(16) = 4.0
np.arange(3) = [0 1 2]
print
、表达式、赋值等。非常感谢你的反馈!下面我将结合前述讲解和你的新问题,用更清晰的例子和Markdown图解,详细解释:
假设你有如下代码:
class Demo:
class_var = 10 # 类变量
def __new__(cls, *args, **kwargs):
print("Demo.__new__ called")
instance = super().__new__(cls)
return instance
def __init__(self, value):
print("Demo.__init__ called")
self.instance_var = value
def foo(self):
print("Demo.foo called")
class_var = 10
)def __init__...
,会创建函数对象,然后以名字为key保存到命名空间)# 类体执行到最后,类命名空间长这样(伪代码):
Demo命名空间 = {
'class_var': 10,
'__new__': ,
'__init__': ,
'foo':
}
Demo类对象
├── class_var : 10
├── __new__ :
├── __init__ :
├── foo :
1. 解释器"遇见" class Demo:
|
|---> 创建一个"类命名空间"(空字典)
|
|---> 依次执行class体每行代码,每一行的赋值/def都写入这个字典
| ├─ class_var = 10 -> class_var: 10
| ├─ def __new__(...) -> __new__: function object
| ├─ def __init__(...) -> __init__: function object
| └─ def foo(...) -> foo: function object
|
|---> class体执行完毕
|
|---> 解释器用这个字典,创建一个新的"类对象"
| └─ 类对象的属性 = 类命名空间的内容
|
|---> "Demo"这个名字指向这个类对象
Demo (类对象)
├── class_var = 10
├── __new__ # 方法
├── __init__ # 方法
├── foo # 方法
e = Demo(123) # 实例化后
e (Demo实例对象)
├── instance_var = 123 # 只属于e的实例变量
e = Demo(123)
Demo.__new__
(类的__new__方法)
Demo.__init__
self.instance_var = value
给实例绑定实例变量e = Demo(123)
|
|---> Demo.__new__(Demo, 123)
| |
| |---> super().__new__(Demo) # 创建空对象 e
| |---> 返回 e
|
|---> Demo.__init__(e, 123)
| |
| |---> e.instance_var = 123 # 给e绑定实例变量
class Demo:
class_var = 10
def __new__(cls, *args, **kwargs):
print("Demo.__new__ called")
instance = super().__new__(cls)
return instance
def __init__(self, value):
print("Demo.__init__ called")
self.instance_var = value
def foo(self): pass
print('类命名空间内容:')
print(Demo.__dict__) # 类对象的属性,实际就是类命名空间内容
e = Demo(123)
print('实例命名空间内容:')
print(e.__dict__)
输出(部分):
类命名空间内容:
{'__module__': '__main__', 'class_var': 10, '__new__': , '__init__': , 'foo': , ...}
Demo.__new__ called
Demo.__init__ called
实例命名空间内容:
{'instance_var': 123}
self.xxx=yyy
绑定到实例对象上。__new__
用于创建实例对象,__init__
用于初始化实例变量。这里补充一个“实例修改类”(这个话是一个错误的话)
因为修改class_var
这会在 e 的实例字典 e.__dict__
里新建一个名为class_var的实例变量,它只属于 e。
从此,e.class_var 访问的是实例自己的,不再是类的那个。
其他实例和类本身的 class_var 不受影响。再次声明,以防出现误解。
Demo (类对象)
├── class_var = 10
├── __new__ # 方法
├── __init__ # 方法
├── foo # 方法
e = Demo(123) # 实例化后
├── instance_var = 123 # 只属于e
└── class_var = 20 # 只属于e(实例变量,遮盖了类变量)
f = Demo(456) # 另一个实例
└── instance_var = 456 # 只属于f
Demo (类对象)
└── class_var = 10 # 仍然属于类对象
查找变量/方法顺序:
实例对象 → 类对象 → 父类对象
class Person:
species = "Homo sapiens"
def __new__(cls, *args, **kwargs):
print(f"Person.__new__ for {cls.__name__}")
return super().__new__(cls)
def __init__(self, name):
print("Person.__init__")
self.name = name
def introduce(self):
print(f"I am {self.name}, a {self.species}")
class Employee(Person):
company = "PyTech"
def __init__(self, name, emp_id):
print("Employee.__init__")
super().__init__(name)
self.emp_id = emp_id
def work(self):
print(f"{self.name} is working at {self.company}")
class Manager(Employee):
def __init__(self, name, emp_id, team_size):
print("Manager.__init__")
super().__init__(name, emp_id)
self.team_size = team_size
def manage(self):
print(f"{self.name} manages a team of {self.team_size}")
Person
类体结束后Person命名空间:
├── species : "Homo sapiens"
├── __new__ :
├── __init__ :
└── introduce :
Employee
类体结束后Employee命名空间:
├── company : "PyTech"
├── __init__ :
└── work :
# 注意:没有species、introduce、__new__,但继承自Person
Manager
类体结束后Manager命名空间:
├── __init__ :
└── manage :
# 其它成员都继承自Employee/Person
m = Manager("Alice", "A1001", 5)
1. Manager.__new__(继承自Person.__new__)
└─ 打印:Person.__new__ for Manager
└─ 返回新实例 m
2. Manager.__init__(m, "Alice", "A1001", 5)
└─ 打印:Manager.__init__
└─ 调用 super().__init__("Alice", "A1001")
└─ Employee.__init__(m, "Alice", "A1001")
└─ 打印:Employee.__init__
└─ 调用 super().__init__("Alice")
└─ Person.__init__(m, "Alice")
└─ 打印:Person.__init__
└─ m.name = "Alice"
└─ m.emp_id = "A1001"
└─ m.team_size = 5
Manager (类对象)
├── __init__ # Manager自定义
├── manage # Manager自定义
├── company # 继承自Employee
├── work # 继承自Employee
├── species # 继承自Person
├── introduce # 继承自Person
├── __new__ # 继承自Person
m (Manager实例对象)
├── name = "Alice" # 从Person.__init__赋值
├── emp_id = "A1001" # 从Employee.__init__赋值
├── team_size = 5 # 从Manager.__init__赋值
m.work()
m.introduce()
m.company
m.species
m.name
Manager (类对象)
├── __init__ [Manager自己的]
├── manage [Manager自己的]
├── work [继承自Employee]
├── company [继承自Employee]
├── introduce [继承自Person]
├── species [继承自Person]
├── __new__ [继承自Person]
m = Manager("Alice", "A1001", 5) (实例)
├── name = "Alice" [Person.__init__]
├── emp_id = "A1001" [Employee.__init__]
├── team_size = 5 [Manager.__init__]
m = Manager("Alice", "A1001", 5)
print("实例命名空间:", m.__dict__)
print("company:", m.company)
print("species:", m.species)
m.introduce()
m.work()
m.manage()
输出:
Person.__new__ for Manager
Manager.__init__
Employee.__init__
Person.__init__
实例命名空间: {'name': 'Alice', 'emp_id': 'A1001', 'team_size': 5}
company: PyTech
species: Homo sapiens
I am Alice, a Homo sapiens
Alice is working at PyTech
Alice manages a team of 5
__new__
和__init__
沿MRO链路(super)逐级调用,分别负责分配对象和初始化实例属性。__dict__
,类变量/方法都在类对象,继承链查找。