thepoy 发表于 2021-4-8 08:46

用 python 实现一个只读的,只能有固定字段的类似结构体的特殊字典

本帖最后由 thepoy 于 2021-4-8 10:57 编辑

昨天在写 metaWeblog 的时候,因为请求是固定的几个字段,但 python 中好像并没有 struct 以供使用,于是便想着简单实现一下:
```python
class BaseStruct(dict):
    fields: Optional] = 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.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

    def __setattr__(self, key, value):
      raise NotImplementedError('read only')

    def __setitem__(self, k, v):
      raise NotImplementedError('read only')
```

基类写完,下面试一下好不好用:
```python
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"}
```
好像可以用了。

龍謹 发表于 2021-4-8 09:18

学习学习,谢谢楼主分享心得!

santus36 发表于 2021-4-8 10:46

collections.namedtuple?

thepoy 发表于 2021-4-8 10:49

本帖最后由 thepoy 于 2021-4-8 10:54 编辑

santus36 发表于 2021-4-8 10:46
collections.namedtuple?
我之前用namedtuple,但它不能被xmlrpc序列化,而且所有字段都不能为空,就给换了。
fields里定义的是所有有效字段,但字典不需要包含全部字段。
页: [1]
查看完整版本: 用 python 实现一个只读的,只能有固定字段的类似结构体的特殊字典