pyobject 1.2.9.2__tar.gz → 1.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. {pyobject-1.2.9.2/pyobject.egg-info → pyobject-1.3.1}/PKG-INFO +23 -405
  2. {pyobject-1.2.9.2 → pyobject-1.3.1}/README.rst +22 -404
  3. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/__init__.py +6 -5
  4. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/examples/test_inject.py +3 -3
  5. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/objproxy/__init__.py +289 -288
  6. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/objproxy/builtin_hook.py +2 -20
  7. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/objproxy/optimize.py +10 -8
  8. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/tests/test_objproxy.py +33 -10
  9. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/tests/test_objproxy_perf.py +4 -3
  10. {pyobject-1.2.9.2 → pyobject-1.3.1/pyobject.egg-info}/PKG-INFO +23 -405
  11. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject.egg-info/SOURCES.txt +0 -1
  12. pyobject-1.2.9.2/pyobject/objproxy/dynobj.py +0 -190
  13. {pyobject-1.2.9.2 → pyobject-1.3.1}/LICENSE +0 -0
  14. {pyobject-1.2.9.2 → pyobject-1.3.1}/MANIFEST.in +0 -0
  15. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/browser.py +0 -0
  16. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/code.py +0 -0
  17. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/examples/README.md +0 -0
  18. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/examples/__init__.py +0 -0
  19. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/examples/empty_cp37.pyc +0 -0
  20. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/examples/pyc_zipper_unpack.py +0 -0
  21. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/examples/pyc_zipper_zlib.py +0 -0
  22. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/images/back.gif +0 -0
  23. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/images/codeobject.gif +0 -0
  24. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/images/dict.gif +0 -0
  25. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/images/empty_dict.gif +0 -0
  26. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/images/empty_list.gif +0 -0
  27. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/images/empty_tuple.gif +0 -0
  28. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/images/forward.gif +0 -0
  29. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/images/function.gif +0 -0
  30. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/images/list.gif +0 -0
  31. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/images/number.gif +0 -0
  32. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/images/python.gif +0 -0
  33. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/images/python.ico +0 -0
  34. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/images/refresh.gif +0 -0
  35. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/images/string.gif +0 -0
  36. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/images/tuple.gif +0 -0
  37. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/objproxy/utils.py +0 -0
  38. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/other/browser_chs_locale.py +0 -0
  39. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/pyobj_extension.c +0 -0
  40. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/search.py +0 -0
  41. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject/tests/test_code.py +0 -0
  42. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject.egg-info/dependency_links.txt +0 -0
  43. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject.egg-info/requires.txt +0 -0
  44. {pyobject-1.2.9.2 → pyobject-1.3.1}/pyobject.egg-info/top_level.txt +0 -0
  45. {pyobject-1.2.9.2 → pyobject-1.3.1}/setup.cfg +0 -0
  46. {pyobject-1.2.9.2 → pyobject-1.3.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyobject
3
- Version: 1.2.9.2
3
+ Version: 1.3.1
4
4
  Summary: A multifunctional all-in-one utility tool for managing internal Python objects, compatible with nearly all Python 3 versions. 一个多功能合一的提供操作Python对象底层工具的Python包, 支持几乎所有Python 3版本。
5
5
  Home-page: https://github.com/qfcy/pyobject
6
6
  Author: qfcy
@@ -15,406 +15,12 @@ Classifier: Topic :: Software Development :: Testing
15
15
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
16
  License-File: LICENSE
17
17
 
18
- pyobject - 一个多功能合一的提供操作Python对象底层工具的Python包,
19
- 支持几乎所有Python 3版本。 A multifunctional all-in-one utility tool for
20
- managing internal Python objects, compatible with nearly all Python 3
21
- versions.
18
+ |Stars| |GitHub release| |License: MIT|
22
19
 
23
- **The English introduction is shown below the Chinese version.**
20
+ pyobject - A multifunctional all-in-one utility tool for managing
21
+ internal Python objects, compatible with nearly all Python 3 versions.
24
22
 
25
- 子模块
26
- ------
27
-
28
- pyobject.\__init\_\_ - 显示和输出Python对象的各个属性值
29
-
30
- pyobject.browser - 调用tkinter,浏览Python对象的图形界面
31
-
32
- pyobject.code - Python 底层字节码(bytecode)的操作工具
33
-
34
- pyobject.search - 以一个对象为起点,查找和搜索能到达的所有python对象
35
-
36
- pyobject.objproxy -
37
- 实现一个通用的对象代理,能够代理任意Python对象,包括模块,函数和类
38
-
39
- pyobject.pyobj_extension - C扩展模块, 提供操作Python对象底层的函数
40
-
41
- 包含的函数
42
- ----------
43
-
44
- **describe(obj, level=0, maxlevel=1, tab=4, verbose=False,
45
- file=sys.stdout)**:
46
-
47
- 以\ ``属性名: 值``\ 格式,打印出对象的各个属性,便于实时调试对象。(别名为\ ``desc()``\ )
48
-
49
- - maxlevel: 打印对象属性的层数。
50
- - tab: 缩进的空格数,默认为4。
51
- - verbose: 一个布尔值,是否打印出对象的特殊方法(如\ ``__init__``\ )。
52
- - file: 一个类似文件的对象,用于打印输出。
53
-
54
- **browse(object, verbose=False, name=‘obj’)**:
55
-
56
- 用图形界面浏览任意的Python对象,需要tkinter库。
57
-
58
- - verbose:
59
- 与describe相同,是否打印出对象的特殊方法(如\ ``__init__``\ )。
60
-
61
- 函数browse()的图形界面如下(中文的版本可在包目录内的\ `other/browser_chs_locale.py <https://github.com/qfcy/pyobject/blob/main/pyobject/other/browser_chs_locale.py>`__\ 中找到):
62
-
63
- .. figure::
64
- https://i-blog.csdnimg.cn/blog_migrate/3d67b32633815a54c8c9d0c370248318.png
65
- :alt: browse函数界面图片
66
-
67
- browse函数界面图片
68
-
69
- **bases(obj, level=0, tab=4)**:
70
-
71
- bases(obj) - 打印出对象的基类,以及继承顺序。
72
-
73
- - tab: 缩进的空格数,默认为4。
74
-
75
- 用于对象搜索的函数
76
- ------------------
77
-
78
- **make_list(start_obj, recursions=2, all=False)**:
79
-
80
- 创建一个对象的列表,列表中无重复的对象。
81
-
82
- - start: 开始搜索的对象
83
- - recursion: 递归次数
84
- - all: 是否将对象的特殊属性(如\ ``__init__``\ )加入列表
85
-
86
- **make_iter(start_obj, recursions=2, all=False)**:
87
-
88
- 功能、参数与make_list相同,但创建迭代器,且迭代器中可能有重复的对象。
89
-
90
- **search(obj, start, recursions=3, search_str=False)**:
91
-
92
- 从一个起点开始搜索对象,如\ ``search(os, sys, 3)``\ 返回\ ``["sys.modules['site'].os", "sys.modules['os']", ...]``\ 的结果。
93
-
94
- - obj: 待搜索的对象
95
- - start: 起点对象
96
- - recursion: 递归次数
97
- - search_str: 是否是查找字符串子串
98
-
99
- 类: ``pyobject.Code``
100
- ---------------------
101
-
102
- 类Code提供了Python字节码(bytecode)对象的封装,便于操作Python字节码。
103
-
104
- Python内部的字节码对象\ ``CodeType``\ ,如\ ``func.__code__``\ ,是不可变的,这里的Code类提供了一个\ **可变**\ 的字节码对象,以及一系列方法,使得操作底层字节码变得更容易。
105
-
106
- 此外和Java字节码不同,Python字节码是\ **不跨版本**\ 的,不同版本Python解释器的字节码互不兼容,
107
-
108
- 而Code类提供了字节码的\ **通用接口**\ ,支持\ **3.4至3.14**\ 之间的所有Python版本(甚至PyPy的.pyc格式),简化了复杂的版本兼容性问题。
109
-
110
- 构造函数(\ ``Code(code=None)``\ )
111
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
112
-
113
- ``code``\ 参数可以是现有的 ``CodeType`` 对象,或者另一个 ``Code``
114
- 实例。如果未提供\ ``code,则会创建一个默认的``\ CodeType\` 对象。
115
-
116
- 属性
117
- ^^^^
118
-
119
- - ``_code``:
120
- 当前Code对象的内部字节码,如应使用\ ``exec(c._code)``\ 或\ ``exec(c.to_code())``\ ,而不是直接使用\ ``exec(c)``\ 。
121
-
122
- 以下是Python内置字节码的属性(也是\ ``Code``\ 对象的属性)。Python内部的字节码\ ``CodeType``\ 是不可变的,这些属性只读,但\ ``Code``\ 对象可变,也就是这些属性都\ **可修改**:
123
-
124
- - ``co_argcount``: 位置参数的数量(包括有默认值的参数)。
125
- - ``co_cellvars``: 一个包含被嵌套函数所引用的局部变量名称的元组。
126
- - ``co_code``:
127
- 一个表示字节码指令序列的\ ``bytes``\ 类型,存放真正的二进制字节码。
128
- - ``co_consts``: 一个包含字节码所使用的字面值的元组。
129
- - ``co_filename``: 被编码代码所在的文件名。
130
- - ``co_firstlineno``:
131
- 字节码对应到源文件首行的行号,在解释器内部和\ ``co_lnotab``\ 结合使用,用来在Traceback中输出精确的行号。
132
- - ``co_flags``: 一个以整数编码表示的多个解释器所用的旗标。
133
- - ``co_freevars``: 一个包含自由变量名称的元组。
134
- - ``co_kwonlyargcount``: 仅关键字参数的数量。
135
- - ``co_lnotab``:
136
- 一个以编码表示的从字节码偏移量到行号的映射的字符串(Python
137
- 3.10开始,被\ ``co_linetable``\ 替代)。
138
- - ``co_name``: 字节码对应的函数/类名称。
139
- - ``co_names``: 一个包含字节码所使用的名称的元组。
140
- - ``co_nlocals``: 函数使用的局部变量数量(包括参数)。
141
- - ``co_stacksize``: 执行字节码需要的栈大小。
142
- - ``co_varnames``: 一个包括局部变量名称的元组(以参数名打头)。
143
-
144
- 3.8及以上版本新增的属性:
145
-
146
- - ``co_posonlyargcount``: 仅位置参数的数量,在Python 3.8引入。
147
- - ``co_linetable``:
148
- 行号映射数据,从3.10开始作为\ ``co_lnotab``\ 属性的替代。
149
- - ``co_exceptiontable``: 异常表数据,Python 3.11引入。
150
- - ``co_qualname``: 字节码的全名,Python 3.11引入。
151
-
152
- 方法
153
- ^^^^
154
-
155
- **主要方法**
156
-
157
- - ``exec(globals_=None, locals_=None)``\ :在全局和局部作用域字典中执行代码对象。
158
- - ``eval(globals_=None, locals_=None)``\ :在全局和局部作用域字典中执行代码对象,并获取返回值。
159
- - ``copy()``\ :复制一份\ ``Code``\ 对象,返回复制的副本。
160
- - ``to_code()``\ :将 ``Code`` 实例转换回内置的 ``CodeType``
161
- 对象,和\ ``c._code``\ 相同。
162
- - ``to_func(globals_=None, name=None, argdefs=None, closure=None, kwdefaults=None)``\ :将代码对象转换为
163
- Python
164
- 函数,参数用法和Python内置\ ``FunctionTypes``\ 实例化的参数相同。
165
- - ``get_flags()``\ :返回 ``co_flags``
166
- 属性的标志名称列表,如\ ``["NOFREE"]``\ 。
167
- - ``get_sub_code(name)``\ :搜索代码的\ ``co_consts``\ 中的子代码,如函数、类定义等,不会递归搜索。返回搜索到的\ ``Code``\ 对象,未找到时抛出\ ``ValueError``\ 。
168
-
169
- **序列化**
170
-
171
- - ``to_pycfile(filename)``\ :使用 ``marshal`` 模块将代码对象转储到
172
- ``.pyc`` 文件中。
173
- - ``from_pycfile(filename)``\ :从 ``.pyc`` 文件创建 ``Code`` 实例。
174
- - ``from_file(filename)``\ :从 ``.py`` 或 ``.pyc`` 文件创建 ``Code``
175
- 实例。
176
- - ``pickle(filename)``\ :将 ``Code`` 对象序列化为 pickle 文件。
177
-
178
- **调试和检查**
179
-
180
- - ``show(*args, **kw)``\ :在内部调用\ ``pyobject.desc``\ ,显示代码对象的属性,参数用法和\ ``desc()``\ 的用法相同。
181
- - ``info()``\ :在内部调用\ ``dis.show_code``\ ,显示字节码的基本信息。
182
- - ``dis(*args, **kw)``\ :调用 ``dis``
183
- 模块输出字节码的反汇编,和\ ``dis.dis(c.to_code())``\ 相同。
184
- - ``decompile(version=None, *args, **kw)``\ :调用 ``uncompyle6``
185
- 库将代码对象反编译为源代码。(安装\ ``pyobject``\ 库时,
186
- ``uncompyle6`` 库是可选的。)
187
-
188
- **工厂函数**
189
-
190
- - ``fromfunc(function)``\ :从 Python 函数对象创建 ``Code``
191
- 实例,和\ ``Code(func.__code__)``\ 相同。
192
- - ``fromstring(string, mode='exec', filename='')``\ :从源代码字符串创建
193
- ``Code``
194
- 实例,参数用法和\ ``compile``\ 内置函数相同,在内部调用\ ``compile()``\ 。
195
-
196
- 兼容性细节
197
- ^^^^^^^^^^
198
-
199
- - 属性\ ``co_lnotab``\ :在3.10以上的版本中,如果尝试设置\ ``co_lnotab``\ 属性,会自动转换成设置\ ``co_linetable``\ 。
200
-
201
- 示例用法: (从doctest中摘取):
202
-
203
- .. code:: python
204
-
205
- >>> def f():print("Hello")
206
- >>> c=Code.fromfunc(f) # 或 c=Code(f.__code__)
207
- >>> c.co_consts
208
- (None, 'Hello')
209
- >>> c.co_consts=(None, 'Hello World!')
210
- >>> c.exec()
211
- Hello World!
212
- >>>
213
- >>> # 保存到 pickle 文件
214
- >>> import os,pickle
215
- >>> temp=os.getenv('temp')
216
- >>> with open(os.path.join(temp,"temp.pkl"),'wb') as f:
217
- ... pickle.dump(c,f)
218
- ...
219
- >>> # 读取pickle文件,并重新执行读取到的字节码
220
- >>> f=open(os.path.join(temp,"temp.pkl"),'rb')
221
- >>> pickle.load(f).to_func()()
222
- Hello World!
223
- >>> # 转换为pyc文件,并导入pyc模块
224
- >>> c.to_pycfile(os.path.join(temp,"temppyc.pyc"))
225
- >>> sys.path.append(temp)
226
- >>> import temppyc
227
- Hello World!
228
- >>> Code.from_pycfile(os.path.join(temp,"temppyc.pyc")).exec()
229
- Hello World!
230
-
231
- 对象代理类\ ``ObjChain``\ 和\ ``ProxiedObj``
232
- --------------------------------------------
233
-
234
- ``pyobject.objproxy``\ 是一个强大的代理任何其他对象,生成调用对象的代码的工具,能够记录对象的详细访问和调用历史记录。
235
- ``ObjChain``\ 是用于管理多个\ ``ProxiedObj``\ 对象的类封装,\ ``ProxiedObj``\ 是代理其他对象的类。
236
-
237
- 示例用法:
238
-
239
- .. code:: python
240
-
241
- from pyobject import ObjChain
242
-
243
- chain = ObjChain(export_attrs=["__array_struct__"])
244
- np = chain.new_object("import numpy as np","np")
245
- plt = chain.new_object("import matplotlib.pyplot as plt","plt",
246
- export_funcs = ["show"])
247
-
248
- # 测试调用代理后的numpy, matplotlib模块
249
- arr = np.array(range(1,11))
250
- arr_squared = arr ** 2
251
- print(np.mean(arr)) # 输出平均值
252
-
253
- plt.plot(arr, arr_squared) # 绘制y=x**2的图像
254
- plt.show()
255
-
256
- # 显示自动生成的调用numpy, matplotlib库的代码
257
- print(f"Code:\n{chain.get_code()}\n")
258
- print(f"Optimized:\n{chain.get_optimized_code()}")
259
-
260
- 输出效果:
261
-
262
- .. code:: python
263
-
264
- Code: # 未优化的代码,包含了对象的所有详细访问记录
265
- import numpy as np
266
- import matplotlib.pyplot as plt
267
- var0 = np.array
268
- var1 = var0(range(1, 11))
269
- var2 = var1 ** 2
270
- var3 = np.mean
271
- var4 = var3(var1)
272
- var5 = var1.mean
273
- var6 = var5(axis=None, dtype=None, out=None)
274
- ex_var7 = str(var4)
275
- var8 = plt.plot
276
- var9 = var8(var1, var2)
277
- var10 = var1.to_numpy
278
- var11 = var1.values
279
- var12 = var1.shape
280
- var13 = var1.ndim
281
- ...
282
- var81 = var67.__array_struct__
283
- ex_var82 = iter(var70)
284
- ex_var83 = iter(var70)
285
- var84 = var70.mask
286
- var85 = var70.__array_struct__
287
- var86 = plt.show
288
- var87 = var86()
289
-
290
- Optimized: # 优化后的代码
291
- import numpy as np
292
- import matplotlib.pyplot as plt
293
- var1 = np.array(range(1, 11))
294
- plt.plot(var1, var1 ** 2)
295
- plt.show()
296
-
297
- 详细用法
298
- ^^^^^^^^
299
-
300
- | **``ObjChain``**
301
- | - ``ObjChain(export_funcs = None, export_attrs = None)``:
302
- 创建一个\ ``ObjChain``\ 对象,\ ``export_funcs``\ 为全局范围需要导出的函数列表,\ ``export_attrs``\ 为全局范围需要导出的属性列表。由于是全局范围,对所有变量有效。
303
- -
304
- ``new_object(code_line,name, export_funcs=None, export_attrs=None, use_target_obj=True)``:
305
- 新增一个对象,返回一个生成的\ ``ProxiedObj``\ 类型的代理对象,返回值可以直接当作普通对象使用。
306
- | ``code_line``\ 是为了得到这个对象而需要执行的代码(如\ ``"import numpy as np"``\ ),\ ``name``\ 是执行之后对象放在的变量值(如\ ``"np"``\ )。
307
- | ``export_funcs``\ 和\ ``export_attrs``\ 是针对这个对象,需要导出的方法和属性列表。
308
- | ``use_target_obj``\ 为是否实时创建一个代理的模板对象,并操作(详见“实现原理”一节)。
309
- | - ``add_existing_obj(obj, name)``:
310
- 添加现有的对象,返回一个\ ``ProxiedObj``\ 类型的代理对象。
311
- | ``obj``\ 为对象,\ ``name``\ 为任意的变量名,用来在\ ``ObjChain``\ 生成的代码中,指代这个对象。
312
- | - ``get_code(start_lineno=None, end_lineno=None)``:
313
- 获取\ ``ObjChain``\ 生成的原始代码,\ ``start_lineno``\ 和\ ``end_lineno``\ 为从0开始的行号,如果未指定,则默认为开头和末尾。
314
- -
315
- ``get_optimized_code(no_optimize_vars=None, remove_internal=True, remove_export_type=True)``:
316
- 获取优化后的代码,内部使用了有向无环图(DAG)进行优化(详见“实现原理”一节)。
317
- | ``no_optimize_vars``: 不能移除的变量名的列表,如\ ``["temp_var"]``\ 。
318
- | ``remove_internal``:
319
- 是否移除执行代码本身时产生的内部代码。例如\ ``plt.plot``\ 和\ ``arr``,
320
- ``arr2``\ 都是\ ``ProxiedObj``\ 对象,
321
- 如果\ ``remove_internal``\ 为\ ``False``\ ,调用\ ``plt.plot(arr,arr2)``\ 本身时生成的访问\ ``arr``,
322
- ``arr2``\ 的内部代码,如\ ``var13 = arr.ndim``\ 不会被移除。
323
- | ``remove_export_type``: 是否移除无用的类型导出,如\ ``str(var)``\ 。
324
-
325
- **``ProxiedObj``**
326
-
327
- ``ProxiedObj``\ 为\ ``ObjChain``\ 的\ ``new_object()``\ 、\ ``add_existing_obj()``\ 返回的代理对象的类型,可以替代任何普通对象使用,但通常不建议直接使用\ ``ProxiedObj``\ 类本身的方法和属性。
328
-
329
- 实现原理
330
- ^^^^^^^^
331
-
332
- | ``ObjChain``\ 类\ **追踪**\ 所有加入\ ``ObjChain``\ 的对象,以及派生出的对象,并且维护一个包含被追踪的对象的命名空间字典,用于调用\ ``exec``\ 执行自身生成的代码。
333
- | 每个\ ``ProxiedObj``\ 对象属于一个\ ``ObjChain``\ 。\ ``ProxiedObj``\ 类的所有魔法方法(如\ ``__call__``,
334
- ``__getattr__``\ )都是被\ **重写**\ 的,重写的方法一边将调用记录加入\ ``ProxiedObj``\ 属于的\ ``ObjChain``\ ,
335
- 一边调用自身代理的对象\ ``__target_obj``\ (如果有)的相同魔法方法。
336
- | 当对\ ``ProxiedObj``\ 的操作返回了新的对象(如\ ``obj.attr``\ 返回新的属性)时,新的对象也会被\ ``ObjChain``\ 追踪,直到\ ``ObjChain``\ 内部形成一个从第一个对象开始,派生出的所有对象的\ **长链**\ 。
337
- | 如果\ ``ProxiedObj``\ 存在\ ``__target_obj``\ 属性,则调用\ ``ProxiedObj``\ 的魔法方法时,会\ **同步**\ 地调用\ ``__target_obj``\ 的魔法方法,并将返回的结果传递给下一个\ ``ProxiedObj``\ 的\ ``__target_obj``\ 属性。
338
- | 如果\ ``__target_obj``\ 属性不存在,\ ``ProxiedObj``\ 不会同步地调用魔法方法,而是生成一份调用记录的代码,\ **临时保存**\ 在\ ``ProxiedObj``\ 中,直到出现了需要导出(\ ``export``\ )的方法或属性,
339
- 才会一次性执行全部之前加入的代码,并返回结果。
340
-
341
- **代码优化的原理**
342
-
343
- | 在代码中,变量的依赖关系可以表示为一个\ **图**\ ,如语句\ ``y = func(x)``\ 可以表示为节点\ ``x``\ 有一条指向\ ``y``\ 的边。
344
- | 但由于\ ``ProxiedObj``\ 生成的代码中一个对象只能对应一个变量,变量不能被重新赋值(类似js的\ ``const``\ ),会形成一个有向无环图(DAG)。
345
- | 优化时首先找出只影响0个或1个其他变量(只指向0~1个其他节点)的变量,如果只影响一个变量,则将自身的值代入被影响的语句进行内联,否则直接去除自身。
346
- | 如:
347
-
348
- .. code:: python
349
-
350
- temp_var = [1,2,3]
351
- unused_var = func(temp_var)
352
-
353
- | 代码中\ ``temp_var``\ 只有一条指向\ ``unused_var``\ 的边,而\ ``unused_var``\ 没有任何指出的边。
354
- | 将\ ``temp_var``\ 的值代入\ ``func(temp_var)``\ 进行内联,得到\ ``unused_var = func([1,2,3])``\ ,再去掉\ ``unused_var``\ ,优化后的代码会变成\ ``func([1,2,3])``\ 。
355
-
356
- 模块\ ``pyobject.pyobj_extension``
357
- ----------------------------------
358
-
359
- 本模块使用了C语言编写。可使用\ ``import pyobject.pyobj_extension as pyobj_extension``,
360
- 导入该独立模块。其中包含的函数如下:
361
-
362
- **convptr(pointer)**:
363
-
364
- 将整数指针转换为Python对象,与id()相反。
365
-
366
- **py_decref(object, n)**:
367
-
368
- 将对象的引用计数减小1。
369
-
370
- **py_incref(object, n)**:
371
-
372
- 将对象的引用计数增加1。
373
-
374
- **getrealrefcount(obj)**:
375
-
376
- | 获取调用本函数前对象的实际引用计数。和sys.getrefcount()不同,不考虑调用时新增的引用计数。(差值为\ ``_REFCNT_DELTA``\ 这个常量)
377
- | 如:getrealrefcount([])会返回0,因为退出getrealrefcount后列表[]不再被任何对象引用,而sys.getrefcount([])会返回1。
378
- | 另外,a=[];getrealrefcount(a)会返回1而不是2。
379
-
380
- **setrefcount(obj, n)**:
381
-
382
- 设置对象的实际引用计数(调用函数前)为n,和getrealrefcount()相反,同样不考虑调用时新增的引用计数。
383
-
384
- **getrefcount_nogil(obj)**\ 和\ **setrefcount_nogil(obj,ref_data)**:
385
-
386
- 在Python
387
- 3.14+的无GIL版本中获取和设置引用计数,\ ``ref_data``\ 为\ ``(ob_ref_local, ob_ref_shared)``\ ,不考虑调用时新增的引用计数。(实验性)
388
-
389
- *警告: 不恰当地调用这些函数可能导致Python崩溃。*
390
-
391
- **list_in(obj, lst)**:
392
-
393
- 判断obj是否在列表或元组lst中。与Python内置的obj in
394
- lst调用多次==运算符(``__eq__``)相比,
395
- 本函数直接比较对象的指针,提高了效率。
396
-
397
- **``pyobject``\ 当前版本**: 1.2.9.2
398
-
399
- 更新日志:
400
- ---------
401
-
402
- | 2025-4-30(v1.2.9):改进和增强了子模块pyobject.objproxy,重命名子模块pyobject.code_为pyobject.code。
403
- | 2025-3-31(v1.2.8):将pyobject.super_proxy重命名为pyobject.objproxy,并正式发布;修改了pyobject.pyobj_extension模块。
404
- | 2025-3-6(v1.2.7):为pyobject.browser新增了\ ``dir()``\ 中不存在的类属性(如\ ``__flags__``,
405
- ``__mro__``\ ),修改了pyobj_extension模块。
406
- | 2025-2-15(v1.2.6):修复了pyobject.browser浏览过大对象的卡顿问题,改进了pyobject.code_模块,新增了正在开发中的反射库pyobject.super_proxy,
407
- 在pyobj_extension新增了\ ``getrefcount_nogil``\ 和\ ``setrefcount_nogil``\ 。
408
- | 2024-10-24(v1.2.5):修复了pyobject.browser在Windows下的高DPI支持,修改了pyobj_extension模块,以及其他改进。
409
- | 2024-8-12(v1.2.4):针对pyobject.code_增加了对3.10及以上版本的支持;进一步优化了search模块的搜索性能,以及一些其他修复和改进。
410
- | 2024-6-20(v1.2.3):更新了包内test目录下的.pyc文件加壳工具,并更新了pyobject.browser中的对象浏览器,添加了显示列表和字典项,后退、前进、刷新页面,以及新增、编辑和删除项等新特性。
411
- | 2022-7-25(v1.2.2):增加了操作Python底层对象引用,
412
- 以及对象指针的C语言模块pyobj_extension。
413
- | 2022-2-2(v1.2.0):修复了一些bug,优化了search模块的性能;
414
- code_中增加了Code类, browser中增加编辑属性功能,
415
- 增加了Code类的doctest。
416
-
417
- --------------
23
+ [English \| `中文 <README_zh.md>`__]
418
24
 
419
25
  Submodules:
420
26
  -----------
@@ -751,11 +357,12 @@ Detailed Usage
751
357
  and returns a proxy object of type ``ProxiedObj``.
752
358
  | ``obj`` is the object to be added, and ``name`` is an arbitrary
753
359
  variable name that will be used to refer to this object in the code
754
- generated by ``ObjChain``. -
755
- ``get_code(start_lineno=None, end_lineno=None)``: Retrieves the
756
- original code generated by ``ObjChain``. ``start_lineno`` and
757
- ``end_lineno`` are line numbers starting from 0, and if not specified,
758
- they default to the beginning and end. -
360
+ generated by ``ObjChain``. ``use_exported_obj`` determines whether not
361
+ to pass the ``ProxiedObj`` object as a calling parameter to
362
+ ``__target_obj``. - ``get_code(start_lineno=None, end_lineno=None)``:
363
+ Retrieves the original code generated by ``ObjChain``.
364
+ ``start_lineno`` and ``end_lineno`` are line numbers starting from 0,
365
+ and if not specified, they default to the beginning and end. -
759
366
  ``get_optimized_code(no_optimize_vars=None, remove_internal=True, remove_export_type=True)``:
760
367
  Retrieves the optimized code. Internally, a directed acyclic graph
761
368
  (DAG) is used for optimization (see the “Implementation” section).
@@ -886,11 +493,15 @@ Python call “obj in lst” that invokes the “==” operator (``__eq__``)
886
493
  multiple times, this function directly compares the pointers to improve
887
494
  efficiency.
888
495
 
889
- **Current Version of ``pyobject``**: 1.2.9.2
496
+ **Current Version of ``pyobject``**: 1.3.1
890
497
 
891
498
  Change Log
892
499
  ----------
893
500
 
501
+ | 2025-6-23(v1.3.1): Added the ``use_exported_obj`` parameter to the
502
+ pyobject.objproxy module and further optimized the performance.
503
+ | 2025-6-6(v1.3.0): Optimized the performance of the pyobject.objproxy
504
+ module.
894
505
  | 2025-4-30(v1.2.9): Improved and enhanced the sub-module
895
506
  ``pyobject.objproxy``, and renamed the sub-module ``pyobject.code_``
896
507
  to ``pyobject.code``.
@@ -923,3 +534,10 @@ Change Log
923
534
  of the ``search`` module; added the ``Code`` class in ``code_``,
924
535
  introduced editing properties functionality in ``browser``, and added
925
536
  doctests for the ``Code`` class.
537
+
538
+ .. |Stars| image:: https://img.shields.io/github/stars/qfcy/pyobject
539
+ :target: https://img.shields.io/github/stars/qfcy/pyobject
540
+ .. |GitHub release| image:: https://img.shields.io/github/v/release/qfcy/pyobject
541
+ :target: https://github.com/qfcy/pyobject/releases/latest
542
+ .. |License: MIT| image:: https://img.shields.io/github/license/qfcy/pyobject
543
+ :target: https://github.com/qfcy/pyobject/blob/main/LICENSE