推荐学习书目
› 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 · Sep 1, 2022 · 5640 views
    This topic created in 1531 days ago, the information mentioned may be changed or developed.

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

    比如

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

    popen node.js console.log(json)
    Hstar
    Hstar
    Sep 1, 2022
    3
    这种格式只存在于代码中,city 和 device 是个变量引用。

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

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

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

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

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

    写漏了

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

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

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

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

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

    这样不就好了??
    gongshuiwen
    gongshuiwen
    Sep 2, 2022
    34
    使用非字符串对象作为键就会输出该格式,例如:
    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
    xiaochun41
    Sep 2, 2022
    35
    楼上和楼上的楼上的分析可以借鉴,python 里面字典打印的时候调用的是 dict 的这个方法 __repr__ ,单说 key 的话 也是调用的 key 的类型对应的 __repr__ 方法。
    所以就是两个思路:
    1 . 继承 dict ,重新定义一个自己的字典类,重新实现 __repr__
    2 . 针对特定的 key ,重新实现 key 的 __repr__方法
    pjxxcc
    pjxxcc
    Sep 2, 2022
    36
    用数字作为 key ,就不会带引号哦
    比如:
    >>> d = {1: 'yi', 'a': "A"}
    >>> d
    {1: 'yi', 'a': 'A'}
    >>> print(d)
    {1: 'yi', 'a': 'A'}
    stonesirsir
    stonesirsir
    Dec 30, 2022
    37
    遍历字典,然后用字符串打印出来吧
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   952 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 70ms · UTC 20:16 · PVG 04:16 · LAX 12:16 · JFK 15:16
    ♥ Do have faith in what you're doing.