pyobject 1.2.9.2__tar.gz → 1.3.0__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.
- {pyobject-1.2.9.2/pyobject.egg-info → pyobject-1.3.0}/PKG-INFO +6 -3
- {pyobject-1.2.9.2 → pyobject-1.3.0}/README.rst +5 -2
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/__init__.py +3 -3
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/examples/test_inject.py +3 -3
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/objproxy/__init__.py +197 -207
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/objproxy/builtin_hook.py +2 -20
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/tests/test_objproxy.py +21 -1
- {pyobject-1.2.9.2 → pyobject-1.3.0/pyobject.egg-info}/PKG-INFO +6 -3
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject.egg-info/SOURCES.txt +0 -1
- pyobject-1.2.9.2/pyobject/objproxy/dynobj.py +0 -190
- {pyobject-1.2.9.2 → pyobject-1.3.0}/LICENSE +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/MANIFEST.in +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/browser.py +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/code.py +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/examples/README.md +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/examples/__init__.py +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/examples/empty_cp37.pyc +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/examples/pyc_zipper_unpack.py +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/examples/pyc_zipper_zlib.py +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/images/back.gif +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/images/codeobject.gif +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/images/dict.gif +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/images/empty_dict.gif +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/images/empty_list.gif +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/images/empty_tuple.gif +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/images/forward.gif +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/images/function.gif +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/images/list.gif +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/images/number.gif +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/images/python.gif +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/images/python.ico +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/images/refresh.gif +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/images/string.gif +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/images/tuple.gif +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/objproxy/optimize.py +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/objproxy/utils.py +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/other/browser_chs_locale.py +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/pyobj_extension.c +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/search.py +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/tests/test_code.py +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject/tests/test_objproxy_perf.py +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject.egg-info/dependency_links.txt +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject.egg-info/requires.txt +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/pyobject.egg-info/top_level.txt +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/setup.cfg +0 -0
- {pyobject-1.2.9.2 → pyobject-1.3.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyobject
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
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
|
|
@@ -394,11 +394,12 @@ Python内部的字节码对象\ ``CodeType``\ ,如\ ``func.__code__``\ ,是
|
|
|
394
394
|
lst调用多次==运算符(``__eq__``)相比,
|
|
395
395
|
本函数直接比较对象的指针,提高了效率。
|
|
396
396
|
|
|
397
|
-
**``pyobject``\ 当前版本**: 1.
|
|
397
|
+
**``pyobject``\ 当前版本**: 1.3.0
|
|
398
398
|
|
|
399
399
|
更新日志:
|
|
400
400
|
---------
|
|
401
401
|
|
|
402
|
+
| 2025-6-6(v1.3.0):性能优化,提升了pyobject.objproxy模块的性能。
|
|
402
403
|
| 2025-4-30(v1.2.9):改进和增强了子模块pyobject.objproxy,重命名子模块pyobject.code_为pyobject.code。
|
|
403
404
|
| 2025-3-31(v1.2.8):将pyobject.super_proxy重命名为pyobject.objproxy,并正式发布;修改了pyobject.pyobj_extension模块。
|
|
404
405
|
| 2025-3-6(v1.2.7):为pyobject.browser新增了\ ``dir()``\ 中不存在的类属性(如\ ``__flags__``,
|
|
@@ -886,11 +887,13 @@ Python call “obj in lst” that invokes the “==” operator (``__eq__``)
|
|
|
886
887
|
multiple times, this function directly compares the pointers to improve
|
|
887
888
|
efficiency.
|
|
888
889
|
|
|
889
|
-
**Current Version of ``pyobject``**: 1.
|
|
890
|
+
**Current Version of ``pyobject``**: 1.3.0
|
|
890
891
|
|
|
891
892
|
Change Log
|
|
892
893
|
----------
|
|
893
894
|
|
|
895
|
+
| 2025-6-6(v1.3.0): Optimized the performance of the pyobject.objproxy
|
|
896
|
+
module.
|
|
894
897
|
| 2025-4-30(v1.2.9): Improved and enhanced the sub-module
|
|
895
898
|
``pyobject.objproxy``, and renamed the sub-module ``pyobject.code_``
|
|
896
899
|
to ``pyobject.code``.
|
|
@@ -377,11 +377,12 @@ Python内部的字节码对象\ ``CodeType``\ ,如\ ``func.__code__``\ ,是
|
|
|
377
377
|
lst调用多次==运算符(``__eq__``)相比,
|
|
378
378
|
本函数直接比较对象的指针,提高了效率。
|
|
379
379
|
|
|
380
|
-
**``pyobject``\ 当前版本**: 1.
|
|
380
|
+
**``pyobject``\ 当前版本**: 1.3.0
|
|
381
381
|
|
|
382
382
|
更新日志:
|
|
383
383
|
---------
|
|
384
384
|
|
|
385
|
+
| 2025-6-6(v1.3.0):性能优化,提升了pyobject.objproxy模块的性能。
|
|
385
386
|
| 2025-4-30(v1.2.9):改进和增强了子模块pyobject.objproxy,重命名子模块pyobject.code_为pyobject.code。
|
|
386
387
|
| 2025-3-31(v1.2.8):将pyobject.super_proxy重命名为pyobject.objproxy,并正式发布;修改了pyobject.pyobj_extension模块。
|
|
387
388
|
| 2025-3-6(v1.2.7):为pyobject.browser新增了\ ``dir()``\ 中不存在的类属性(如\ ``__flags__``,
|
|
@@ -869,11 +870,13 @@ Python call “obj in lst” that invokes the “==” operator (``__eq__``)
|
|
|
869
870
|
multiple times, this function directly compares the pointers to improve
|
|
870
871
|
efficiency.
|
|
871
872
|
|
|
872
|
-
**Current Version of ``pyobject``**: 1.
|
|
873
|
+
**Current Version of ``pyobject``**: 1.3.0
|
|
873
874
|
|
|
874
875
|
Change Log
|
|
875
876
|
----------
|
|
876
877
|
|
|
878
|
+
| 2025-6-6(v1.3.0): Optimized the performance of the pyobject.objproxy
|
|
879
|
+
module.
|
|
877
880
|
| 2025-4-30(v1.2.9): Improved and enhanced the sub-module
|
|
878
881
|
``pyobject.objproxy``, and renamed the sub-module ``pyobject.code_``
|
|
879
882
|
to ``pyobject.code``.
|
|
@@ -6,7 +6,7 @@ import sys
|
|
|
6
6
|
from warnings import warn
|
|
7
7
|
from pprint import pprint
|
|
8
8
|
|
|
9
|
-
__version__="1.
|
|
9
|
+
__version__="1.3.0"
|
|
10
10
|
|
|
11
11
|
__all__=["objectname","bases","describe","desc"]
|
|
12
12
|
_ignore_names=["__builtins__","__doc__"]
|
|
@@ -97,8 +97,8 @@ try:
|
|
|
97
97
|
"set_type_subclasses_by_cls"])
|
|
98
98
|
except ImportError:warn("Failed to import pyobject.pyobj_extension.")
|
|
99
99
|
try:
|
|
100
|
-
from pyobject.objproxy import
|
|
101
|
-
__all__.extend(["
|
|
100
|
+
from pyobject.objproxy import ObjChain,ProxiedObj,unproxy_obj
|
|
101
|
+
__all__.extend(["ObjChain","ProxiedObj","unproxy_obj"])
|
|
102
102
|
except (ImportError, SyntaxError):
|
|
103
103
|
warn("Failed to import pyobject.objproxy.") # Python 3.5及以下不支持f-string,无法使用objproxy库
|
|
104
104
|
|
|
@@ -7,7 +7,7 @@ except ImportError:
|
|
|
7
7
|
from importlib._bootstrap import MAGIC_NUMBER
|
|
8
8
|
|
|
9
9
|
MARK=b"#####MyPython####"
|
|
10
|
-
TARGET='empty_cp37.pyc' #
|
|
10
|
+
TARGET='empty_cp37.pyc' # 需Python 3.7
|
|
11
11
|
|
|
12
12
|
def extract_file(filename):
|
|
13
13
|
# 将py,pyc文件还原为Code对象
|
|
@@ -121,10 +121,10 @@ def spread_to_mod(modname,use_pycache=True):
|
|
|
121
121
|
if use_pycache and file.endswith('.py') or file.endswith('.pyw'):
|
|
122
122
|
# 获取目标文件位置
|
|
123
123
|
splited=os.path.split(file)
|
|
124
|
-
os.makedirs(splited[0] + '
|
|
124
|
+
os.makedirs(splited[0] + '/__pycache__',exist_ok=True)
|
|
125
125
|
pyc=os.path.splitext(splited[1])[0] + \
|
|
126
126
|
'.cpython-%d%d' % (sys.version_info.major,sys.version_info.minor)
|
|
127
|
-
target=splited[0] + '
|
|
127
|
+
target=splited[0] + '/__pycache__/'+pyc+'.pyc'
|
|
128
128
|
else:target=None
|
|
129
129
|
co=spread(file,pycfile=target)
|
|
130
130
|
return co
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import functools,itertools,types
|
|
2
2
|
from pyobject import shortrepr
|
|
3
|
-
from pyobject.objproxy.dynobj import DynObj
|
|
4
3
|
from pyobject.objproxy.optimize import optimize_code
|
|
5
4
|
from pyobject.objproxy.utils import *
|
|
6
5
|
|
|
@@ -24,42 +23,6 @@ def unproxy_obj(obj):
|
|
|
24
23
|
obj = obj._ProxiedObj__target_obj
|
|
25
24
|
return obj
|
|
26
25
|
|
|
27
|
-
def unproxy_obj_recursive(obj): # 递归解除obj的代理(备用函数)
|
|
28
|
-
while _isinstance(obj, ProxiedObj):
|
|
29
|
-
obj = obj._ProxiedObj__target_obj
|
|
30
|
-
# 递归处理容器
|
|
31
|
-
if _isinstance(obj, dict):
|
|
32
|
-
return {unproxy_obj_recursive(k): unproxy_obj_recursive(v)
|
|
33
|
-
for k, v in obj.items()}
|
|
34
|
-
elif _isinstance(obj, list):
|
|
35
|
-
return [unproxy_obj_recursive(item) for item in obj]
|
|
36
|
-
elif _isinstance(obj, tuple):
|
|
37
|
-
return tuple(unproxy_obj_recursive(item) for item in obj)
|
|
38
|
-
elif _isinstance(obj, set):
|
|
39
|
-
return {unproxy_obj_recursive(item) for item in obj}
|
|
40
|
-
else:
|
|
41
|
-
return obj
|
|
42
|
-
def accept_raw_obj(func,process_arg=None,process_kw=None,process_ret=None):
|
|
43
|
-
# 装饰器,用于有target_obj时只接受原始对象而不是ProxiedObj的函数(备用)
|
|
44
|
-
@functools.wraps(func)
|
|
45
|
-
def inner(*args,**kw):
|
|
46
|
-
args = unproxy_obj_recursive(args)
|
|
47
|
-
kw = unproxy_obj_recursive(kw)
|
|
48
|
-
|
|
49
|
-
if process_arg is not None:
|
|
50
|
-
args = process_arg(args)
|
|
51
|
-
if process_kw is not None:
|
|
52
|
-
kw = process_kw(kw)
|
|
53
|
-
|
|
54
|
-
if kw:
|
|
55
|
-
result = func(*args,**kw)
|
|
56
|
-
else:
|
|
57
|
-
result = func(*args)
|
|
58
|
-
if process_ret is not None:
|
|
59
|
-
result = process_ret(result)
|
|
60
|
-
return result
|
|
61
|
-
return inner
|
|
62
|
-
|
|
63
26
|
class _EmptyTarget:
|
|
64
27
|
def __bool__(self):return False
|
|
65
28
|
EMPTY_OBJ = _EmptyTarget() # 空对象的特殊值
|
|
@@ -87,7 +50,7 @@ def is_trivial_obj(obj): # 检查对象能否被repr()表示(即对象必须
|
|
|
87
50
|
if type(obj) not in TRIVIAL_TYPES: # 不使用isinstance(由于不能是基本类型子类)
|
|
88
51
|
return False
|
|
89
52
|
if type(obj) in (list, tuple, dict, set):
|
|
90
|
-
if
|
|
53
|
+
if _isinstance(obj, dict):
|
|
91
54
|
obj = itertools.chain(obj.keys(), obj.values())
|
|
92
55
|
return all(is_trivial_obj(sub) for sub in obj)
|
|
93
56
|
return True
|
|
@@ -104,42 +67,12 @@ def is_builtin_type(cls): # 备用函数
|
|
|
104
67
|
# return True
|
|
105
68
|
#return False
|
|
106
69
|
|
|
107
|
-
def proxyCls(T=_EmptyTarget, chain=EMPTY_OBJ, fromvar=None):
|
|
108
|
-
# 泛型,proxyCls(T)生成类型信息为T的继承自ProxiedObj的类
|
|
109
|
-
if T is EMPTY_OBJ:
|
|
110
|
-
return ProxiedObj
|
|
111
|
-
|
|
112
|
-
class ProxyCls(ProxiedObj): # 创建同时从ProxiedObj与T继承的类
|
|
113
|
-
# pylint: disable=unused-private-member
|
|
114
|
-
__proto = T # 自身使用的原型
|
|
115
|
-
def __new__(cls,*args,**kw):
|
|
116
|
-
_chain = args[0] if args else kw.get("chain")
|
|
117
|
-
if not _isinstance(_chain,ObjChain) and chain is not EMPTY_OBJ:
|
|
118
|
-
var = chain.new_var(T.__name__)
|
|
119
|
-
if fromvar is not None:
|
|
120
|
-
# pylint: disable=self-cls-assignment
|
|
121
|
-
cls = chain.add_existing_obj(T,var,f"{var} = {fromvar}.__class__",
|
|
122
|
-
[fromvar])
|
|
123
|
-
else:
|
|
124
|
-
cls = chain.add_existing_obj(T,var, # pylint: disable=self-cls-assignment
|
|
125
|
-
f"# class {var}: {shortrepr(cls,repr_func=basic_repr)}")
|
|
126
|
-
if len(args) == 3 and isinstance(T,type):
|
|
127
|
-
args=(args[0],tuple(unproxy_obj(cls) for cls in args[1]),args[2])
|
|
128
|
-
|
|
129
|
-
if kw:return cls(*args,**kw)
|
|
130
|
-
return cls(*args) # 返回ProxyCls
|
|
131
|
-
else:
|
|
132
|
-
return ProxiedObj.__new__(cls,*args,**kw)
|
|
133
|
-
|
|
134
|
-
return ProxyCls
|
|
135
|
-
|
|
136
70
|
class ObjChain:
|
|
137
71
|
def __init__(self, export_funcs = None, export_attrs = None,
|
|
138
72
|
export_trivial_obj = False, hook_inheritance = False,
|
|
139
73
|
hook_method_call = False):
|
|
140
74
|
# ObjChain()的export_funcs和export_attrs作用于当前链的所有对象
|
|
141
75
|
self.codes = []
|
|
142
|
-
self.indent = 0 # 代码缩进格数(暂未使用)
|
|
143
76
|
self.scope = {} # 上次执行的命名空间
|
|
144
77
|
self.export_funcs = {} # 哪些函数需要导出(键为对象的变量名,值为属性名的列表,属性名可用"."分隔)
|
|
145
78
|
self.export_attrs = {} # 哪些属性需要导出(键为对象的变量名)
|
|
@@ -153,19 +86,26 @@ class ObjChain:
|
|
|
153
86
|
self._var_num = 0 # 变量序号
|
|
154
87
|
self.code_vars = [] # 每行代码修改和依赖于的变量,例如[("result_var",["depend_var1",...],{}),...],{}为额外信息
|
|
155
88
|
self.code_executed = [] # 代码是否已执行过(确保代码只执行一次)
|
|
89
|
+
self._executed_idx = 0 # 前面全部执行过的行号
|
|
156
90
|
self._is_evaluating = False # 当前是否正在执行调用(用于代码的_internal信息)
|
|
157
91
|
self.export_trivial_obj = export_trivial_obj # 是否不使用ProxiedObj包装基本类型(如整数、列表等)
|
|
158
92
|
self.hook_inheritance = hook_inheritance # 是否继续hook从ProxiedObj包装的类继承的新类
|
|
159
93
|
self.hook_method_call = hook_method_call # 是否hook实例方法的调用
|
|
160
94
|
def add_code(self,code_line,result_var=None,dependency_vars=None,
|
|
161
95
|
executed=True,**extra_info):
|
|
96
|
+
# result_var: 新变量名(每个变量对应的对象id不变,类似js的const)
|
|
97
|
+
# dependency_vars: 依赖的变量列表(可能会修改对象,但不会修改变量的对象id)
|
|
162
98
|
if dependency_vars is None:
|
|
163
99
|
dependency_vars = []
|
|
164
|
-
self.codes.append(
|
|
100
|
+
self.codes.append(code_line)
|
|
165
101
|
if "_internal" not in extra_info:
|
|
166
102
|
extra_info["_internal"] = self._is_evaluating # _internal: 是否是执行其他生成代码时,递归生成的
|
|
167
103
|
self.code_vars.append((result_var,dependency_vars,extra_info))
|
|
168
104
|
self.code_executed.append(executed)
|
|
105
|
+
def remove_last_line(self): # 删除最后一行代码
|
|
106
|
+
self.codes.pop()
|
|
107
|
+
self.code_vars.pop()
|
|
108
|
+
self.code_executed.pop()
|
|
169
109
|
def detect_dependency_vars(self,*iterables):
|
|
170
110
|
# 自动检测依赖的变量,返回变量名的列表和未知对象的列表
|
|
171
111
|
result = []; unknown = []
|
|
@@ -342,11 +282,11 @@ class ObjChain:
|
|
|
342
282
|
remove_export_type=True):
|
|
343
283
|
return optimize_code(self.codes, self.code_vars, no_optimize_vars,
|
|
344
284
|
remove_internal, remove_export_type)
|
|
345
|
-
def eval_value(self,var_name=None,end_lineno=None):
|
|
285
|
+
def eval_value(self,var_name=None,start_lineno=None,end_lineno=None):
|
|
346
286
|
# 一次性执行未执行过的代码(仅用于没有target_obj时)
|
|
347
287
|
if end_lineno is None:end_lineno = len(self.codes)
|
|
348
288
|
|
|
349
|
-
exec(self.get_code(
|
|
289
|
+
exec(self.get_code(start_lineno, end_lineno, _only_not_executed = True),
|
|
350
290
|
self.scope)
|
|
351
291
|
if var_name is not None:
|
|
352
292
|
return self.scope[var_name]
|
|
@@ -356,23 +296,23 @@ class ObjChain:
|
|
|
356
296
|
use_exported_obj=False):
|
|
357
297
|
# 依赖于最后一行代码,要求调用之前先调用了add_code
|
|
358
298
|
# var_name为None时,返回None(此时不可使用返回值)
|
|
359
|
-
if result_getter_func is not None and var_name is None:
|
|
360
|
-
raise ValueError("result_getter_func requires var_name")
|
|
361
|
-
|
|
362
299
|
pre_is_evaluating = self._is_evaluating
|
|
363
300
|
self._is_evaluating = True # 记录当前正在执行其他代码
|
|
364
301
|
|
|
365
302
|
new_code = self.codes[-1]
|
|
366
|
-
cur_idx = -1
|
|
303
|
+
cur_idx = len(self.codes) - 1
|
|
367
304
|
if target_obj is not EMPTY_OBJ:
|
|
368
305
|
# 一次执行完前面的全部代码
|
|
369
|
-
self.eval_value(
|
|
306
|
+
self.eval_value(start_lineno = self._executed_idx,
|
|
307
|
+
end_lineno = cur_idx) # 不包括最后一行新加入的代码
|
|
370
308
|
self.code_executed[cur_idx] = True # 最后一行设为已执行过
|
|
309
|
+
self._executed_idx = cur_idx + 1
|
|
371
310
|
|
|
372
311
|
# 实时操作对象,并返回操作结果
|
|
373
312
|
if result_getter_func is not None:
|
|
374
313
|
result = result_getter_func() # 从外部函数获取返回结果(比exec更快)
|
|
375
|
-
|
|
314
|
+
if var_name is not None:
|
|
315
|
+
self.scope[var_name] = result # 将结果存入为scope的变量(此时var_name不为None)
|
|
376
316
|
else:
|
|
377
317
|
if export or use_exported_obj: # use_exported_obj: 是否在不导出时也在exec用target_obj作为变量,避免递归
|
|
378
318
|
scope = {}
|
|
@@ -399,35 +339,45 @@ class ObjChain:
|
|
|
399
339
|
self._is_evaluating = pre_is_evaluating
|
|
400
340
|
return result # result须不为ProxiedObj类型
|
|
401
341
|
|
|
402
|
-
def magic_meth_chained(fmt = None, use_newvar = True,
|
|
403
|
-
|
|
342
|
+
def magic_meth_chained(fmt = None, use_newvar = True, export = False,
|
|
343
|
+
use_exported_obj = True, default_fmt = False,
|
|
344
|
+
no_exec = True, aug_assign = False):
|
|
404
345
|
# fmt: 代码的格式,{_var}表示新变量,{_self}表示自身变量
|
|
405
346
|
# use_newvar: 是否会生成新的返回值变量,为False时用于+=, -=等运算符
|
|
406
|
-
# indent_delta: 缩进的变化量。export: 是否返回ProxiedObj外的其他类型
|
|
407
347
|
# default_fmt: 自动生成代码的格式,此时use_target_obj总是为True
|
|
348
|
+
# no_exec: 不使用exec()执行动态生成的代码,用于提高性能
|
|
349
|
+
# aug_assign: 是否为增强赋值语句(会同时将use_newvar设为False)
|
|
350
|
+
|
|
408
351
|
if not use_newvar and export:
|
|
409
|
-
raise ValueError("can't disable use_newvar while export is
|
|
352
|
+
raise ValueError("can't disable use_newvar while export is True")
|
|
353
|
+
if aug_assign:
|
|
354
|
+
use_newvar=False # 自动将use_newvar设为False
|
|
355
|
+
if default_fmt or fmt is None:
|
|
356
|
+
raise ValueError(
|
|
357
|
+
"can't use default_fmt=True or fmt=None while aug_assign is True")
|
|
358
|
+
|
|
410
359
|
def magic_meth_chained_inner(meth):
|
|
360
|
+
meth_name = meth.__name__ # 方法名,仅default_fmt为True时使用
|
|
411
361
|
if export:
|
|
412
|
-
DEFAULT_EXPORT_FUNCS.append(
|
|
362
|
+
DEFAULT_EXPORT_FUNCS.append(meth_name) # 自动生成常量DEFAULT_EXPORT_FUNCS
|
|
413
363
|
@functools.wraps(meth)
|
|
414
364
|
def override(self, *args, **kw):
|
|
415
365
|
nonlocal use_exported_obj
|
|
416
366
|
chain = self._ProxiedObj__chain
|
|
417
|
-
|
|
418
|
-
meth_name = meth.__name__
|
|
367
|
+
self_name = self._ProxiedObj__name
|
|
419
368
|
target_obj = self._ProxiedObj__target_obj
|
|
420
369
|
no_target_obj = target_obj is EMPTY_OBJ
|
|
421
370
|
|
|
422
371
|
# ReprFormatProxy:自定义!r格式化的行为
|
|
423
372
|
fmt_kw = {key:ReprFormatProxy(val,chain.get_repr) for key,val in kw.items()}
|
|
424
|
-
fmt_kw["_self"] =
|
|
373
|
+
fmt_kw["_self"] = self_name
|
|
425
374
|
if use_newvar:
|
|
426
375
|
new_var = chain.new_var(export=export) # 申请一个新变量名
|
|
427
376
|
fmt_kw["_var"] = new_var
|
|
428
377
|
else:
|
|
429
378
|
new_var = None
|
|
430
379
|
|
|
380
|
+
# 添加代码并检测依赖的变量
|
|
431
381
|
depend_vars = chain._detect_var_and_add_obj((self,), args, kw.values())
|
|
432
382
|
if fmt is not None:
|
|
433
383
|
fmt_args = [ReprFormatProxy(arg,chain.get_repr) for arg in args]
|
|
@@ -435,28 +385,32 @@ def magic_meth_chained(fmt = None, use_newvar = True, indent_delta = 0,
|
|
|
435
385
|
chain.add_code(new_code, new_var, depend_vars, _export_type = export,
|
|
436
386
|
executed = not no_target_obj) # 加入新的一行代码
|
|
437
387
|
elif default_fmt: # 自动生成格式
|
|
438
|
-
|
|
388
|
+
fmt_args = None
|
|
389
|
+
use_exported_obj = True # 此时use_exported_obj总是为True
|
|
439
390
|
if use_newvar:
|
|
440
391
|
new_code = "{} = {}.{}({})".format(
|
|
441
|
-
new_var,
|
|
392
|
+
new_var,self_name,meth_name,format_func_call(args,kw,chain.get_repr))
|
|
442
393
|
else:
|
|
443
394
|
new_code = "{}.{}({})".format(
|
|
444
|
-
|
|
395
|
+
self_name,meth_name,format_func_call(args,kw,chain.get_repr))
|
|
445
396
|
chain.add_code(new_code, new_var, depend_vars, _export_type = export,
|
|
446
397
|
executed = not no_target_obj)
|
|
447
398
|
else:
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
chain.indent += indent_delta # 变化缩进
|
|
399
|
+
new_code = fmt_args = None
|
|
451
400
|
|
|
401
|
+
getter_func = (lambda:meth(target_obj,
|
|
402
|
+
*((unproxy_obj(arg) for arg in args) if use_exported_obj else args))) \
|
|
403
|
+
if no_exec and not no_target_obj else None # no_exec为True时,不使用关键字参数kw
|
|
452
404
|
|
|
453
405
|
# 不使用use_exported_obj时,result总是为None
|
|
454
406
|
result = chain._get_new_targetobj(target_obj,new_var,
|
|
455
407
|
export=export,
|
|
456
|
-
use_exported_obj=use_exported_obj
|
|
408
|
+
use_exported_obj=use_exported_obj,
|
|
409
|
+
result_getter_func=getter_func)
|
|
457
410
|
|
|
458
411
|
if export or (self._ProxiedObj__export_trivial_obj
|
|
459
412
|
and is_trivial_obj(result)):
|
|
413
|
+
# 返回导出的对象
|
|
460
414
|
if use_newvar:
|
|
461
415
|
chain.add_exported_obj(result, new_var) # 继续追踪导出的值
|
|
462
416
|
if target_obj is not EMPTY_OBJ:
|
|
@@ -467,7 +421,23 @@ def magic_meth_chained(fmt = None, use_newvar = True, indent_delta = 0,
|
|
|
467
421
|
if use_newvar:
|
|
468
422
|
return proxyCls(type(result),self._ProxiedObj__chain,new_var)(chain,new_var,
|
|
469
423
|
result,export_trivial_obj=self._ProxiedObj__export_trivial_obj)
|
|
470
|
-
|
|
424
|
+
if aug_assign:
|
|
425
|
+
if result is target_obj:return self
|
|
426
|
+
else:
|
|
427
|
+
result_var = chain.new_var() # 新变量的名称
|
|
428
|
+
chain.scope[result_var] = result
|
|
429
|
+
chain.remove_last_line() # 回退已生成的代码,重新加入
|
|
430
|
+
fmt_kw["_self"] = result_var
|
|
431
|
+
chain.add_code(f"{result_var} = {self_name}",result_var,[self_name])
|
|
432
|
+
new_code = fmt.format(*fmt_args, **fmt_kw)
|
|
433
|
+
# 需加入self_name,由于可能会修改self_name的对象
|
|
434
|
+
chain.add_code(new_code, None, [result_var, self_name],
|
|
435
|
+
_export_type = export, executed = not no_target_obj)
|
|
436
|
+
return proxyCls(type(result),self._ProxiedObj__chain,result_var)(
|
|
437
|
+
chain,result_var,result,
|
|
438
|
+
export_trivial_obj = \
|
|
439
|
+
self._ProxiedObj__export_trivial_obj)
|
|
440
|
+
return None
|
|
471
441
|
|
|
472
442
|
return override
|
|
473
443
|
return magic_meth_chained_inner
|
|
@@ -486,7 +456,7 @@ class ProxiedObj:
|
|
|
486
456
|
self.__name=name
|
|
487
457
|
self.__export_call=_export_call
|
|
488
458
|
if not _export_call and self.__chain.hook_method_call \
|
|
489
|
-
and
|
|
459
|
+
and _isinstance(target_obj,types.MethodType):
|
|
490
460
|
obj = target_obj.__self__
|
|
491
461
|
if id(obj) in self.__chain.proxies:
|
|
492
462
|
target_obj = types.MethodType(target_obj.__func__,
|
|
@@ -522,7 +492,7 @@ class ProxiedObj:
|
|
|
522
492
|
self.__chain.add_exported_obj(result, new_var)
|
|
523
493
|
return result # 直接返回结果,不继续返回ProxiedObj
|
|
524
494
|
|
|
525
|
-
if
|
|
495
|
+
if _isinstance(self.__target_obj,type) and _isinstance(result,self.__target_obj):
|
|
526
496
|
# 自身是类且result为自身的实例化对象,则实例使用类的导出函数、属性
|
|
527
497
|
if self.__name in self.__chain.export_attrs:
|
|
528
498
|
self.__chain.export_attrs[new_var] = self.__chain.\
|
|
@@ -535,26 +505,22 @@ class ProxiedObj:
|
|
|
535
505
|
|
|
536
506
|
#@magic_meth_chained("{_var} = {_self}.{}")
|
|
537
507
|
def __getattr__(self,attr):
|
|
538
|
-
if "_ProxiedObj__chain" not in object.\
|
|
539
|
-
__getattribute__(self,"__dict__"): # self尚未初始化
|
|
540
|
-
return object.__getattribute__(self,attr)
|
|
541
508
|
if attr in NOCODE_EXPORT_ATTRS and self.__target_obj is not EMPTY_OBJ:
|
|
542
|
-
return
|
|
509
|
+
return _getattr(self.__target_obj, attr) # 不留下代码的直接导出属性
|
|
543
510
|
|
|
544
511
|
new_var=self.__chain.new_var()
|
|
545
512
|
new_code = f"{new_var} = {self.__name}.{attr}"
|
|
546
513
|
self.__chain.add_code(new_code, new_var, [self.__name],
|
|
547
514
|
executed = self.__target_obj is not EMPTY_OBJ)
|
|
548
515
|
|
|
549
|
-
|
|
516
|
+
is_export = self.__chain.is_export_attr(attr, self.__name)
|
|
550
517
|
result = self.__chain._get_new_targetobj(
|
|
551
|
-
self.__target_obj,new_var,lambda:
|
|
552
|
-
export =
|
|
553
|
-
if
|
|
518
|
+
self.__target_obj,new_var,lambda:_getattr(self.__target_obj,attr),
|
|
519
|
+
export = is_export) # 获取结果对象
|
|
520
|
+
if is_export:
|
|
554
521
|
return result
|
|
555
522
|
|
|
556
|
-
if self.__export_trivial_obj and is_trivial_obj(result)
|
|
557
|
-
or self.__chain.is_export_attr(attr,self.__name):
|
|
523
|
+
if self.__export_trivial_obj and is_trivial_obj(result) or is_export:
|
|
558
524
|
self.__chain.add_exported_obj(result, new_var)
|
|
559
525
|
return result # 直接返回结果,不继续返回ProxiedObj
|
|
560
526
|
else:
|
|
@@ -564,25 +530,27 @@ class ProxiedObj:
|
|
|
564
530
|
self.__chain,new_var,result,
|
|
565
531
|
self.__chain.is_export_func(attr,self.__name),
|
|
566
532
|
self.__export_trivial_obj)
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
533
|
+
|
|
534
|
+
#@magic_meth_chained("{_var} = str({_self})",export=True)
|
|
535
|
+
#def __str__(self): return str(self)
|
|
536
|
+
# 优化函数调用开销
|
|
537
|
+
__str__ = magic_meth_chained("{_var} = str({_self})",export=True)(str)
|
|
538
|
+
__repr__ = magic_meth_chained("{_var} = repr({_self})",export=True)(repr)
|
|
539
|
+
__dir__ = magic_meth_chained("{_var} = dir({_self})",export=True)(dir)
|
|
540
|
+
__setattr_override = magic_meth_chained("{_self}.{} = {!r}", False)(setattr)
|
|
541
|
+
|
|
542
|
+
def __setattr__(self,attr,value): # 仅用于__no_self_attr
|
|
576
543
|
dct = object.__getattribute__(self,"__dict__")
|
|
577
544
|
if not dct.get("_ProxiedObj__no_self_attr",False):
|
|
578
545
|
object.__setattr__(self,attr,value)
|
|
579
546
|
else:
|
|
580
547
|
self.__setattr_override(attr,value)
|
|
581
|
-
def __getattribute__(self,attr):
|
|
548
|
+
def __getattribute__(self,attr): # 仅用于__no_self_attr
|
|
582
549
|
result = object.__getattribute__(self,attr)
|
|
583
550
|
if object.__getattribute__(self,"__dict__").get(
|
|
584
551
|
"_ProxiedObj__no_self_attr",False) \
|
|
585
552
|
and not attr.startswith("_ProxiedObj"):
|
|
553
|
+
#return type(self).__getattr__(self,attr)
|
|
586
554
|
raise AttributeError # 改用__getattr__
|
|
587
555
|
return result
|
|
588
556
|
def __new__(cls,*args,**kw):
|
|
@@ -598,160 +566,182 @@ class ProxiedObj:
|
|
|
598
566
|
|
|
599
567
|
# 算术运算符
|
|
600
568
|
@magic_meth_chained("{_var} = {_self} + {!r}")
|
|
601
|
-
def __add__(self, other):
|
|
569
|
+
def __add__(self, other): return self + other
|
|
602
570
|
@magic_meth_chained("{_var} = {_self} - {!r}")
|
|
603
|
-
def __sub__(self, other):
|
|
571
|
+
def __sub__(self, other): return self - other
|
|
604
572
|
@magic_meth_chained("{_var} = {_self} * {!r}")
|
|
605
|
-
def __mul__(self, other):
|
|
573
|
+
def __mul__(self, other): return self * other
|
|
606
574
|
@magic_meth_chained("{_var} = {_self} / {!r}")
|
|
607
|
-
def __truediv__(self, other):
|
|
575
|
+
def __truediv__(self, other): return self / other
|
|
608
576
|
@magic_meth_chained("{_var} = {_self} // {!r}")
|
|
609
|
-
def __floordiv__(self, other):
|
|
577
|
+
def __floordiv__(self, other): return self // other
|
|
610
578
|
@magic_meth_chained("{_var} = {_self} % {!r}")
|
|
611
|
-
def __mod__(self, other):
|
|
579
|
+
def __mod__(self, other): return self % other
|
|
612
580
|
@magic_meth_chained("{_var} = {_self} ** {!r}")
|
|
613
|
-
def __pow__(self, other):
|
|
581
|
+
def __pow__(self, other): return self ** other
|
|
614
582
|
@magic_meth_chained("{_var} = {_self} << {!r}")
|
|
615
|
-
def __lshift__(self, other):
|
|
583
|
+
def __lshift__(self, other): return self << other
|
|
616
584
|
@magic_meth_chained("{_var} = {_self} >> {!r}")
|
|
617
|
-
def __rshift__(self, other):
|
|
585
|
+
def __rshift__(self, other): return self >> other
|
|
618
586
|
@magic_meth_chained("{_var} = {_self} & {!r}")
|
|
619
|
-
def __and__(self, other):
|
|
587
|
+
def __and__(self, other): return self & other
|
|
620
588
|
@magic_meth_chained("{_var} = {_self} ^ {!r}")
|
|
621
|
-
def __xor__(self, other):
|
|
589
|
+
def __xor__(self, other): return self ^ other
|
|
622
590
|
@magic_meth_chained("{_var} = {_self} | {!r}")
|
|
623
|
-
def __or__(self, other):
|
|
591
|
+
def __or__(self, other): return self | other
|
|
624
592
|
|
|
625
593
|
# 反向算术运算符
|
|
594
|
+
@magic_meth_chained("{_var} = {!r} + {_self}")
|
|
595
|
+
def __radd__(self, other): return other + self
|
|
626
596
|
@magic_meth_chained("{_var} = {!r} - {_self}")
|
|
627
|
-
def
|
|
628
|
-
@magic_meth_chained("{_var} = {!r} - {_self}")
|
|
629
|
-
def __rsub__(self, other): pass
|
|
597
|
+
def __rsub__(self, other): return other - self
|
|
630
598
|
@magic_meth_chained("{_var} = {!r} * {_self}")
|
|
631
|
-
def __rmul__(self, other):
|
|
599
|
+
def __rmul__(self, other): return other * self
|
|
632
600
|
@magic_meth_chained("{_var} = {!r} / {_self}")
|
|
633
|
-
def __rtruediv__(self, other):
|
|
601
|
+
def __rtruediv__(self, other): return other / self
|
|
634
602
|
@magic_meth_chained("{_var} = {!r} // {_self}")
|
|
635
|
-
def __rfloordiv__(self, other):
|
|
603
|
+
def __rfloordiv__(self, other): return other // self
|
|
636
604
|
@magic_meth_chained("{_var} = {!r} % {_self}")
|
|
637
|
-
def __rmod__(self, other):
|
|
605
|
+
def __rmod__(self, other): return other % self
|
|
638
606
|
@magic_meth_chained("{_var} = {!r} ** {_self}")
|
|
639
|
-
def __rpow__(self, other):
|
|
607
|
+
def __rpow__(self, other): return other ** self
|
|
640
608
|
@magic_meth_chained("{_var} = {!r} << {_self}")
|
|
641
|
-
def __rlshift__(self, other):
|
|
609
|
+
def __rlshift__(self, other): return other << self
|
|
642
610
|
@magic_meth_chained("{_var} = {!r} >> {_self}")
|
|
643
|
-
def __rrshift__(self, other):
|
|
611
|
+
def __rrshift__(self, other): return other >> self
|
|
644
612
|
@magic_meth_chained("{_var} = {!r} & {_self}")
|
|
645
|
-
def __rand__(self, other):
|
|
613
|
+
def __rand__(self, other): return other & self
|
|
646
614
|
@magic_meth_chained("{_var} = {!r} ^ {_self}")
|
|
647
|
-
def __rxor__(self, other):
|
|
615
|
+
def __rxor__(self, other): return other ^ self
|
|
648
616
|
@magic_meth_chained("{_var} = {!r} | {_self}")
|
|
649
|
-
def __ror__(self, other):
|
|
617
|
+
def __ror__(self, other): return other | self
|
|
650
618
|
|
|
651
619
|
# 增量赋值
|
|
652
|
-
@magic_meth_chained("{_self} += {!r}",
|
|
653
|
-
def __iadd__(self, other):
|
|
654
|
-
@magic_meth_chained("{_self} -= {!r}",
|
|
655
|
-
def __isub__(self, other):
|
|
656
|
-
@magic_meth_chained("{_self} *= {!r}",
|
|
657
|
-
def __imul__(self, other):
|
|
658
|
-
@magic_meth_chained("{_self} /= {!r}",
|
|
659
|
-
def __itruediv__(self, other):
|
|
660
|
-
@magic_meth_chained("{_self} //= {!r}",
|
|
661
|
-
def __ifloordiv__(self, other):
|
|
662
|
-
@magic_meth_chained("{_self} %= {!r}",
|
|
663
|
-
def __imod__(self, other):
|
|
664
|
-
@magic_meth_chained("{_self} **= {!r}",
|
|
665
|
-
def __ipow__(self, other):
|
|
666
|
-
@magic_meth_chained("{_self} <<= {!r}",
|
|
667
|
-
def __ilshift__(self, other):
|
|
668
|
-
@magic_meth_chained("{_self} >>= {!r}",
|
|
669
|
-
def __irshift__(self, other):
|
|
670
|
-
@magic_meth_chained("{_self} &= {!r}",
|
|
671
|
-
def __iand__(self, other):
|
|
672
|
-
@magic_meth_chained("{_self} |= {!r}",
|
|
673
|
-
def __ior__(self, other):
|
|
674
|
-
@magic_meth_chained("{_self} ^= {!r}",
|
|
675
|
-
def __ixor__(self, other):
|
|
620
|
+
@magic_meth_chained("{_self} += {!r}", aug_assign=True)
|
|
621
|
+
def __iadd__(self, other): self += other; return self
|
|
622
|
+
@magic_meth_chained("{_self} -= {!r}", aug_assign=True)
|
|
623
|
+
def __isub__(self, other): self -= other; return self
|
|
624
|
+
@magic_meth_chained("{_self} *= {!r}", aug_assign=True)
|
|
625
|
+
def __imul__(self, other): self *= other; return self
|
|
626
|
+
@magic_meth_chained("{_self} /= {!r}", aug_assign=True)
|
|
627
|
+
def __itruediv__(self, other): self /= other; return self
|
|
628
|
+
@magic_meth_chained("{_self} //= {!r}", aug_assign=True)
|
|
629
|
+
def __ifloordiv__(self, other): self //= other; return self
|
|
630
|
+
@magic_meth_chained("{_self} %= {!r}", aug_assign=True)
|
|
631
|
+
def __imod__(self, other): self %= other; return self
|
|
632
|
+
@magic_meth_chained("{_self} **= {!r}", aug_assign=True)
|
|
633
|
+
def __ipow__(self, other): self **= other; return self
|
|
634
|
+
@magic_meth_chained("{_self} <<= {!r}", aug_assign=True)
|
|
635
|
+
def __ilshift__(self, other): self <<= other; return self
|
|
636
|
+
@magic_meth_chained("{_self} >>= {!r}", aug_assign=True)
|
|
637
|
+
def __irshift__(self, other): self >>= other; return self
|
|
638
|
+
@magic_meth_chained("{_self} &= {!r}", aug_assign=True)
|
|
639
|
+
def __iand__(self, other): self &= other; return self
|
|
640
|
+
@magic_meth_chained("{_self} |= {!r}", aug_assign=True)
|
|
641
|
+
def __ior__(self, other): self |= other; return self
|
|
642
|
+
@magic_meth_chained("{_self} ^= {!r}", aug_assign=True)
|
|
643
|
+
def __ixor__(self, other): self ^= other; return self
|
|
676
644
|
|
|
677
645
|
# 比较运算符
|
|
678
646
|
@magic_meth_chained("{_var} = {_self} < {!r}",export=True)
|
|
679
|
-
def __lt__(self, other):
|
|
647
|
+
def __lt__(self, other): return self < other
|
|
680
648
|
@magic_meth_chained("{_var} = {_self} <= {!r}",export=True)
|
|
681
|
-
def __le__(self, other):
|
|
649
|
+
def __le__(self, other): return self <= other
|
|
682
650
|
@magic_meth_chained("{_var} = {_self} == {!r}",export=True)
|
|
683
|
-
def __eq__(self, other):
|
|
651
|
+
def __eq__(self, other): return self == other
|
|
684
652
|
@magic_meth_chained("{_var} = {_self} != {!r}",export=True)
|
|
685
|
-
def __ne__(self, other):
|
|
653
|
+
def __ne__(self, other): return self != other
|
|
686
654
|
@magic_meth_chained("{_var} = {_self} > {!r}",export=True)
|
|
687
|
-
def __gt__(self, other):
|
|
655
|
+
def __gt__(self, other): return self > other
|
|
688
656
|
@magic_meth_chained("{_var} = {_self} >= {!r}",export=True)
|
|
689
|
-
def __ge__(self, other):
|
|
657
|
+
def __ge__(self, other): return self >= other
|
|
690
658
|
|
|
691
659
|
# 一元运算符
|
|
692
660
|
@magic_meth_chained("{_var} = -{_self}")
|
|
693
|
-
def __neg__(self):
|
|
661
|
+
def __neg__(self): return -self
|
|
694
662
|
@magic_meth_chained("{_var} = +{_self}")
|
|
695
|
-
def __pos__(self):
|
|
696
|
-
@magic_meth_chained("{_var} = abs({_self})")
|
|
697
|
-
def __abs__(self): pass
|
|
663
|
+
def __pos__(self): return +self
|
|
698
664
|
@magic_meth_chained("{_var} = ~{_self}")
|
|
699
|
-
def __invert__(self):
|
|
665
|
+
def __invert__(self): return ~self
|
|
666
|
+
__abs__ = magic_meth_chained("{_var} = abs({_self})")(abs)
|
|
700
667
|
|
|
701
668
|
# 容器/迭代器
|
|
702
|
-
|
|
703
|
-
def __len__(self): pass
|
|
669
|
+
__len__ = magic_meth_chained("{_var} = len({_self})",export=True)(len)
|
|
704
670
|
@magic_meth_chained("{_var} = {_self}[{!r}]")
|
|
705
|
-
def __getitem__(self, key):
|
|
671
|
+
def __getitem__(self, key): return self[key]
|
|
706
672
|
@magic_meth_chained("{_self}[{!r}] = {!r}", False)
|
|
707
|
-
def __setitem__(self, key, value):
|
|
673
|
+
def __setitem__(self, key, value): self[key] = value
|
|
708
674
|
@magic_meth_chained("del {_self}[{!r}]", False)
|
|
709
|
-
def __delitem__(self, key):
|
|
710
|
-
@magic_meth_chained("{_var} = reversed({_self})",export=True)
|
|
711
|
-
def __reversed__(self):pass
|
|
675
|
+
def __delitem__(self, key): del self[key]
|
|
712
676
|
@magic_meth_chained("{_var} = {!r} in {_self}",export=True)
|
|
713
|
-
def __contains__(self, item):
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
677
|
+
def __contains__(self, item): return item in self
|
|
678
|
+
__reversed__ = magic_meth_chained("{_var} = reversed({_self})",
|
|
679
|
+
export=True)(reversed)
|
|
680
|
+
__iter__ = magic_meth_chained("{_var} = iter({_self})",export=True)(iter)
|
|
681
|
+
__next__ = magic_meth_chained("{_var} = next({_self})",export=True)(next)
|
|
718
682
|
|
|
719
683
|
# 类型转换
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
@magic_meth_chained("{_var} = bool({_self})",export=True)
|
|
729
|
-
def __bool__(self): pass
|
|
730
|
-
@magic_meth_chained("{_var} = hash({_self})",export=True)
|
|
731
|
-
def __hash__(self): pass
|
|
684
|
+
__int__ = magic_meth_chained("{_var} = int({_self})",export=True)(int)
|
|
685
|
+
__float__ = magic_meth_chained("{_var} = float({_self})",export=True)(float)
|
|
686
|
+
__complex__ = magic_meth_chained("{_var} = complex({_self})",
|
|
687
|
+
export=True)(complex)
|
|
688
|
+
__round__ = magic_meth_chained("{_var} = round({_self}, {!r})",
|
|
689
|
+
export=True)(round)
|
|
690
|
+
__bool__ = magic_meth_chained("{_var} = bool({_self})",export=True)(bool)
|
|
691
|
+
__hash__ = magic_meth_chained("{_var} = hash({_self})",export=True)(hash)
|
|
732
692
|
|
|
733
693
|
# 上下文管理
|
|
734
|
-
#@magic_meth_chained("with {_self}:",False,1)
|
|
735
694
|
@magic_meth_chained(default_fmt=True)
|
|
736
|
-
def __enter__(self):
|
|
737
|
-
#@magic_meth_chained("",False,-1)
|
|
695
|
+
def __enter__(self): return self.__enter__()
|
|
738
696
|
@magic_meth_chained(default_fmt=True,export=True)
|
|
739
|
-
def __exit__(self, exc_type, exc_value, traceback):
|
|
697
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
|
698
|
+
return self.__exit__(exc_type, exc_value, traceback)
|
|
740
699
|
|
|
741
700
|
# 其他
|
|
742
|
-
@magic_meth_chained(default_fmt=True,export=True)
|
|
701
|
+
@magic_meth_chained(default_fmt=True,export=True,no_exec=False)
|
|
743
702
|
def __await__(self):pass
|
|
744
|
-
@magic_meth_chained(default_fmt=True,export=True)
|
|
703
|
+
@magic_meth_chained(default_fmt=True,export=True,no_exec=False)
|
|
745
704
|
def __aiter__(self):pass
|
|
746
705
|
@magic_meth_chained(default_fmt=True,export=True)
|
|
747
|
-
def __fspath__(self):
|
|
706
|
+
def __fspath__(self):return self.__fspath__()
|
|
707
|
+
|
|
708
|
+
def proxyCls(T=_EmptyTarget, chain=EMPTY_OBJ, fromvar=None):
|
|
709
|
+
# 泛型,proxyCls(T)生成类型信息为T的继承自ProxiedObj的类
|
|
710
|
+
if T is EMPTY_OBJ:
|
|
711
|
+
return ProxiedObj
|
|
712
|
+
|
|
713
|
+
class ProxyCls(ProxiedObj): # 创建同时从ProxiedObj与T继承的类
|
|
714
|
+
# pylint: disable=unused-private-member
|
|
715
|
+
__proto = T # 自身使用的原型
|
|
716
|
+
def __new__(cls,*args,**kw):
|
|
717
|
+
_chain = args[0] if args else kw.get("chain")
|
|
718
|
+
if not _isinstance(_chain,ObjChain) and chain is not EMPTY_OBJ:
|
|
719
|
+
var = chain.new_var(T.__name__)
|
|
720
|
+
if fromvar is not None:
|
|
721
|
+
cls_ = chain.add_existing_obj(T,var,f"{var} = {fromvar}.__class__",
|
|
722
|
+
[fromvar])
|
|
723
|
+
else:
|
|
724
|
+
cls_ = chain.add_existing_obj(T,var,
|
|
725
|
+
f"# class {var}: {shortrepr(cls,repr_func=basic_repr)}")
|
|
726
|
+
if len(args) == 3 and _isinstance(T,type):
|
|
727
|
+
args=(args[0],tuple(unproxy_obj(cls) for cls in args[1]),args[2])
|
|
728
|
+
|
|
729
|
+
if kw:return cls_(*args,**kw)
|
|
730
|
+
return cls_(*args) # 返回ProxyCls
|
|
731
|
+
else:
|
|
732
|
+
return ProxiedObj.__new__(cls,*args,**kw)
|
|
733
|
+
|
|
734
|
+
return ProxyCls
|
|
735
|
+
|
|
748
736
|
|
|
749
737
|
_isinstance = isinstance
|
|
738
|
+
_getattr = getattr
|
|
750
739
|
from pyobject.objproxy.builtin_hook import hook_builtins # pylint: disable=ungrouped-imports
|
|
751
740
|
hook_builtins() # hook内置函数
|
|
752
741
|
|
|
753
742
|
def proxy_demo():
|
|
754
|
-
chain = ObjChain(export_attrs=["__array_struct__"]
|
|
743
|
+
chain = ObjChain(export_attrs=["__array_struct__"],
|
|
744
|
+
export_trivial_obj=True)
|
|
755
745
|
try:
|
|
756
746
|
np = chain.new_object("import numpy as np","np")
|
|
757
747
|
plt = chain.new_object("import matplotlib.pyplot as plt","plt",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# 内置函数和部分标准库函数的hook
|
|
2
2
|
import sys,builtins,_collections_abc,inspect
|
|
3
3
|
import collections.abc as collections_abc
|
|
4
|
-
from pyobject.objproxy import ProxiedObj
|
|
4
|
+
from pyobject.objproxy import ProxiedObj
|
|
5
5
|
|
|
6
6
|
_range = type(range(0)) #range
|
|
7
7
|
def range(*args):
|
|
@@ -65,11 +65,9 @@ def callable(obj):
|
|
|
65
65
|
if _isinstance(obj, ProxiedObj):
|
|
66
66
|
obj = obj._ProxiedObj__target_obj
|
|
67
67
|
return _callable(obj)
|
|
68
|
-
def getattr(*args
|
|
68
|
+
def getattr(*args):
|
|
69
69
|
if _isinstance(args[1],ProxiedObj):
|
|
70
70
|
args = (args[0], args[1]._ProxiedObj__target_obj, *args[2:])
|
|
71
|
-
if "name" in kw and _isinstance(kw["name"],ProxiedObj):
|
|
72
|
-
kw["name"] = kw["name"]._ProxiedObj__target_obj
|
|
73
71
|
return _getattr(*args)
|
|
74
72
|
|
|
75
73
|
_pre_check_methods = _collections_abc._check_methods
|
|
@@ -138,19 +136,3 @@ def hook_builtins():
|
|
|
138
136
|
collections_abc._check_methods = _check_methods
|
|
139
137
|
inspect.signature = signature
|
|
140
138
|
inspect.getattr_static = getattr_static
|
|
141
|
-
|
|
142
|
-
# 内置类型的修改(备用)
|
|
143
|
-
class CustomStr(builtins.str):
|
|
144
|
-
__init__ = accept_raw_obj(builtins.str,lambda args:args[1:],
|
|
145
|
-
process_ret=lambda ret:None)
|
|
146
|
-
__new__ = accept_raw_obj(builtins.str,lambda args:args[1:])
|
|
147
|
-
|
|
148
|
-
class CustomInt(builtins.int):
|
|
149
|
-
__init__ = accept_raw_obj(builtins.int,lambda args:args[1:],
|
|
150
|
-
process_ret=lambda ret:None)
|
|
151
|
-
__new__ = accept_raw_obj(builtins.int,lambda args:args[1:])
|
|
152
|
-
|
|
153
|
-
class CustomBytes(builtins.bytes):
|
|
154
|
-
__init__ = accept_raw_obj(builtins.bytes,lambda args:args[1:],
|
|
155
|
-
process_ret=lambda ret:None)
|
|
156
|
-
__new__ = accept_raw_obj(builtins.bytes,lambda args:args[1:])
|
|
@@ -8,7 +8,7 @@ except ImportError:
|
|
|
8
8
|
sys.path.append(path) # 加入当前pyobject库所在的目录
|
|
9
9
|
from pyobject import ObjChain, ProxiedObj
|
|
10
10
|
|
|
11
|
-
def current_func_name(level = 0):
|
|
11
|
+
def current_func_name(level = 0): # 获取当前函数名,便于调试输出
|
|
12
12
|
frame = sys._getframe()
|
|
13
13
|
for i in range(level + 1):
|
|
14
14
|
if frame is None:return None
|
|
@@ -87,6 +87,26 @@ class TestObjChain(unittest.TestCase):
|
|
|
87
87
|
class Inherited(cls):pass
|
|
88
88
|
Inherited().meth()
|
|
89
89
|
self.print_code(chain, print_optimized = True)
|
|
90
|
+
def test_aug_assign(self):
|
|
91
|
+
class Cls:
|
|
92
|
+
def __iadd__(self, inc):return inc
|
|
93
|
+
def __isub__(self, dec):return self
|
|
94
|
+
|
|
95
|
+
chain = ObjChain()
|
|
96
|
+
obj = chain.add_existing_obj(Cls(),"obj")
|
|
97
|
+
var1=obj; var1+=1
|
|
98
|
+
self.assertEqual(var1, 1)
|
|
99
|
+
self.print_code(chain, print_optimized = True)
|
|
100
|
+
def test_setattr(self):
|
|
101
|
+
class Cls:
|
|
102
|
+
def __init__(self):
|
|
103
|
+
self.attr = 42
|
|
104
|
+
|
|
105
|
+
chain = ObjChain()
|
|
106
|
+
obj = chain.add_existing_obj(Cls(),"obj")
|
|
107
|
+
obj.attr = 1
|
|
108
|
+
self.assertEqual(obj.attr, 1)
|
|
109
|
+
self.print_code(chain)
|
|
90
110
|
def test_export(self): # 测试export_funcs和export_attrs
|
|
91
111
|
class Cls:
|
|
92
112
|
def __init__(self):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyobject
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
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
|
|
@@ -394,11 +394,12 @@ Python内部的字节码对象\ ``CodeType``\ ,如\ ``func.__code__``\ ,是
|
|
|
394
394
|
lst调用多次==运算符(``__eq__``)相比,
|
|
395
395
|
本函数直接比较对象的指针,提高了效率。
|
|
396
396
|
|
|
397
|
-
**``pyobject``\ 当前版本**: 1.
|
|
397
|
+
**``pyobject``\ 当前版本**: 1.3.0
|
|
398
398
|
|
|
399
399
|
更新日志:
|
|
400
400
|
---------
|
|
401
401
|
|
|
402
|
+
| 2025-6-6(v1.3.0):性能优化,提升了pyobject.objproxy模块的性能。
|
|
402
403
|
| 2025-4-30(v1.2.9):改进和增强了子模块pyobject.objproxy,重命名子模块pyobject.code_为pyobject.code。
|
|
403
404
|
| 2025-3-31(v1.2.8):将pyobject.super_proxy重命名为pyobject.objproxy,并正式发布;修改了pyobject.pyobj_extension模块。
|
|
404
405
|
| 2025-3-6(v1.2.7):为pyobject.browser新增了\ ``dir()``\ 中不存在的类属性(如\ ``__flags__``,
|
|
@@ -886,11 +887,13 @@ Python call “obj in lst” that invokes the “==” operator (``__eq__``)
|
|
|
886
887
|
multiple times, this function directly compares the pointers to improve
|
|
887
888
|
efficiency.
|
|
888
889
|
|
|
889
|
-
**Current Version of ``pyobject``**: 1.
|
|
890
|
+
**Current Version of ``pyobject``**: 1.3.0
|
|
890
891
|
|
|
891
892
|
Change Log
|
|
892
893
|
----------
|
|
893
894
|
|
|
895
|
+
| 2025-6-6(v1.3.0): Optimized the performance of the pyobject.objproxy
|
|
896
|
+
module.
|
|
894
897
|
| 2025-4-30(v1.2.9): Improved and enhanced the sub-module
|
|
895
898
|
``pyobject.objproxy``, and renamed the sub-module ``pyobject.code_``
|
|
896
899
|
to ``pyobject.code``.
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
# 实现简单的不可变的链式求值对象(备用,也是后续ProxiedObj的原型)
|
|
2
|
-
import functools
|
|
3
|
-
try:from timer_tool import timer # pip install timer-tool
|
|
4
|
-
except ImportError:timer=lambda func:func
|
|
5
|
-
from pyobject.objproxy.utils import format_func_call
|
|
6
|
-
|
|
7
|
-
ENABLE_CACHE = False
|
|
8
|
-
|
|
9
|
-
def using_namespace(obj,scope,except_=[],internal=False):
|
|
10
|
-
for name in dir(obj):
|
|
11
|
-
if not internal and name.startswith("_"):continue
|
|
12
|
-
if name in except_:continue
|
|
13
|
-
scope[name]=getattr(obj,name)
|
|
14
|
-
|
|
15
|
-
def unuse_namespace(obj,scope,except_=[],internal=False):
|
|
16
|
-
# 参数应和之前调用using_namespace的一致
|
|
17
|
-
for name in dir(obj):
|
|
18
|
-
if not internal and name.startswith("_"):continue
|
|
19
|
-
if name in except_:continue
|
|
20
|
-
del scope[name]
|
|
21
|
-
|
|
22
|
-
def define_enum(names,local,start=0):
|
|
23
|
-
# names: 字符串列表,或者以","和\n分割的字符串
|
|
24
|
-
if isinstance(names,str):
|
|
25
|
-
ignored=str.maketrans("","","\n ")
|
|
26
|
-
names=names.translate(ignored).split(",")
|
|
27
|
-
for i,name in enumerate(names,start):
|
|
28
|
-
local[name]=i
|
|
29
|
-
|
|
30
|
-
class Symbol:
|
|
31
|
-
define_enum(
|
|
32
|
-
"""ADD, SUB, MUL, DIV, MOD, POW, FLOOR_DIV,
|
|
33
|
-
AND, OR, XOR, NOT,
|
|
34
|
-
LT, LE, EQ, NE, GT, GE,
|
|
35
|
-
LSHIFT, RSHIFT,
|
|
36
|
-
BIT_AND, BIT_OR, BIT_XOR, BIT_NOT,
|
|
37
|
-
ASSIGN,NEG,POS,
|
|
38
|
-
PLUS_ASSIGN, MINUS_ASSIGN, MUL_ASSIGN, DIV_ASSIGN, MOD_ASSIGN, POW_ASSIGN, FLOOR_DIV_ASSIGN,
|
|
39
|
-
LSHIFT_ASSIGN, RSHIFT_ASSIGN, AND_ASSIGN, OR_ASSIGN, XOR_ASSIGN, HIGHEST""",
|
|
40
|
-
locals()
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
priority = [
|
|
44
|
-
# 优先级最低:赋值运算符
|
|
45
|
-
(ASSIGN, PLUS_ASSIGN, MINUS_ASSIGN, MUL_ASSIGN, DIV_ASSIGN, MOD_ASSIGN, POW_ASSIGN,
|
|
46
|
-
FLOOR_DIV_ASSIGN, LSHIFT_ASSIGN, RSHIFT_ASSIGN, AND_ASSIGN, OR_ASSIGN, XOR_ASSIGN),
|
|
47
|
-
# 逻辑运算符
|
|
48
|
-
(OR, AND),
|
|
49
|
-
# 比较运算符
|
|
50
|
-
(LT, LE, EQ, NE, GT, GE),
|
|
51
|
-
# 位运算符
|
|
52
|
-
(BIT_OR,),
|
|
53
|
-
(BIT_XOR,),
|
|
54
|
-
(BIT_AND,),
|
|
55
|
-
# 位移运算符
|
|
56
|
-
(LSHIFT, RSHIFT),
|
|
57
|
-
# 算术运算符
|
|
58
|
-
(ADD, SUB),
|
|
59
|
-
(MUL, DIV, MOD, FLOOR_DIV),
|
|
60
|
-
# 幂运算符
|
|
61
|
-
(POW,),
|
|
62
|
-
# 一元运算符
|
|
63
|
-
(NOT, BIT_NOT, NEG, POS),
|
|
64
|
-
# 最高优先级的占位符
|
|
65
|
-
(HIGHEST,),
|
|
66
|
-
]
|
|
67
|
-
|
|
68
|
-
PRIORITY={}
|
|
69
|
-
for level in range(len(Symbol.priority)):
|
|
70
|
-
for symbol in Symbol.priority[level]:
|
|
71
|
-
PRIORITY[symbol]=level
|
|
72
|
-
|
|
73
|
-
using_namespace(Symbol,globals(),["priority"])
|
|
74
|
-
|
|
75
|
-
def ck(obj,symbol):
|
|
76
|
-
# 如对于x + (y * z),outer_priority为"+",inner_priority为"*"
|
|
77
|
-
outer_priority=PRIORITY[symbol]
|
|
78
|
-
inner_priority=PRIORITY[getattr(obj,"_DynObj__last_symbol",HIGHEST)]
|
|
79
|
-
fmt="({!r})" if outer_priority > inner_priority else "{!r}"
|
|
80
|
-
return fmt.format(obj)
|
|
81
|
-
|
|
82
|
-
def magic_meth(meth): # 用于无法获知具体表达式的魔法方法调用(备用函数)
|
|
83
|
-
@functools.wraps(meth)
|
|
84
|
-
def override(self,*args,**kw):
|
|
85
|
-
return DynObj(f"{ck(self, HIGHEST)}.{meth.__name__}") # 优先级使用默认的HIGHEST
|
|
86
|
-
return override
|
|
87
|
-
|
|
88
|
-
# 能包装表达式链式求值的对象(不可变)
|
|
89
|
-
class DynObj:
|
|
90
|
-
_cache = {}
|
|
91
|
-
if ENABLE_CACHE:
|
|
92
|
-
def __new__(cls, code, symbol=HIGHEST):
|
|
93
|
-
if code in cls._cache:
|
|
94
|
-
return cls._cache[code]
|
|
95
|
-
instance = super().__new__(cls)
|
|
96
|
-
cls._cache[code] = instance
|
|
97
|
-
return instance
|
|
98
|
-
|
|
99
|
-
def __init__(self,code,symbol=HIGHEST):
|
|
100
|
-
self.__code=code # __code仅在__str__和__repr__使用
|
|
101
|
-
self.__last_symbol=symbol # pylint: disable=unused-private-member
|
|
102
|
-
def __call__(self,*args,**kw):
|
|
103
|
-
new_code="{}({})".format(self, format_func_call(args,kw))
|
|
104
|
-
return DynObj(new_code)
|
|
105
|
-
def __getattr__(self,name):
|
|
106
|
-
new_code="{}.{}".format(self,name)
|
|
107
|
-
return DynObj(new_code)
|
|
108
|
-
def __str__(self):
|
|
109
|
-
return self.__code
|
|
110
|
-
def __repr__(self):
|
|
111
|
-
return self.__code
|
|
112
|
-
|
|
113
|
-
# 算术运算符
|
|
114
|
-
def __add__(self, other): return DynObj(f"{ck(self, ADD)} + {ck(other,ADD)}",ADD)
|
|
115
|
-
def __sub__(self, other): return DynObj(f"{ck(self, SUB)} - {ck(other,SUB)}",SUB)
|
|
116
|
-
def __mul__(self, other): return DynObj(f"{ck(self, MUL)} * {ck(other,MUL)}",MUL)
|
|
117
|
-
def __truediv__(self, other):
|
|
118
|
-
return DynObj(f"{ck(self, DIV)} / {ck(other, DIV)}", DIV)
|
|
119
|
-
def __floordiv__(self, other):
|
|
120
|
-
return DynObj(f"{ck(self, FLOOR_DIV)} // {ck(other, FLOOR_DIV)}", FLOOR_DIV)
|
|
121
|
-
def __mod__(self, other): return DynObj(f"{ck(self, MOD)} % {ck(other, MOD)}", MOD)
|
|
122
|
-
def __pow__(self, other): return DynObj(f"{ck(self, POW)} ** {ck(other, POW)}", POW)
|
|
123
|
-
def __lshift__(self, other):
|
|
124
|
-
return DynObj(f"{ck(self, LSHIFT)} << {ck(other, LSHIFT)}", LSHIFT)
|
|
125
|
-
def __rshift__(self, other):
|
|
126
|
-
return DynObj(f"{ck(self, RSHIFT)} >> {ck(other, RSHIFT)}", RSHIFT)
|
|
127
|
-
def __and__(self, other): return DynObj(f"{ck(self, BIT_AND)} & {ck(other, BIT_AND)}", BIT_AND)
|
|
128
|
-
def __xor__(self, other): return DynObj(f"{ck(self, BIT_XOR)} ^ {ck(other, BIT_XOR)}", BIT_XOR)
|
|
129
|
-
def __or__(self, other): return DynObj(f"{ck(self, BIT_OR)} | {ck(other, BIT_OR)}", BIT_OR)
|
|
130
|
-
|
|
131
|
-
# 反向算术运算符
|
|
132
|
-
def __radd__(self, other): return DynObj(f"{ck(other, ADD)} + {ck(self, ADD)}", ADD)
|
|
133
|
-
def __rsub__(self, other): return DynObj(f"{ck(other, SUB)} - {ck(self, SUB)}", SUB)
|
|
134
|
-
def __rmul__(self, other): return DynObj(f"{ck(other, MUL)} * {ck(self, MUL)}", MUL)
|
|
135
|
-
def __rtruediv__(self, other):
|
|
136
|
-
return DynObj(f"{ck(other, DIV)} / {ck(self, DIV)}", DIV)
|
|
137
|
-
def __rfloordiv__(self, other):
|
|
138
|
-
return DynObj(f"{ck(other, FLOOR_DIV)} // {ck(self, FLOOR_DIV)}", FLOOR_DIV)
|
|
139
|
-
def __rmod__(self, other): return DynObj(f"{ck(other, MOD)} % {ck(self, MOD)}", MOD)
|
|
140
|
-
def __rpow__(self, other): return DynObj(f"{ck(other, POW)} ** {ck(self, POW)}", POW)
|
|
141
|
-
def __rlshift__(self, other):
|
|
142
|
-
return DynObj(f"{ck(other, LSHIFT)} << {ck(self, LSHIFT)}", LSHIFT)
|
|
143
|
-
def __rrshift__(self, other):
|
|
144
|
-
return DynObj(f"{ck(other, RSHIFT)} >> {ck(self, RSHIFT)}", RSHIFT)
|
|
145
|
-
def __rand__(self, other): return DynObj(f"{ck(other, BIT_AND)} & {ck(self, BIT_AND)}", BIT_AND)
|
|
146
|
-
def __rxor__(self, other): return DynObj(f"{ck(other, BIT_XOR)} ^ {ck(self, BIT_XOR)}", BIT_XOR)
|
|
147
|
-
def __ror__(self, other): return DynObj(f"{ck(other, BIT_OR)} | {ck(self, BIT_OR)}", BIT_OR)
|
|
148
|
-
|
|
149
|
-
# 比较运算符
|
|
150
|
-
def __lt__(self, other): return DynObj(f"{ck(self, LT)} < {ck(other, LT)}", LT)
|
|
151
|
-
def __le__(self, other): return DynObj(f"{ck(self, LE)} <= {ck(other, LE)}", LE)
|
|
152
|
-
def __eq__(self, other): return DynObj(f"{ck(self, EQ)} == {ck(other, EQ)}", EQ)
|
|
153
|
-
def __ne__(self, other): return DynObj(f"{ck(self, NE)} != {ck(other, NE)}", NE)
|
|
154
|
-
def __gt__(self, other): return DynObj(f"{ck(self, GT)} > {ck(other, GT)}", GT)
|
|
155
|
-
def __ge__(self, other): return DynObj(f"{ck(self, GE)} >= {ck(other, GE)}", GE)
|
|
156
|
-
|
|
157
|
-
# 一元运算符
|
|
158
|
-
def __neg__(self): return DynObj(f"-{ck(self, NEG)}", NEG)
|
|
159
|
-
def __pos__(self): return DynObj(f"+{ck(self, POS)}", POS)
|
|
160
|
-
def __abs__(self): return DynObj(f"abs({self})")
|
|
161
|
-
def __invert__(self): return DynObj(f"~{ck(self, BIT_NOT)}", BIT_NOT)
|
|
162
|
-
|
|
163
|
-
# 容器协议
|
|
164
|
-
#def __len__(self): return DynObj(f"len({self})")
|
|
165
|
-
def __getitem__(self, key): return DynObj(f"{self}[{key!r}]")
|
|
166
|
-
#def __setitem__(self, key, value): return DynObj(f"{self}[{key!r}] = {value!r}")
|
|
167
|
-
#def __delitem__(self, key): return DynObj(f"del {self}[{key!r}]")
|
|
168
|
-
#def __contains__(self, item):pass
|
|
169
|
-
|
|
170
|
-
# 类型转换 (待实现)
|
|
171
|
-
#def __int__(self):pass
|
|
172
|
-
#def __float__(self):pass
|
|
173
|
-
#def __complex__(self):pass
|
|
174
|
-
#def __round__(self, ndigits=None):pass
|
|
175
|
-
|
|
176
|
-
def test():
|
|
177
|
-
_1=DynObj("1");_2=DynObj("2")
|
|
178
|
-
print(-(_1+_2)*_1)
|
|
179
|
-
|
|
180
|
-
@timer
|
|
181
|
-
def test_perf():
|
|
182
|
-
def recursion(x=None,recurse=10):
|
|
183
|
-
if recurse<=0:return x
|
|
184
|
-
return recursion(-(x+x)*x/x//x,recurse-1)
|
|
185
|
-
|
|
186
|
-
x=DynObj("x")
|
|
187
|
-
obj=recursion(x,10)
|
|
188
|
-
print(recursion(x,1),":",len(repr(obj)))
|
|
189
|
-
|
|
190
|
-
if __name__ == "__main__":test_perf()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|