本帖最后由 thepoy 于 2021-4-8 10:57 编辑
昨天在写 metaWeblog 的时候,因为请求是固定的几个字段,但 python 中好像并没有 struct 以供使用,于是便想着简单实现一下:
class BaseStruct(dict):
fields: Optional[Union[tuple, set, list]] = None
def __new__(cls, *args, **kwargs):
if not (isinstance(cls.fields, tuple) or isinstance(cls.fields, set)
or isinstance(cls.fields, list)):
raise AttributeError(
"`fields` is must be instance of tuple, set, or list")
if not set(args[0].keys()).issubset(set(cls.fields)):
raise OverflowError(
f"all keys of the dict object should be contained in `fields`: {cls.fields}"
)
return super().__new__(cls, *args, **kwargs)
def __getattr__(self, item: str):
if item not in self.fields:
raise KeyError("the key `%s` not exists" % item)
return self[item]
def __setattr__(self, key, value):
raise NotImplementedError('read only')
def __setitem__(self, k, v):
raise NotImplementedError('read only')
基类写完,下面试一下好不好用:
class BlogInfo(BaseStruct):
fields = ["blogid", "url", "blogName", "username", "password"]
rbi = {"blogid": 1, "url": "http", "blogName": "blog"}
bi = BlogInfo(rbi)
bi
# {'blogid': 1, 'url': 'http', 'blogName': 'blog'}
bi.url
# http
bi.url = "ftp"
# NotImplementedError: read only
bi["url"] = "ftp"
# NotImplementedError: read only
rbi = {"blogid": 1, "url": "http", "blogName": "blog", "content": "It is content"}
bi = BlogInfo(rbi)
# OverflowError: all keys of the dict object should be contained in `fields`: ['blogid', 'url', 'blogName', 'username', 'password']
rbi = {"blogid": 1, "url": "http"} # 能使用部分字段是与 namedtuple 的区别
bi = BlogInfo(rbi)
bi
# {"blogid": 1, "url": "http"}
好像可以用了。
|