首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在使用python-attrs模块时使用子类初始化基类时遇到的问题

在使用python-attrs模块时使用子类初始化基类时遇到的问题
EN

Stack Overflow用户
提问于 2022-02-16 15:57:34
回答 1查看 73关注 0票数 1

我正在尝试使用吸引人模块创建模型类。在我的脚本中,CollectionModel类是在User类中继承的。因此,从逻辑上讲,CollectionModel中的所有属性都应该在User中可用。但是,在尝试从字典中创建用户的新实例时(使用attrs是可能的),这表明CollectionModel的属性不存在于User中。

我的剧本:

代码语言:javascript
复制
from bson import ObjectId
from attrs import asdict, define, field, validators, Factory
import time


@define
class CollectionModel:
    """ Base Class For All Collection Schema"""
    _id : str =   field(converter=str, default=Factory(ObjectId))
    _timestamp : float = field(default=Factory(time.time))

    def get_dict(self):
        return asdict(self)

    def update(self):
        self._timestamp = time.time()

@define
class User(CollectionModel):
    
    username : str = field(factory = str, validator=validators.instance_of(str)) 
    userType : str = field(factory = str, validator=validators.instance_of(str)) 
    password : str = field(factory = str, validator=validators.instance_of(str))



user_object = User()
new_user_object = User(**asdict(user_object))

在这里,我试图从user_object创建一个新的用户对象。它显示了以下错误。

代码语言:javascript
复制
TypeError: User.__init__() got an unexpected keyword argument '_id'

我猜想父类一开始并不是初始化的。因此,我尝试用super()函数启动它,并且根据attrs文档,它应该用__attrs_pre_init__来完成。从文件中:

__attrs_pre_init__存在的唯一原因是为了给用户调用super().__init__()的机会,因为一些基于子类的API需要这样做。

所以修改后的子类会变成这样。

代码语言:javascript
复制
@define
class User(CollectionModel):
    
    username : str = field(factory = str, validator=validators.instance_of(str)) 
    userType : str = field(factory = str, validator=validators.instance_of(str)) 
    password : str = field(factory = str, validator=validators.instance_of(str))

    def __attrs_pre_init__(self):
        super().__init__()

但问题仍然存在。我是不是做错了?还是仅仅是attrs模块的一个bug?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-17 20:58:56

我解决了这个问题,有两个问题。第一个在python中,在属性名使其为私有属性之前下划线。因此,在从字典中创建新实例时,_id是一个意外的键。

第二个问题是,在使用_id时,我确实需要一个MongoDB字段。在MongoDB文档中,保留_id作为主键使用。

现在,第一个问题可以通过将_id替换为id_来解决(是的,在对面下划线,因为id实际上是python中变量名的糟糕的选择 )。

对于第二个问题,我已经搜索了很多,以便为id_字段创建一个别名。但是,在使用attrs模块时,这并不简单。因此,我对get_dict()方法进行了修改,以便在将数据放入MongoDB集合之前获得一个完美的字典。

下面是修改后的CollectionModel类和User类:

代码语言:javascript
复制
@define
class CollectionModel:
    """ Base Class For All Collection Schema"""
    id_: ObjectId =   field(default=Factory(ObjectId))
    timestamp : float = field(default=Factory(time.time))

    def get_dict(self):
        d = asdict(self)
        d["_id"] = d["id_"]
        del d["id_"]
        return d

    def update(self):
        self.timestamp = time.time()

@define
class User(CollectionModel):

    username : str = field(factory = str, validator=validators.instance_of(str)) 
    userType : str = field(factory = str, validator=validators.instance_of(str)) 
    password : str = field(factory = str, validator=validators.instance_of(str))

现在打印一个实例:

代码语言:javascript
复制
user_object = User()
print(user_object.get_dict())

输出:

代码语言:javascript
复制
{'timestamp': 1645131182.421929, 'username': '', 'userType': '', 'password': '', '_id': ObjectId('620eb5ae10f27b87de5be3a9')}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71145126

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档