怎么才能在 Python 中输出一个 key 不带引号的字典呢

2022-09-01 16:19:58 +08:00
 mylifcc

或者说这是一个什么样的格式?

比如

{
city: "beijing",
device: "Iphone"
}
3900 次点击
所在节点    Python
37 条回复
wxf666
2022-09-01 20:21:36 +08:00
@mylifcc 对了,若是 key 包含 " \ : <换行> 等字符,你打算咋表示呢?

{
 \": "引号",
 \\: "斜杠",
 \:: "冒号",
 \n: "换行"
}

这样?
mylifcc
2022-09-01 20:51:09 +08:00
@wxf666 我不知道呀,我只想生成一个 不带引号的 key 的字典?。。。。
ershierdu
2022-09-01 20:53:44 +08:00
之前被迫需要用 Python 解析这种结构的字符串,查了一圈,大家都叫它“bad json”…
thinkershare
2022-09-01 21:08:56 +08:00
@mylifcc 如果你只是需要一个这样的字符串, 那么有非常多办法, 如果你需要一个无属性字典, 那么, 没有办法, 因为字典的 key 必须是一个可以哈希化的值, 而你写的属性名称不是任何类型, 因此没办法实现你要的功能. 作为 key 的键, 必须是一个值, 你需要对象那种普通属性是做不到的.
Vegetable
2022-09-01 21:31:07 +08:00
这个考察应该是递归方向的内容,如果用替换那条路会被各种各样的特殊情况为难。

https://imgur.com/a/PkZDCYZ
LindsayZhou
2022-09-01 21:49:43 +08:00
Python 的 JSONEncoder 全部是用 Python 写的,没用 C
继承过来重新写一下就行了吧: https://github.com/python/cpython/blob/2ecc195498f3b1256fabc2b66e0d8f6d671fa1d7/Lib/json/encoder.py#L36
mylifcc
2022-09-01 22:03:34 +08:00
@LindsayZhou
@thinkershare 主要是想知道这是个什么东西,因为这个东西看起来不像是语法错误,但我又说不上是什么,也没想着他是什么指定的格式,就想知道什么地方会生成它,然后什么地方会用到
wxf666
2022-09-01 22:35:52 +08:00
@mylifcc 这个应该是 js 的对象(字面量)吧: https://zh.javascript.info/object


试着写了一个( v 站排版原因,行首有若干全角空格):

1. 可以是数字、布尔、空值、字符串、列表、字典的随意组合

2. 除了字典的键会直接字符串化外,其他字符串会遵循 json 的要求,不包含控制字符和 \ "(替换为转义字符或十六进制)


from typing import Sequence, Mapping

ESCAPE_TABLE = str.maketrans(
  {chr(i): f'\\u{i:04x}' for i in range(32)} |
  {k: f'\\{v}' for k, v in zip('\b\t\n\f\r\\"', 'btnfr"\\')}
)

def jsonify(obj) -> str:
   if isinstance(obj, str):
     return f'"{obj.translate(ESCAPE_TABLE)}"'
   elif isinstance(obj, Sequence):
     return f"[{', '.join(map(jsonify, obj))}]"
   elif isinstance(obj, Mapping):
     return f"{{{', '.join(f'{k}: {jsonify(v)}' for k, v in obj.items())}}}"
   else:
     return str({
       None: 'null',
       True: 'true',
       False: 'false',
    }.get(obj, obj))
JamesMackerel
2022-09-01 22:43:49 +08:00
@wxf666 参考 https://blog.dragonslayer.me/archives/115

虽然性能很低就是了(感觉)。如果要性能,应该可以根据语义去做 pretty print ,感觉是一个 json serializer ?不知道好做不好做。
wxf666
2022-09-02 00:30:51 +08:00
@JamesMackerel
@llsquaer
@mylifcc

尝试用正则实现了,可在 regexr.com regex101.com 运行

1. 可以是数字、布尔、空值、字符串、列表、字典的随意组合

2. 除了字典的键会直接字符串化外,其他字符串会遵循 json 的要求,不包含控制字符和 \ "(替换为转义字符或十六进制)


以前写过『用正则去除 不规则 json 中的末项逗号』(如:[1, 2, 3,]),想着拿来改改就好

发现功力不够,必须要用到 (?>...) 特性,来防止回溯(即,碰到 \ 就一定要继续匹配后面的转义字符)

但这也导致 JavaScript 、Golang 、Python 3.10 及以下版本 无法使用( Python 3.11 开始支持了)


正则:"((?:(?>\\?).)*?)"\s*(:)|("(?:\\?.)*?")
替换:$1$2$3
引擎:PCRE


『例子( v 站排版原因,行首有若干全角空格,但不影响)』

[
  "\"fake_key\": value",
   123, true, false, null,
  {
    "key1" : "\n\\\":,]:\\",
    "key2" : "\n\\\":,}:\\",
  },
]


『替换后』

[
  "\"fake_key\": value",
   123, true, false, null,
  {
     key1: "\n\\\":,]:\\",
     key2: "\n\\\":,}:\\",
  },
]
wxf666
2022-09-02 00:38:13 +08:00
@mylifcc 28 楼有个小地方写错了,

{k: f'\\{v}' for k, v in zip('\b\t\n\f\r\\"', 'btnfr"\\')}

改成

{k: f'\\{v}' for k, v in zip('\b\t\n\f\r\\"', 'btnfr\\"')}
mylifcc
2022-09-02 01:10:33 +08:00
@wxf666 牛的
js8510
2022-09-02 01:59:34 +08:00
```
>>> class Key:
... def __repr__(self):
... return "Key"
...
>>>
>>>
>>>
>>> m={Key(), 1}
>>> m
{1, Key}
```

这样不就好了??
gongshuiwen
2022-09-02 10:21:17 +08:00
使用非字符串对象作为键就会输出该格式,例如:
class City:
pass


city = City()
print({city: "beijing"})

输出结果为:{<__main__.City object at 0x000001CE970BB608>: 'beijing'}


上面为对象默认的字符串表示形式,可以使用 __repr__ 方法改变对象的字符串表示形式:
class City:
def __repr__(self):
return 'city'


city = City()
print({city: "beijing"})

输入结果为:{city: 'beijing'}

所以字典中不带引号的键说明是一个非字符串对象作为的键吧。
xiaochun41
2022-09-02 10:44:07 +08:00
楼上和楼上的楼上的分析可以借鉴,python 里面字典打印的时候调用的是 dict 的这个方法 __repr__ ,单说 key 的话 也是调用的 key 的类型对应的 __repr__ 方法。
所以就是两个思路:
1 . 继承 dict ,重新定义一个自己的字典类,重新实现 __repr__
2 . 针对特定的 key ,重新实现 key 的 __repr__方法
pjxxcc
2022-09-02 11:06:53 +08:00
用数字作为 key ,就不会带引号哦
比如:
>>> d = {1: 'yi', 'a': "A"}
>>> d
{1: 'yi', 'a': 'A'}
>>> print(d)
{1: 'yi', 'a': 'A'}
stonesirsir
2022-12-30 16:18:55 +08:00
遍历字典,然后用字符串打印出来吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/877027

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX