Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 元类不初始化新类_Python 3.x_Metaclass - Fatal编程技术网

Python 3.x 元类不初始化新类

Python 3.x 元类不初始化新类,python-3.x,metaclass,Python 3.x,Metaclass,全部!我的代码有一个大问题。我试图编写简单的代码作为理解元编程的简单框架。我还有下一个问题 doc1 = Document() doc1.id = 20 doc2 = Document() print (doc2.id) # show 20, but it's wrong!!! It should be 0 这是我的代码列表 class BaseModel(type): def __new__(cls, name, bases, attrs, **kwargs): instance

全部!我的代码有一个大问题。我试图编写简单的代码作为理解元编程的简单框架。我还有下一个问题

doc1 = Document()
doc1.id = 20
doc2 = Document()
print (doc2.id) # show 20, but it's wrong!!! It should be 0
这是我的代码列表

class BaseModel(type):
def __new__(cls, name, bases, attrs,  **kwargs):
    instance = super().__new__

    parents = [b for b in bases if isinstance(b, BaseModel)]
    if not parents:
        return instance(cls, name, bases, attrs)

    module_ = attrs.pop('__module__')
    attrs_ = {'__module__': module_}

    classcell_ = attrs.pop('__classcell__', None)
    if classcell_ is not None:
        attrs_['__classcell__'] = classcell_

    for key, value in attrs.items():
        if not isinstance(value, Field):
            continue

        print (value.__dict__)
        attrs_[key] = value

    instance = instance(cls, name, bases, attrs_, **kwargs)

    return instance


class Model(metaclass=BaseModel):
    pass

class Field:
    def __init__(self, value=0):
        self._value = value

    def __get__(self, instance, owner):
        return self._value

    def __set__(self, instance, value):
        self._value = value

class Document(Model):
    id = Field()

发生什么事了?我认为主要问题是元类中的新方法。我说得对吗?如何修复它?

尽管元类不是问题的根源,但您试图用元类完成的工作令人困惑。实现唯一ID不需要元类,只需要精心编制的描述符

在您的例子中,
字段
描述符跟踪单个值,而不是现有的实例和ID对

要解决此问题,您需要保留已获取值的弱引用

import weakref, itertools

class UniqueId:
    def __init__(self):
        self._values = weakref.WeakKeyDictionary()

    def __get__(self, instance, owner):
        if instance is None:
            return self
        else:
            return self._values[instance]

    def __set__(self, instance, value):
        if value not in self._values.values():
            self._values[instance] = value
        else:
            raise ValueError('Unique id {} already taken'.format(value))

    def get_unique_id(self):
        existing_ids = set(self._values.values())
        return next(i for i in itertools.count() if i not in existing_ids)

class Model:
    def __new__(cls, *args, **kwargs):
        instance = super().__new__(cls, *args, **kwargs)

        for name, attr in cls.__dict__.items():
            if isinstance(attr, UniqueId):
                setattr(instance, name, attr.get_unique_id())

        return instance

class Document(Model):
    id = UniqueId()
例子
虽然元类不是问题的根源,但您试图用元类完成的工作令人困惑。实现唯一ID不需要元类,只需要精心编制的描述符

在您的例子中,
字段
描述符跟踪单个值,而不是现有的实例和ID对

要解决此问题,您需要保留已获取值的弱引用

import weakref, itertools

class UniqueId:
    def __init__(self):
        self._values = weakref.WeakKeyDictionary()

    def __get__(self, instance, owner):
        if instance is None:
            return self
        else:
            return self._values[instance]

    def __set__(self, instance, value):
        if value not in self._values.values():
            self._values[instance] = value
        else:
            raise ValueError('Unique id {} already taken'.format(value))

    def get_unique_id(self):
        existing_ids = set(self._values.values())
        return next(i for i in itertools.count() if i not in existing_ids)

class Model:
    def __new__(cls, *args, **kwargs):
        instance = super().__new__(cls, *args, **kwargs)

        for name, attr in cls.__dict__.items():
            if isinstance(attr, UniqueId):
                setattr(instance, name, attr.get_unique_id())

        return instance

class Document(Model):
    id = UniqueId()
例子
太棒了。谢谢大家!@基里尔:没问题。在StackOverflow上,单击左侧的绿色复选标记,毫不犹豫地接受允许ot解决问题的答案。这有助于其他用户找到有用的答案,并为提问者和回答者提供一些良好的声誉。这太棒了。谢谢大家!@基里尔:没问题。在StackOverflow上,单击左侧的绿色复选标记,毫不犹豫地接受允许ot解决问题的答案。这有助于其他用户找到有用的答案,并为提问者和回答者提供一些良好的声誉。