我的问题有两个方面:首先,我不明白为什么__new__()
元类的MetaBoundedInt
方法没有被类BoundedInt
的定义调用,其次想知道如何让它发挥作用。在这一点上,我不知道它是否正常工作,因为它甚至没有被执行 - 所以我的问题在这一点上并不是真的(但如果你发现某些东西,或者在这方面有评论或建议,那么感觉自由地提出来。; - )。
我怀疑问题与BoundedInt
是内置int
的子类而非object
的事实有关,但无法在文档中找到任何内容内联的子类必须以某种方式以不同的方式处理。
更新:抱歉,我没有意识到我在使用Python 3.3.4运行脚本。在Python 2.7.6中确实调用了MataBoundInt.__new__()
方法 - 所以现在我想知道为什么会有区别。与此同时,我将重新尝试使其工作(这是一个重新打包 - 嵌套 - 进入一个元类,我在Python 2.7.6和Python 3.3.4中使用的一些代码。)
import functools
class MetaBoundedInt(type):
# int arithmetic methods that return an int
_specials = ('abs add and div floordiv invert lshift mod mul neg or pos '
'pow radd rand rdiv rfloordiv rlshift rmod rmul ror rpow '
'rrshift rshift rsub rtruediv rxor sub truediv xor').split()
_ops = set('__%s__' % name for name in _specials)
def __new__(cls, name, bases, attrs):
print('in MetaBoundedInt.__new__()')
classobj = type.__new__(cls, name, bases, attrs)
# create wrappers for all inherited int arithmetic ops
for name, meth in ((n, m) for n, m in vars(int).items() if n in cls._ops):
setattr(classobj, name, cls._DecoratedIntMethod(cls, meth))
return classobj
class _DecoratedIntMethod(object):
def __init__(self, cls, func):
self.cls, self.func = cls, func
def __get__(self, obj, cls=None):
# assume obj is a BoundedInt instance
@functools.wraps(self.func)
def wrapper(*args, **kwargs):
# return result of calling self.func() as BoundedInt
return self.cls(self.func(obj, *args, **kwargs),
bounds=obj._bounds)
return wrapper
class BoundedInt(int):
__metaclass__ = MetaBoundedInt
def __new__(cls, *args, **kwargs):
lower, upper = bounds = kwargs.pop('bounds')
val = int.__new__(cls, *args, **kwargs) # support multiple int() args
if val < lower:
val = int.__new__(cls, lower)
elif val > upper:
val = int.__new__(cls, upper)
val._bounds = bounds
return val
if __name__ == '__main__':
v = BoundedInt('64', 16, bounds=(0, 100)) # 0x64 == 100
print('type(v)={}, value={}'.format(type(v).__name__, v))
v += 10
print('type(v)={}, value={}'.format(type(v).__name__, v))
w = v + 10
print('type(v)={}, value={}'.format(type(w).__name__, w))
x = v - 110
print('type(v)={}, value={}'.format(type(x).__name__, x))
答案 0 :(得分:3)
我没有意识到我在使用Python 3.3.4运行脚本。在Python 2.7.6中确实调用了
MataBoundInt.__new__()
方法 - 所以现在我想知道为什么会有区别。
不同之处在于,在Python 3中,您通过metaclass
语句的class
关键字参数指定了元类:
class BoundedInt(int, metaclass=MetaBoundedInt):
这已被更改,以便元类可以在类创建过程的早期阶段参与进来,更改变量和函数定义在类语句中的操作方式,而不仅仅是对类的字典进行后处理。有关详细信息,请参阅PEP 3115。
答案 1 :(得分:0)
BoundedInt必须是对象的子类?让我查看一下
它使用您的代码按原样为我调用元类(python2.7)。你对物体所说的话虽然为我敲了响。
snowy:~$ python -V
Python 2.7.3
snowy:~$ python x.py
in MetaBoundedInt.__new__() <==== see
type(v)=BoundedInt, value=100
Traceback (most recent call last): <==== and this is a separate problem.
File "x.py", line 53, in <module>
v += 10
File "x.py", line 24, in __get__
@functools.wraps(self.func)
File "/usr/lib/python2.7/functools.py", line 33, in update_wrapper
setattr(wrapper, attr, getattr(wrapped, attr))
AttributeError: 'wrapper_descriptor' object has no attribute '__module__'
尝试运行isinstance(int,object),它为我返回true。
来自http://docs.python.org/2/library/stdtypes.html的Note Historically (until release 2.2), Python’s built-in types have differed from user-defined types because it was not possible to use the built-in types as the basis for object-oriented inheritance. This limitation no longer exists.
所以我认为你可能会遇到旧版本Python的问题..(2.2虽然很老......但是我觉得这些日子我看起来很不走运。)