python - 使 Python 函数可下标
问题描述
出于完全人为的编程练习的目的,我希望能够访问我为特定类创建的所有对象,使用装饰器并通过下标类本身。
在下面的示例中,我使用参数创建了 A 类的实例1
,并使用键将结果存储在字典中'1'
。
因此,通过尝试直接索引 A 类,它应该返回创建的对象的实例,但是,它只返回传递给 __get__item 的参数,如果我尝试使用 A['1 直接索引它,则会引发 TypeError ']。
import types
def remember(cl):
seen = dict()
def _remember(*args, **kwargs):
key = ','.join(map(str, args))
if key not in seen:
seen[key] = cl(*args, **kwargs)
return seen[key]
_remember.__getitem__ = types.MethodType(seen.get, _remember)
return _remember
@remember
class A(object):
def __init__(self, x):
pass
a = A(1)
b = A.__getitem__('1')
print(a == b) #should print true, but instead, A.__get__item returns '1'. Ideally, A['1'] would work.
解决方案
这就是我想出的。
我们不能有A[<something>]
尽可能多的用法,因为这意味着改变type
. 我已经A.get(<something>)
为那个用例创建了。
这与您的尝试不同,我们不是从装饰器返回一个函数,而是返回一个从原始类扩展的新类。该类存储其父类的所有实例化实例,并通过从args
and创建的键对它们进行索引kwargs
。
已__getitem__
在类上被覆盖,然后在父类中被覆盖,它采用以下任何一种:
- args (tuple) 和 kwargs (dict) 的元组
- Args 作为一个元组
- 单个参数
无论如何,使用代码:
from typing import Any, Dict
def remember(klass):
def get_key(args, kwargs):
return hash((args, tuple(sorted(kwargs.items()))))
class RememberedClass(klass):
_instances: Dict[int, Any] = {}
def __new__(cls, *args, **kwargs):
c = klass(*args, **kwargs)
klass.__getitem__ = cls.__getitem__
key = get_key(args, kwargs)
cls._instances[key] = c
return c
@staticmethod
def get(*args, **kwargs) -> klass:
key = get_key(args, kwargs)
return RememberedClass._instances[key]
def __getitem__(self, item) -> klass:
if isinstance(item, tuple) and len(item) == 2:
# (args, kwargs)
args, kwargs = item
key = get_key(args, kwargs)
elif isinstance(item, tuple):
# (arg, arg, ...)
key = get_key(item, {})
else:
# arg
key = get_key((item,), {})
return RememberedClass._instances.get(key)
return RememberedClass
@remember
class Foo:
def __init__(self, val):
pass
我相信这就是你想要的?
>>> f = Foo(1)
>>> g = Foo(2)
>>> f is g
False
>>> f is f[1]
True
>>> g is g[2]
True
>>> g is f[2]
True
>>> f is Foo.get(1)
True
>>> type(f)
__main__.Foo
>>> Foo
__main__.remember.<locals>.RememberedClass
推荐阅读
- sms - 如何实现这样的短信 USSD 应用程序?
- javascript - 如何更改 img src 的域?
- python - 如何仅使用rdd而不是数据框从spark中的csv中获取N(th)列
- javascript - 如何通过缩写获得时区?
- android - 应为 BEGIN_ARRAY,但在此代码中为 STRING
- html - 为什么我的 css 动画在 Safari 中不起作用?
- java - 如何在 Java 中将方法级整数和实例级整数相加?
- typescript - 类型“ConnectedComponentClass<>”不可分配给类型“ComponentType”
- apache-flink - Flink 在提交任务时抛出 NullPointerException。我如何解决它?
- dictionary - Haskell Data.Map 的内部表示