6
回答
python高手来看看这两个的主要特性是什么?
利用AWS快速构建适用于生产的无服务器应用程序,免费试用12个月>>>   

直接上代码吧==!

import copy
import types
ImmutableTypes = (
    types.NoneType,
    bool,
    complex,
    float,
    int,
    long,
    tuple,
    frozenset,
    basestring
)

MUTABLE = "__mutable__"

class COWMeta(type):
    pass

class COWDictMeta(COWMeta):
    __warn__ = False
    __hasmutable__ = False
    __marker__ = tuple()

    def __str__(cls):
        # FIXME: I have magic numbers!
        return "<COWDict Level: %i Current Keys: %i>" % (cls.__count__, len(cls.__dict__) - 3)
    __repr__ = __str__

    def cow(cls):
        class C(cls):
            __count__ = cls.__count__ + 1
        return C
    copy = cow
    __call__ = cow

    def __setitem__(cls, key, value):
        if not isinstance(value, ImmutableTypes):
            if not isinstance(value, COWMeta):
                cls.__hasmutable__ = True
            key += MUTABLE
        setattr(cls, key, value)

    def __getmutable__(cls, key, readonly=False):
        nkey = key + MUTABLE
        try:
            return cls.__dict__[nkey]
        except KeyError:
            pass

        value = getattr(cls, nkey)
        if readonly:
            return value

        if not cls.__warn__ is False and not isinstance(value, COWMeta):
            print("Warning: Doing a copy because %s is a mutable type." % key, file=cls.__warn__)
        try:
            value = value.copy()
        except AttributeError as e:
            value = copy.copy(value)
        setattr(cls, nkey, value)
        return value

    __getmarker__ = []
    def __getreadonly__(cls, key, default=__getmarker__):
        """\
        Get a value (even if mutable) which you promise not to change.
        """
        return cls.__getitem__(key, default, True)

    def __getitem__(cls, key, default=__getmarker__, readonly=False):
        try:
            try:
                value = getattr(cls, key)
            except AttributeError:
                value = cls.__getmutable__(key, readonly)

            # This is for values which have been deleted
            if value is cls.__marker__:
                raise AttributeError("key %s does not exist." % key)

            return value
        except AttributeError as e:
            if not default is cls.__getmarker__:
                return default

            raise KeyError(str(e))

    def __delitem__(cls, key):
        cls.__setitem__(key, cls.__marker__)

    def __revertitem__(cls, key):
        if not cls.__dict__.has_key(key):
            key += MUTABLE
        delattr(cls, key)

    def __contains__(cls, key):
        return cls.has_key(key)

    def has_key(cls, key):
        value = cls.__getreadonly__(key, cls.__marker__)
        if value is cls.__marker__:
            return False
        return True

    def iter(cls, type, readonly=False):
        for key in dir(cls):
            if key.startswith("__"):
                continue

            if key.endswith(MUTABLE):
                key = key[:-len(MUTABLE)]

            if type == "keys":
                yield key

            try:
                if readonly:
                    value = cls.__getreadonly__(key)
                else:
                    value = cls[key]
            except KeyError:
                continue

            if type == "values":
                yield value
            if type == "items":
                yield (key, value)
        raise StopIteration()

    def iterkeys(cls):
        return cls.iter("keys")
    def itervalues(cls, readonly=False):
        if not cls.__warn__ is False and cls.__hasmutable__ and readonly is False:
            print("Warning: If you arn't going to change any of the values call with True.", file=cls.__warn__)
        return cls.iter("values", readonly)
    def iteritems(cls, readonly=False):
        if not cls.__warn__ is False and cls.__hasmutable__ and readonly is False:
            print("Warning: If you arn't going to change any of the values call with True.", file=cls.__warn__)
        return cls.iter("items", readonly)

class COWSetMeta(COWDictMeta):
    def __str__(cls):
        # FIXME: I have magic numbers!
        return "<COWSet Level: %i Current Keys: %i>" % (cls.__count__, len(cls.__dict__) -3)
    __repr__ = __str__

    def cow(cls):
        class C(cls):
            __count__ = cls.__count__ + 1
        return C

    def add(cls, value):
        COWDictMeta.__setitem__(cls, repr(hash(value)), value)

    def remove(cls, value):
        COWDictMeta.__delitem__(cls, repr(hash(value)))

    def __in__(cls, value):
        return COWDictMeta.has_key(repr(hash(value)))

    def iterkeys(cls):
        raise TypeError("sets don't have keys")

    def iteritems(cls):
        raise TypeError("sets don't have 'items'")

# These are the actual classes you use!
class COWDictBase(object):
    __metaclass__ = COWDictMeta
    __count__ = 0

class COWSetBase(object):
    __metaclass__ = COWSetMeta
    __count__ = 0

举报
ChenQi
发帖于5年前 6回/425阅
共有6个答案 最后回答: 5年前
COWDictBase和COWSetBase 是两个metaclass ,不信你输出type( COWDictBase),type( COWSetBase),metaclass 就是生成类的类。
--- 共有 2 条评论 ---
ChenQi而且你看他的注释: # These are the actual classes you use! 问题是,我没看懂为啥要写这两个类。 5年前 回复
ChenQiCOWDictMeta和COWSetMeta才是metaclass 5年前 回复
COWDictMeta和COWSetMeta 却实也是metaclas, COWDictBase和COWSetBase才是实际使用的metaclass 你看不出来你用type试试就是知道了。类似于在封装. 

引用来自“Boa.Hancoc”的答案

COWDictMeta和COWSetMeta 却实也是metaclas, COWDictBase和COWSetBase才是实际使用的metaclass 你看不出来你用type试试就是知道了。类似于在封装. 

metaclass通常是type的子类或者封装type。COWDictBase明显是继承了object这个积累的。

__metaclass__ = xxxx表明用xxx这个metaclass来构建这个类,他是这个类的一个attribute,和封装没关系。

下面这个片段说明了如何使用metaclass:(from SO)

You can add a __metaclass__ attribute when you write a class:

class Foo(object):   __metaclass__ = something...   [...] 

If you do so, Python will use the metaclass to create the class Foo.

Careful, it's tricky.

You write class Foo(object) first, but the class object Foo is not created in memory yet.

Python will look for __metaclass__ in the class definition. If it finds it, if will use it to create the object class Foo. If it doesn't, it will usetype to create the class.

你这是py3啊,这个代码很明白啊,就是修改下默认metaclass,的一些特殊成员。我不明白你想问什么。

没仔细看,刚看了下。COWDictBase和COWSetBase不是metaclass.

顶部