为什么在这种情况下没有使用元类?

2024-10-01 15:41:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我的问题有两个方面:首先,我不明白为什么MetaBoundedInt元类的__new__()方法没有被BoundedInt类的定义调用;其次,我想知道如何让它工作。在这一点上,我不知道它是否能正常工作,因为它甚至还没有被执行——所以我的问题并不是关于这个问题的(但是如果你发现了什么,或者在这方面有什么意见或建议,请随意提出来。;-). 在

我怀疑这个问题与BoundedInt是内置int的子类而不是{}的子类有关,但是在文档中找不到任何东西表明必须以不同的方式处理内置子类。在

更新:对不起,我没有意识到我在用Python3.3.4运行脚本。在Python2.7.6中,MataBoundInt.__new__()方法确实被调用了——所以现在我想知道为什么会有区别。同时,我将继续尝试使其正常工作(这是将我在Python2.7.6和Python3.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))

Tags: nameinselfnewreturndeftypeargs
2条回答

I didn't realize I was running the script with Python 3.3.4. In Python 2.7.6 the MataBoundInt.__new__()method is indeed being called so now I'm wondering why there's a difference.

区别在于,在Python3中,通过metaclass关键字参数向class语句指定一个元类:

class BoundedInt(int, metaclass=MetaBoundedInt):

这一点被改变了,以便元类可以更早地参与到类创建过程中,改变变量和函数定义在类语句中的操作方式,而不是仅仅对类的dict进行后处理。有关详细信息,请参见PEP 3115。在

BoundedInt必须是object的子类?让我检查一下

它按原样使用代码调用元类newforme(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。在

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.

来自http://docs.python.org/2/library/stdtypes.html 所以我想你可能对旧版本的Python有问题。。(2.2已经很老了。。我想你这几天看到它会很不幸的)。在

相关问题 更多 >

    热门问题