从 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 ,它仍然不受欢迎;使用普通的 dict
s 并不能清楚地表明预期存在哪些键(也许下一个 dict
有一个额外的键,而后一个缺少一个键),并且 Python 使得没有真正努力优化大量纯 dict
s,这些 dict
s 恰好都是用同一组键定义的(大多数 Python 对象 是 实现的一个底层 dict
来存储它们的属性,并且他们优化了 dict
以减少该用例中的内存使用,但它依赖于 class 的存在 dict
存储共享密钥以供将来实例检索 dict
s).
执行此操作的最简单方法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])
在 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 之前,你会得到最终输出的结果 OrderedDict
s,而不是 dict
(直到 3.7,dict
不能保证保留键顺序,所以他们最初使用 OrderedDict
来这样做),但是如果您不需要输出中键的可靠排序,请将最后一行更改为:
print([dict(obj._asdict()) for obj in obj_data])
会这样做。
如果您出于某种原因不想要 namedtuple
s(通常是因为您不希望对象表现得像 tuple
s,具有长度和可迭代性,或者您想要它们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,因为:
dataclasses
仅在 3.7 中引入(其中有 insertion-ordered plain dict
),并且
- 因此,它从一开始就默认为
dict
我是 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 ,它仍然不受欢迎;使用普通的 dict
s 并不能清楚地表明预期存在哪些键(也许下一个 dict
有一个额外的键,而后一个缺少一个键),并且 Python 使得没有真正努力优化大量纯 dict
s,这些 dict
s 恰好都是用同一组键定义的(大多数 Python 对象 是 实现的一个底层 dict
来存储它们的属性,并且他们优化了 dict
以减少该用例中的内存使用,但它依赖于 class 的存在 dict
存储共享密钥以供将来实例检索 dict
s).
执行此操作的最简单方法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])
在 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 之前,你会得到最终输出的结果 OrderedDict
s,而不是 dict
(直到 3.7,dict
不能保证保留键顺序,所以他们最初使用 OrderedDict
来这样做),但是如果您不需要输出中键的可靠排序,请将最后一行更改为:
print([dict(obj._asdict()) for obj in obj_data])
会这样做。
如果您出于某种原因不想要 namedtuple
s(通常是因为您不希望对象表现得像 tuple
s,具有长度和可迭代性,或者您想要它们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,因为:
dataclasses
仅在 3.7 中引入(其中有 insertion-ordered plaindict
),并且- 因此,它从一开始就默认为
dict