示例代码:
@classmethoddef from_mongo(cls: Type[T], data: dict) -> T:"""Convert "_id" (str object) into "id" (UUID object)."""if not data:raise ValueError("Data is empty.")id = data.pop("_id")return cls(**dict(data, id=id))
这段代码分成两部分来理解:
-
dict(data, id=id) 部分:
- 作用:
这里调用了 Python 内置的dict()
构造函数,它接受一个已有的字典(这里是data
)以及额外的关键字参数(这里是id=id
)。 - 效果:
它会创建一个新的字典,这个字典包含data
中的所有键值对,同时如果data
中已经有id
键,那么它会被新传入的id
覆盖;如果没有,则会新增一个id
键。 - 举例说明:
假设:
那么data = {"name": "Alice", "age": 30} id_value = "123e4567-e89b-12d3-a456-426614174000"
dict(data, id=id_value)
生成的新字典就是:
如果{"name": "Alice","age": 30,"id": "123e4567-e89b-12d3-a456-426614174000" }
data
原来已经有一个id
键,例如:
则执行data = {"name": "Alice", "age": 30, "id": "old-id"}
dict(data, id=id_value)
后,新字典中"id"
的值将变为"123e4567-e89b-12d3-a456-426614174000"
,覆盖原来的"old-id"
。
- 作用:
-
cls(…) 部分:**
- 作用:
这里的cls
通常代表当前类(比如在一个类方法中用cls
来引用类本身),**
是解包运算符。 - 效果:
当你写cls(**some_dict)
时,相当于把字典some_dict
中的每个键值对都作为关键字参数传给类的构造方法。 - 举例说明:
假设我们有一个类User
定义如下:
如果有字典:class User:def __init__(self, name, age, id):self.name = nameself.age = ageself.id = id
那么调用user_data = {"name": "Alice","age": 30,"id": "123e4567-e89b-12d3-a456-426614174000" }
User(**user_data)
就等价于:User(name="Alice", age=30, id="123e4567-e89b-12d3-a456-426614174000")
- 作用:
综合解释 cls(**dict(data, id=id))
:
- 首先,
dict(data, id=id)
会生成一个新的字典,这个字典包含了data
中所有的键值对,并确保键"id"
的值被更新为变量id
的值。 - 然后,
cls(**dict(...))
会调用类cls
的构造方法,把这个字典中的键值对逐个传入作为命名参数,从而创建并返回一个新的类实例。
通俗举例:
假设有如下情况:
data = {"name": "Bob", "age": 25}
id = "uuid-0001"
- 类
Person
定义为:class Person:def __init__(self, name, age, id):self.name = nameself.age = ageself.id = iddef __repr__(self):return f"Person(name={self.name}, age={self.age}, id={self.id})"
那么,执行 Person(**dict(data, id=id))
的过程如下:
- 生成新字典:
dict(data, id=id)
得到:{"name": "Bob", "age": 25, "id": "uuid-0001"}
- 调用构造函数:
Person(**{"name": "Bob", "age": 25, "id": "uuid-0001"})
就相当于执行:Person(name="Bob", age=25, id="uuid-0001")
- 创建实例:
得到一个Person
对象,其属性分别为name="Bob"
,age=25
,id="uuid-0001"
。
这样写的好处是可以灵活地从一个字典生成实例,同时确保某些关键字段(如 id
)被正确设置或覆盖。