怎么才能在 Python 中输出一个 key 不带引号的字典呢 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
mylifcc
V2EX    Python

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

  •  
  •   mylifcc 2022-09-01 16:19:58 +08:00 4618 次点击
    这是一个创建于 1137 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    比如

    { city: "beijing", device: "Iphone" } 
    37 条回复    2022-12-30 16:18:55 +08:00
    JamesMackerel
        1
    JamesMackerel  
       2022-09-01 16:21:55 +08:00 via iPhone
    可以先序列化再用正则替换一下?
    westoy
        2
    westoy  
       2022-09-01 16:25:21 +08:00
    js object

    popen node.js console.log(json)
    Hstar
        3
    Hstar  
       2022-09-01 16:30:15 +08:00
    这种格式只存在于代码中,city 和 device 是个变量引用。

    输出做不到,非标格式。
    caqiko
        4
    caqiko  
       2022-09-01 16:32:33 +08:00 via Android
    为什么要这样输出?这是 js 里的对象
    yangg
        5
    yangg  
       2022-09-01 16:34:02 +08:00
    yaml.dump ?
    NessajCN
        6
    NessajCN  
       2022-09-01 16:41:00 +08:00
    print("{")
    for key in dict:
    print(f'{key}:"{dict[key]",')
    print("}")
    ChrisFreeMan
        8
    ChrisFreeMan  
       2022-09-01 16:41:53 +08:00
    找下有没有 json5 的库,json5 就是类似这种格式
    mylifcc
        9
    mylifcc  
    OP
       2022-09-01 17:23:58 +08:00
    @caqiko 源自一个笔试题,不知道怎么生成这种结构,也没查出来
    mylifcc
        10
    mylifcc  
    OP
       2022-09-01 17:24:19 +08:00
    @lisongeee
    @ChrisFreeMan 感谢大佬
    lanlanye
        11
    lanlanye  
       2022-09-01 17:28:23 +08:00
    笔试题的话自己写个遍历打印不就好了吗?

    >>> def pprint(dict_):
    ... print("{")
    ... for k, v in dict_.items():
    ... print(f' {k}: "{v}",')
    ... print("}")
    ...
    >>> d = {'city': 'Beijing', 'device': 'iPhone'}
    >>> pprint(d)
    {
    city: "Beijing",
    device: "iPhone",
    }
    mylifcc
        12
    mylifcc  
    OP
       2022-09-01 17:49:40 +08:00
    @lanlanye 主要是想了解怎么用 python 生成这种格式和这种格式是个啥
    huangzhe8263
        13
    huangzhe8263  
       2022-09-01 18:22:16 +08:00
    这就不是 python 里的标准格式吧
    llsquaer
        14
    llsquaer  
       2022-09-01 18:52:09 +08:00
    正则替换.
    dic_str={'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}
    result=re.sub(r"'(.*?)': '(.*?)'" , "1\:\"\2\"", dic_str )
    print(result)
    ysc3839
        15
    ysc3839  
       2022-09-01 18:59:09 +08:00 via Android
    自己写个遍历输出就完事了
    @mylifcc 是 Javascript(不是 JSON)的 object 格式
    ysc3839
        16
    ysc3839  
       2022-09-01 19:09:32 +08:00
    一句话的写法:
    '{' + ', '.join((f'{k}: "{v}"' for k, v in t.items())) + '}'
    没有考虑值中含有引号的转移,可以看规则自己改成 v.replace('"', '\\"')
    wxf666
        17
    wxf666  
       2022-09-01 19:12:12 +08:00
    @JamesMackerel
    @llsquaer

    正则替换,要考虑不少东西的。比如:

    1. 键值对里的值,不一定全是字符串,还可以是数字、列表、字典等

    2. 就算是『"(.+?)"\s*:』,也有可能是『'"fake_key": value'』,序列化成『"\"fake_key\": value"』,然后被替换成『"\fake_key\": value 』了
    mylifcc
        18
    mylifcc  
    OP
       2022-09-01 19:12:36 +08:00
    @ysc3839 了解了
    wxf666
        19
    wxf666  
       2022-09-01 19:17:40 +08:00
    @JamesMackerel
    @llsquaer

    写漏了

    然后被替换成『"\fake_key\": value"』了
    mmm159357456
        20
    mmm159357456  
       2022-09-01 20:03:39 +08:00
    不是啊,OP 要的是字典啊,你们推荐的全转换成 string 了
    wxf666
        21
    wxf666  
       2022-09-01 20:21:36 +08:00
    @mylifcc 对了,若是 key 包含 " \ : <换行> 等字符,你打算咋表示呢?

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

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

    https://imgur.com/a/PkZDCYZ
    LindsayZhou
        26
    LindsayZhou  
       2022-09-01 21:49:43 +08:00   1
    Python 的 JSONEncoder 全部是用 Python 写的,没用 C
    继承过来重新写一下就行了吧: https://github.com/python/cpython/blob/2ecc195498f3b1256fabc2b66e0d8f6d671fa1d7/Lib/json/encoder.py#L36
    mylifcc
        27
    mylifcc  
    OP
       2022-09-01 22:03:34 +08:00
    @LindsayZhou
    @thinkershare 主要是想知道这是个什么东西,因为这个东西看起来不像是语法错误,但我又说不上是什么,也没想着他是什么指定的格式,就想知道什么地方会生成它,然后什么地方会用到
    wxf666
        28
    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
        29
    JamesMackerel  
       2022-09-01 22:43:49 +08:00 via iPhone
    @wxf666 参考 https://blog.dragonslayer.me/archives/115

    虽然性能很低就是了(感觉)。如果要性能,应该可以根据语义去做 pretty print ,感觉是一个 json serializer ?不知道好做不好做。
    wxf666
        30
    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\\\":,}:\\",
      },
    ]
    wf666
        31
    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
        32
    mylifcc  
    OP
       2022-09-02 01:10:33 +08:00
    @wxf666 牛的
    js8510
        33
    js8510  
       2022-09-02 01:59:34 +08:00
    ```
    >>> class Key:
    ... def __repr__(self):
    ... return "Key"
    ...
    >>>
    >>>
    >>>
    >>> m={Key(), 1}
    >>> m
    {1, Key}
    ```

    这样不就好了??
    gongshuiwen
        34
    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
        35
    xiaochun41  
       2022-09-02 10:44:07 +08:00
    楼上和楼上的楼上的分析可以借鉴,python 里面字典打印的时候调用的是 dict 的这个方法 __repr__ ,单说 key 的话 也是调用的 key 的类型对应的 __repr__ 方法。
    所以就是两个思路:
    1 . 继承 dict ,重新定义一个自己的字典类,重新实现 __repr__
    2 . 针对特定的 key ,重新实现 key 的 __repr__方法
    pjxxcc
        36
    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
        37
    stonesirsir  
       2022-12-30 16:18:55 +08:00
    遍历字典,然后用字符串打印出来吧
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     866 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 22:23 PVG 06:23 LAX 15:23 JFK 18:23
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86