gpt4 book ai didi

python - 如何使代理对象表现得像它包装的整数?

转载 作者:行者123 更新时间:2023-11-28 17:25:49 25 4
gpt4 key购买 nike

我想创建一个代理类,它包装一个 int 以进行线程安全访问。与内置类型相反,代理类是可变的,因此它可以就地递增。现在,我想从外部将该类用作普通整数。通常,Python 的 __getattr__ 使得将属性访问转发到内部对象变得非常容易:

class Proxy:

def __init__(self, initial=0):
self._lock = threading.Lock()
self._value = initial

def increment(self):
with self._lock:
self._value += 1

def __getattr__(self, name):
return getattr(self._value, name)

然而,__getattr__ does not get triggered for magic methods__add____rtruediv__ 等,我需要让代理表现得像一个整数。有没有办法自动生成这些方法,或者以其他方式将它们转发给包装的整数对象?

最佳答案

@VPfB 链接的博文在comments有一个更通用和更彻底的解决方案来代理内置类型的 dunder 方法,但这里有一个简化且相当粗暴的例子。我希望它有助于理解如何创建这样的转发方法。

import threading
import numbers


def _proxy_slotted(name):
def _proxy_method(self, *args, **kwgs):
return getattr(self._value, name)(*args, **kwgs)
# Not a proper qualname, but oh well
_proxy_method.__name__ = _proxy_method.__qualname__ = name
return _proxy_method

# The list of abstract methods of numbers.Integral
_integral_methods = """
__abs__ __add__ __and__ __ceil__ __eq__ __floor__
__floordiv__ __int__ __invert__ __le__ __lshift__
__lt__ __mod__ __mul__ __neg__ __or__ __pos__ __pow__
__radd__ __rand__ __rfloordiv__ __rlshift__ __rmod__
__rmul__ __ror__ __round__ __rpow__ __rrshift__
__rshift__ __rtruediv__ __rxor__ __truediv__ __trunc__
__xor__""".split()

# The dunder, aka magic methods
_Magic = type('_Magic', (),
{name: _proxy_slotted(name)
for name in _integral_methods})


class IntProxy(_Magic, numbers.Integral):
"""
>>> res = IntProxy(1) + 1
>>> print(type(res), res)
<class 'int'> 2
>>> print(IntProxy(2) / 3)
0.6666666666666666
"""

def __init__(self, initial=0, Lock=threading.Lock):
self._lock = Lock()
self._value = initial

def increment(self):
with self._lock:
self._value += 1

def __getattr__(self, name):
return getattr(self._value, name)

关于python - 如何使代理对象表现得像它包装的整数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39186692/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com