使用 wrapt 包更改类型
type changed using wrapt package
这个
<class 'assign.A'>
<class 'BoundFunctionWrapper'>
由以下代码打印:
from wrapt import FunctionWrapper
class A(FunctionWrapper):
A = None
def __init__(self, f):
super(A, self).__init__(f, self.wrapper)
def wrapper(self, wrapped, instance, args, kwargs):
return wrapped(*args, **kwargs)
@A
def f():
pass
print(type(f))
A.A = f
print(type(A.A))
如果将 f
分配给 class 的静态变量,则类型只更改 。我本来希望类型保持 A
。
怎么会这样?
我检查了一下,这将是 Python 2 中的默认行为,而不是 Python 3 中的默认行为:
>>> class X(object): # Python 2
def g():pass
>>> X.g
<unbound method X.g>
wrapt 行为的原因:
- 同样的模块也存在于Python 2.
- 我在
wrapt.wrappers
的代码中看到没有检查为这种特殊情况创建不同的行为形式 2 到 3。
解释
__get__
行为发生了变化。
Python 2:
>>> class X(object):
def g():pass
>>> X.g
<unbound method X.g>
>>> class B: # error: Must inherit form object (see comments)
def __get__(self, *args):
print(args)
>>> X.b = B()
>>> X.b
<__main__.B instance at 0x029C0440>
Python 3:
>>> class X(object):
def g():pass
>>> X.g
<function g at 0x030430C0>
>>> class B:
def __get__(self, *args):
print(args)
>>> X.b = B()
>>> X.b
(None, <class 'X'>)
推荐
我想说这可能是一个错误。根据 pypi
, wrapt
渴望正确。所以,我想这应该讨论一下。请在 github 和 link 这个问题上开一个问题(告诉我是否应该这样做)。
使用属性 __bound_function_wrapper__
为绑定方法创建自己的包装器。在 wrapt.wrappers
中显示上下文的代码:
class FunctionWrapper(_FunctionWrapperBase):
__bound_function_wrapper__ = BoundFunctionWrapper
所以,如果你真的想创建一个自己的包装器 class 你可以这样做:
class OwnBoundWrapper(wrapt.BoundFunctionWrapper):
# additional code here
A.__bound_function_wrapper__ = OwnBoundWrapper
我猜这是(大部分)预期的行为。
您可以阅读 this for more details, but basically, as you mentioned the fact that FunctionWrapper
is a descriptor(有一个 __get__
方法)是导致您观察到的行为的原因。
当你做类似
的事情时,描述符协议用于return方法而不仅仅是裸函数
some_var = instance.method
当从 class:
检索实例方法时,python 2 和 3 确实具有不同的行为
python3:
In [1]: class Test:
...: def a(self):
...: pass
...:
In [2]: Test.a
Out[2]: <function __main__.Test.a>
python2:
In [1]: class Test:
...: def a(self):
...: pass
...:
In [2]: Test.a
Out[2]: <function __main__.Test.a>
其中 python2 return 是一个未绑定的方法,python3 只是 return 的函数。但是,可能出于某种原因,当在 class 上访问时,人们可能仍想装饰它们。做这样的事情的一个例子是创建一个混合 属性,它有一个名字,但在 class 上的行为与 class.
的实例不同。
这个
<class 'assign.A'>
<class 'BoundFunctionWrapper'>
由以下代码打印:
from wrapt import FunctionWrapper
class A(FunctionWrapper):
A = None
def __init__(self, f):
super(A, self).__init__(f, self.wrapper)
def wrapper(self, wrapped, instance, args, kwargs):
return wrapped(*args, **kwargs)
@A
def f():
pass
print(type(f))
A.A = f
print(type(A.A))
如果将 f
分配给 class 的静态变量,则类型只更改 。我本来希望类型保持 A
。
怎么会这样?
我检查了一下,这将是 Python 2 中的默认行为,而不是 Python 3 中的默认行为:
>>> class X(object): # Python 2
def g():pass
>>> X.g
<unbound method X.g>
wrapt 行为的原因:
- 同样的模块也存在于Python 2.
- 我在
wrapt.wrappers
的代码中看到没有检查为这种特殊情况创建不同的行为形式 2 到 3。
解释
__get__
行为发生了变化。
Python 2:
>>> class X(object):
def g():pass
>>> X.g
<unbound method X.g>
>>> class B: # error: Must inherit form object (see comments)
def __get__(self, *args):
print(args)
>>> X.b = B()
>>> X.b
<__main__.B instance at 0x029C0440>
Python 3:
>>> class X(object):
def g():pass
>>> X.g
<function g at 0x030430C0>
>>> class B:
def __get__(self, *args):
print(args)
>>> X.b = B()
>>> X.b
(None, <class 'X'>)
推荐
我想说这可能是一个错误。根据 pypi ,
wrapt
渴望正确。所以,我想这应该讨论一下。请在 github 和 link 这个问题上开一个问题(告诉我是否应该这样做)。使用属性
__bound_function_wrapper__
为绑定方法创建自己的包装器。在wrapt.wrappers
中显示上下文的代码:class FunctionWrapper(_FunctionWrapperBase): __bound_function_wrapper__ = BoundFunctionWrapper
所以,如果你真的想创建一个自己的包装器 class 你可以这样做:
class OwnBoundWrapper(wrapt.BoundFunctionWrapper): # additional code here A.__bound_function_wrapper__ = OwnBoundWrapper
我猜这是(大部分)预期的行为。
您可以阅读 this for more details, but basically, as you mentioned the fact that FunctionWrapper
is a descriptor(有一个 __get__
方法)是导致您观察到的行为的原因。
当你做类似
的事情时,描述符协议用于return方法而不仅仅是裸函数some_var = instance.method
当从 class:
检索实例方法时,python 2 和 3 确实具有不同的行为python3:
In [1]: class Test:
...: def a(self):
...: pass
...:
In [2]: Test.a
Out[2]: <function __main__.Test.a>
python2:
In [1]: class Test:
...: def a(self):
...: pass
...:
In [2]: Test.a
Out[2]: <function __main__.Test.a>
其中 python2 return 是一个未绑定的方法,python3 只是 return 的函数。但是,可能出于某种原因,当在 class 上访问时,人们可能仍想装饰它们。做这样的事情的一个例子是创建一个混合 属性,它有一个名字,但在 class 上的行为与 class.
的实例不同。