모든 유형에 대해 새 클래스를 만들어 실제로이를 해결할 수 있습니다. 이 기능을 투명하게 사용하려면 __new__
이 필요합니다.
import weakref
class BigWrap(object):
def __new__(cls, wrapped):
wrapped_type = type(wrapped)
print('Wrapping %s (%s)' % (wrapped, wrapped_type))
# creates a new class, aka a new type
wrapper_class = type( # new_class = type(class name, base classes, class dict)
'%s_%s_%d' % (cls.__name__, wrapped_type.__name__, id(wrapped)), # dynamic class name
(
cls, # inherit from wrap to have all new methods
wrapped_type, # inherit from wrap_type to have all its old methods
),
{
'__getitem__': wrapped.__getitem__, # overwrite __getitem__ based on wrapped *instance*
'__new__': wrapped_type.__new__, # need to use wrapped_type.__new__ as cls.__new__ is this function
})
cls._wrappers[wrapped_type] = wrapper_class # store wrapper for repeated use
return cls._wrappers[wrapped_type](wrapped)
# self is already an instance of wrap_<type(wrapped)>
def __init__(self, wrapped):
self.__wrapped__ = wrapped
초기 "솔루션"
import weakref
class wrap(object):
_wrappers = weakref.WeakValueDictionary() # cache wrapper classes so we don't recreate them
def __new__(cls, wrapped):
wrapped_type = type(wrapped)
print('Wrapping %s (%s)' % (wrapped, wrapped_type))
try:
return object.__new__(cls._wrappers[wrapped_type]) # need to use object.__new__ as cls.__new__ is this function
except KeyError:
print('Creating Wrapper %s (%s)' % (wrapped, wrapped_type))
# creates a new class, aka a new type
wrapper_class = type( # class name, base classes, class dict
'%s_%s' % (cls.__name__, wrapped_type.__name__), # dynamic class name
(cls,), # inherit from wrap to have all its method
{'__getitem__': wrapped_type.__getitem__}) # overwrite __getitem__ based on wrapped class
cls._wrappers[wrapped_type] = wrapper_class # store wrapper for repeated use
return cls._wrappers[wrapped_type](wrapped)
# self is already an instance of wrap_<type(wrapped)>
def __init__(self, wrapped):
self._data = wrapped
것은 그러나 조심! 이렇게하면 래핑 된 클래스 '__getitem__
을 사용하여 원하는대로 할 수 있습니다. 그러나 이것이 항상 의미있는 것은 아닙니다! 예를 들어, list.__getitem__
은 실제로 CPython의 CAPI에 내장되며 다른 유형에는 적용 할 수 없습니다.
foo = wrap([1,2,3])
print(type(foo)) # __main__.wrap_list
foo[2]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-31-82791be7104b> in <module>()
----> 1 foo[2]
TypeError: descriptor '__getitem__' for 'list' objects doesn't apply to 'wrap_list' object
프로 팁 : 왜 이런 문제가 발생했는지 모르는 경우 최적화를 시도해서는 안됩니다. 그것의 간접비는 아마 당신이 생각하는 것만 큼 중요하지 않습니다. – MisterMiyagi
하지만 시도하지 않았다면 어떻게 작동하는지 배울 수 없었을 것입니다. OTOH, 내가 깨닫다 간 알면, 나는 그것을 시도하지 않았을 것입니다 ... 또한, 아마 당신은 내가 얼마나 중요하다고 생각했는지 모릅니다. – NichtJens
모든 유형에 대해 새 클래스를 작성하면 실제로이 문제를 해결할 수 있습니다. 기본적으로 이것을 위해 팩토리 함수가 필요합니다. '__new__'을 통해 투명하게 구현할 수 있습니다. 그것은 약간의 흑 마법입니다 ... 물론 나는 당신이 그것을 얼마나 중요하다고 생각하는지 추측 할 수 있습니다. 참조 용으로 약 0.1 usec의 통화 당 안전 할 수 있습니다. – MisterMiyagi