从 Python 中的字符串创建列表

Create a List from a string in Python

我是 pyhon 的新手,我找不到将我的字符串操作成列表的方法。

我读了一个包含这个确切输出的文件(它是 csv 文件的一个参数):

[{a,b,c},{aa,bb,cc}]

我想格式化该字符串以获得包含 2 个对象的数组:

[{
    val_a: 'a',
    val_b: 'b',
    val_c: 'c'
},
{
    val_a: 'aa',
    val_b: 'bb',
    val_c: 'cc'
}]

有没有简单的方法可以做到这一点?

所以,首先,您在描述中所说的“对象”实际上是对象的 JavaScript-like 定义,在其他语言中并不常用。这种较旧的 JavaScript 对象风格,没有实际的 class 声明来构造具有 pre-defined 组属性和方法的对象,只是一个 string-keyed 散列 table,你可以在事后将 object-oriented 特征完全固定到。它接近 Python 的 dict 语法(其中 dict 是一个完全通用的散列 table,但无法在 class 之后附加额外的行为事实上),但如果你打算用一组一致的属性制作实际的 objects ,它仍然不受欢迎;使用普通的 dicts 并不能清楚地表明预期存在哪些键(也许下一个 dict 有一个额外的键,而后一个缺少一个键),并且 Python 使得没有真正努力优化大量纯 dicts,这些 dicts 恰好都是用同一组键定义的(大多数 Python 对象 实现的一个底层 dict 来存储它们的属性,并且他们优化了 dict 以减少该用例中的内存使用,但它依赖于 class 的存在 dict存储共享密钥以供将来实例检索 dicts).

执行此操作的最简单方法Python通常是使用 namedtuple(轻量级 class 定义具有一组固定键的轻量级 immutable 对象; 除非手动定义的 class 显式使用 per-instance 属性的 __slots__ 到 opt-out dict,否则它实际上比等效的手动定义的 class 内存使用率更低]):

import json
import re
from collections import namedtuple

MyClass = namedtuple('MyClass', 'val_a val_b val_c')  # Defined once at top-level of the file for
                                                      # reuse; makes a lightweight tuple subclass
mystr = '[{a,b,c},{aa,bb,cc}]'

# Make string legal JSON (needs tweaking based on real data)
mystr = mystr.replace('{', '[').replace('}', ']')  # Sets are unordered, we don't want to lose ordering by converting to set
quoted_str = re.sub(r'(\w+)', r'""', mystr)

# Decode from JSON to Python types
orig_data = json.loads(quoted_str)

# Convert from list of three-lists to list of MyClass instances
obj_data = [MyClass(*datagrp) for datagrp in orig_data]

print(obj_data)

# If you'd like it to look like a dict, you can expand from memory-efficient namedtuples to less efficient dicts as needed
print([obj._asdict() for obj in obj_data])

Try it online!

在 Python 3.8 及更高版本上,生成输出:

[MyClass(val_a='a', val_b='b', val_c='c'), MyClass(val_a='aa', val_b='bb', val_c='cc')]
[{'val_a': 'a', 'val_b': 'b', 'val_c': 'c'}, {'val_a': 'aa', 'val_b': 'bb', 'val_c': 'cc'}]

3.8 之前,你会得到最终输出的结果 OrderedDicts,而不是 dict(直到 3.7,dict 不能保证保留键顺序,所以他们最初使用 OrderedDict 来这样做),但是如果您不需要输出中键的可靠排序,请将最后一行更改为:

print([dict(obj._asdict()) for obj in obj_data])

会这样做。

如果您出于某种原因不想要 namedtuples(通常是因为您不希望对象表现得像 tuples,具有长度和可迭代性,或者您想要它们mutable),你可以用the dataclasses module定义一个类似的轻量级class,只是little更冗长:

from dataclasses import dataclass, asdict

@dataclass  # On 3.10+, use @dataclass(slots=True) if you want reduced memory per instance and no auto-vivification if you assign to non-existent attribute
class MyClass:
    val_a: str
    val_b: str
    val_c: str

并且它定义了您需要的所有常用内容,使用之前的其余代码,唯一的变化是将 obj._asdict() 更改为 asdict(obj)dataclasses 使其成为top-level dataclass 模块的函数而不是类型上的方法以避免污染 class 的命名空间)。你永远不需要 dict() 包装 namedtuple 需要 pre-3.8,因为:

  1. dataclasses 仅在 3.7 中引入(其中有 insertion-ordered plain dict),并且
  2. 因此,它从一开始就默认为dict