如何将连接集合映射为匿名对象/具名元组?求字典转含内部集合匿名对象的工具
Great questions! Let's tackle them one by one, using your sample data to make the solutions tangible.
1. Mapping grouped collections to namedtuples or anonymous objects
Your raw data is a flattened list where each entry links a spaceship to a single officer. First, we need to group officers by their spaceship, then convert those groups into the object types you're asking about.
Option 1: Using namedtuple (immutable, structured objects)
namedtuple from the standard library creates lightweight, immutable objects that behave like tuples but have named attributes—perfect for fixed-data structures.
from collections import namedtuple from typing import List # Define our named tuple types Officer = namedtuple('Officer', ['OfficerId', 'OfficerName']) Spaceship = namedtuple('Spaceship', ['SpacehipId', 'SpacehipName', 'Officers']) def process_to_namedtuples(data: List[dict]) -> List[Spaceship]: # Group officers by spaceship ID ship_groups = {} for entry in data: ship_id = entry['SpacehipId'] # Initialize a new group if the spaceship isn't tracked yet if ship_id not in ship_groups: ship_groups[ship_id] = { 'SpacehipId': ship_id, 'SpacehipName': entry['SpacehipName'], 'Officers': [] } # Add the officer to the spaceship's officer list ship_groups[ship_id]['Officers'].append( Officer(entry['OfficerId'], entry['OfficerName']) ) # Convert each group to a Spaceship namedtuple return [Spaceship(**group) for group in ship_groups.values()] # Usage data = [ { "SpacehipId": 1, "SpacehipName": "Independence", "OfficerId": 1, "OfficerName": "John Smith" }, { "SpacehipId": 1, "SpacehipName": "Independence", "OfficerId": 2, "OfficerName": "Steven Smith" }, { "SpacehipId": 2, "SpacehipName": "Liberty", "OfficerId": 3, "OfficerName": "Michel Smith" } ] result = process_to_namedtuples(data) # Access attributes directly: print(result[0].SpacehipName) # Output: Independence print(result[0].Officers[1].OfficerName) # Output: Steven Smith
Option 2: Using types.SimpleNamespace (anonymous, mutable objects)
If you need mutable objects without defining explicit types, SimpleNamespace (from the types module) creates anonymous objects where dictionary keys become attributes.
import types from typing import List def process_to_anonymous_objects(data: List[dict]) -> List[types.SimpleNamespace]: ship_groups = {} for entry in data: ship_id = entry['SpacehipId'] if ship_id not in ship_groups: # Initialize a namespace object for the spaceship ship_groups[ship_id] = types.SimpleNamespace( SpacehipId=ship_id, SpacehipName=entry['SpacehipName'], Officers=[] ) # Add an anonymous officer object to the list ship_groups[ship_id].Officers.append( types.SimpleNamespace( OfficerId=entry['OfficerId'], OfficerName=entry['OfficerName'] ) ) return list(ship_groups.values()) # Usage result = process_to_anonymous_objects(data) # Access attributes the same way: print(result[1].SpacehipName) # Output: Liberty print(result[1].Officers[0].OfficerId) # Output: 3
2. Tools to map dictionaries to anonymous objects with internal collections
Here are the most common tools to handle this, ranging from standard library options to third-party packages:
types.SimpleNamespace: As shown above, it's lightweight, built into Python, and works seamlessly with internal collections. Great for quick, one-off use cases where you don't need formal type definitions.dataclasses.dataclass(Python 3.7+): A standard library tool that creates structured, mutable objects with built-in features like string representations and equality checks. Ideal when you want more structure thanSimpleNamespacebut don't want to write full class boilerplate.from dataclasses import dataclass from typing import List @dataclass class Officer: OfficerId: int OfficerName: str @dataclass class Spaceship: SpacehipId: int SpacehipName: str Officers: List[Officer] # You can reuse the same grouping logic as before, then instantiate the dataclassesattrs(third-party): A more powerful alternative todataclasswith extra features like validation, converters, and frozen (immutable) objects. Install withpip install attrs, then define your classes:import attrs from typing import List @attrs.define class Officer: OfficerId: int OfficerName: str @attrs.define class Spaceship: SpacehipId: int SpacehipName: str Officers: List[Officer]Custom classes: If you need full control over behavior (like custom methods or property validation), write a simple class with an
__init__method, then use dictionary unpacking to instantiate it.
内容的提问来源于stack exchange,提问作者christo

