如何将_Access命名元组的属性直接暴露在Logs类顶层?
实现属性直接访问的几种方案
方案1:使用__getattr__魔法方法(推荐)
这是最简洁且灵活的方式,当访问Logs实例不存在的属性时,自动转向内部的access对象查找,完全不破坏原有结构:
class Logs: def __init__(self, log: str): # 原初始化逻辑保持不变 raw_logs = match(S3_LOG_REGEX, log) if raw_logs is None: raise FormatError(log) logs = raw_logs.groups() timestamp = datetime.strptime(logs[2], "%d/%b/%Y:%H:%M:%S %z") http_status = int(logs[9]) access = _Access( timestamp, logs[3], logs[4], logs[5], logs[6], logs[7], logs[8], http_status, logs[10], ) self.access = access def __getattr__(self, name): # 当访问的属性不在Logs自身时,自动去access实例中查找 return getattr(self.access, name)
之后就能直接用log_struct.action访问,同时log_struct.access.action的原有调用方式也完全保留。
方案2:手动定义属性代理(适合需精准控制属性的场景)
如果只想暴露_Access中的部分属性,或者需要对属性做额外处理,可以逐个定义property:
class Logs: def __init__(self, log: str): # 原初始化逻辑保持不变 raw_logs = match(S3_LOG_REGEX, log) if raw_logs is None: raise FormatError(log) logs = raw_logs.groups() timestamp = datetime.strptime(logs[2], "%d/%b/%Y:%H:%M:%S %z") http_status = int(logs[9]) access = _Access( timestamp, logs[3], logs[4], logs[5], logs[6], logs[7], logs[8], http_status, logs[10], ) self.access = access @property def time(self): return self.access.time @property def ip(self): return self.access.ip @property def actor(self): return self.access.actor @property def request_id(self): return self.access.request_id @property def action(self): return self.access.action @property def key(self): return self.access.key @property def request_uri(self): return self.access.request_uri @property def status(self): return self.access.status @property def error_code(self): return self.access.error_code
这种方式的优点是IDE能自动补全属性,但缺点是_Access字段变更时,需要同步修改Logs的property定义。
方案3:优化IDE补全(配合方案1使用)
用方案1时,IDE可能不会自动提示_Access的属性,重写__dir__方法即可解决:
class Logs: def __init__(self, log: str): # 原初始化逻辑保持不变 self.access = access def __getattr__(self, name): return getattr(self.access, name) def __dir__(self): # 合并自身属性与access的属性列表,让IDE识别 return super().__dir__() + list(self.access._fields)
内容的提问来源于stack exchange,提问作者Mike Williamson
相关产品推荐
相关产品推荐

