使用 python-attrs 模块时使用 child class 启动基础时出现问题
Problem with initiating base with child class while working with python-attrs module
我正在尝试使用 attrs 模块创建模型 class。在我的脚本中 CollectionModel
class 是在 User
class 中继承的。所以从逻辑上讲,CollectionModel
中的所有属性都应该在 User
中可用。但是在尝试从字典创建 User 的新实例时(使用 attrs 是可能的)它表明 CollectionModel
的属性不存在于 User
我的脚本:
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
创建一个新用户 object。它显示以下错误。
TypeError: User.__init__() got an unexpected keyword argument '_id'
估计是parent class一开始没有启动。所以我尝试用 super()
函数启动它,根据 attrs 文档,它应该用 __attrs_pre_init__
来完成。来自文档:
The sole reason for the existence of __attrs_pre_init__
is to give
users the chance to call super().__init__()
, because some
subclassing-based APIs require that.
所以修改后的childclass就变成了这样
@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__()
但问题依旧。我是否以错误的方式执行 OOP?或者它只是 attrs 模块的错误?
我已经解决了那个问题,但有两个问题。第一个,在 python 中,属性名称前的下划线使其成为私有属性。因此,从字典创建新实例时 _id
是一个意外的键。
第二个问题是,我确实需要一个 _id
字段,因为我正在使用 MongoDB。在 MongoDB 文档中 _id
被保留用作主键。
现在第一个问题可以通过将 _id
替换为 id_
来解决(是的,在对面的下划线,因为 id
从字面上看是变量的 bad choice python).
中的名称
对于第二个问题,我进行了很多搜索,为 id_
字段创建了一个别名。但是使用 attrs
模块并不简单。因此,在将数据放入 MongoDB 集合之前,我修改了 get_dict()
方法以获得完美的字典。
这里是修改后的CollectionModel
class和User
class:
@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))
正在打印实例:
user_object = User()
print(user_object.get_dict())
输出:
{'timestamp': 1645131182.421929, 'username': '', 'userType': '', 'password': '', '_id': ObjectId('620eb5ae10f27b87de5be3a9')}
我正在尝试使用 attrs 模块创建模型 class。在我的脚本中 CollectionModel
class 是在 User
class 中继承的。所以从逻辑上讲,CollectionModel
中的所有属性都应该在 User
中可用。但是在尝试从字典创建 User 的新实例时(使用 attrs 是可能的)它表明 CollectionModel
的属性不存在于 User
我的脚本:
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
创建一个新用户 object。它显示以下错误。
TypeError: User.__init__() got an unexpected keyword argument '_id'
估计是parent class一开始没有启动。所以我尝试用 super()
函数启动它,根据 attrs 文档,它应该用 __attrs_pre_init__
来完成。来自文档:
The sole reason for the existence of
__attrs_pre_init__
is to give users the chance to callsuper().__init__()
, because some subclassing-based APIs require that.
所以修改后的childclass就变成了这样
@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__()
但问题依旧。我是否以错误的方式执行 OOP?或者它只是 attrs 模块的错误?
我已经解决了那个问题,但有两个问题。第一个,在 python 中,属性名称前的下划线使其成为私有属性。因此,从字典创建新实例时 _id
是一个意外的键。
第二个问题是,我确实需要一个 _id
字段,因为我正在使用 MongoDB。在 MongoDB 文档中 _id
被保留用作主键。
现在第一个问题可以通过将 _id
替换为 id_
来解决(是的,在对面的下划线,因为 id
从字面上看是变量的 bad choice python).
对于第二个问题,我进行了很多搜索,为 id_
字段创建了一个别名。但是使用 attrs
模块并不简单。因此,在将数据放入 MongoDB 集合之前,我修改了 get_dict()
方法以获得完美的字典。
这里是修改后的CollectionModel
class和User
class:
@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))
正在打印实例:
user_object = User()
print(user_object.get_dict())
输出:
{'timestamp': 1645131182.421929, 'username': '', 'userType': '', 'password': '', '_id': ObjectId('620eb5ae10f27b87de5be3a9')}