字符串中的字典取出value值(eval 使用及介绍)

eval:eval() 函数用来执行一个字符串表达式,并返回表达式的原始值。

例如:有个字符串 A="{'value': 'hello'}"

想要输出该字符串的value值,应该怎么办。

如果仅仅是一个字典的话直接取dict['key']就可以轻松取出来,但是在字符串中我们就必须想办法把字符串转化成字典。这时候eval函数就该闪亮登场了。

代码如下:

>>> A="{'value': 'hello'}"
>>> B=eval(A)
>>> B
{'value': 'hello'}

此时在字典情况下想取出值就轻而易举了!

>>> B['value']

Python eval 函数妙用

eval

  功能:将字符串str当成有效的表达式来求值并返回计算结果。

  语法: eval(source[, globals[, locals]]) -> value

  参数:

    source:一个Python表达式或函数compile()返回的代码对象

    globals:可选。必须是dictionary

    locals:可选。任意map对象

  实例展示:

可以把list,tuple,dict和string相互转化。
#################################################
字符串转换成列表
>>>a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"
>>>type(a)
<type 'str'>
>>> b = eval(a)
>>> print b
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]]
>>> type(b)
<type 'list'>
#################################################
字符串转换成字典
>>> a = "{1: 'a', 2: 'b'}"
>>> type(a)
<type 'str'>
>>> b = eval(a)
>>> print b
{1: 'a', 2: 'b'}
>>> type(b)
<type 'dict'>
#################################################
字符串转换成元组
>>> a = "([1,2], [3,4], [5,6], [7,8], (9,0))"
>>> type(a)
<type 'str'>
>>> b = eval(a)
>>> print b
([1, 2], [3, 4], [5, 6], [7, 8], (9, 0))
>>> type(b)
<type 'tuple'>

eval()使用原因:

1)在编译语言里要动态地产生代码,基本上是不可能的,但动态语言是可以,意味着软件已经部署到服务器上了,但只要作很少的更改,只好直接修改这部分的代码,就可立即实现变化,不用整个软件重新加载。

2)在machin learning里根据用户使用这个软件频率,以及方式,可动态地修改代码,适应用户的变化。

 

example:

a=1
g={'a':20}
eval("a+1",g)

返回21

#test eval() and locals()
x = 1
y = 1
num1 = eval("x+y")
print (num1)

def g():    
    x = 2    
    y = 2  
    num3 = eval("x+y")    
    print (num3)        
    num2 = eval("x+y",globals())   
    #num2 = eval("x+y",globals(),locals())    
    print (num2)
    
g()

print locals()["x"]
print locals()["y"] 
print globals()["x"]
print globals()["y"]
 

num1的值是2;num3的值也很好理解,是4;num2的值呢?由于提供了globals()参数,那么首先应当找全局的x和y值,也就是都为1,那么显而易见,num2的值也是2。如果注释掉该句,执行下面一句呢?根据第3)点可知,结果为4

 

locals()对象的值不能修改,globals()对象的值可以修改


#test globals() and locals()

z=0
def f():    
    z = 1    
    print (locals())        
    locals()["z"] = 2    
    print (locals())      
f() 
globals()["z"] = 2
print (z)

可以得出,两个print (locals())的结果是一样的,说明没有修改成功。而print (z)的值是2,说明修改成功了

 

eval有安全性问题,比如用户恶意输入就会获得当前目录文件

eval("__import__('os').system('dir')")
>>> import os
>>> 'os' in globals()
True
>>> os.system('whoami')
ap\zhail
0

 

怎么避免安全问题?

1、自行写检查函数;

2、使用ast.literal_eval

<think>我们被要字符串转换为字典数据结构。根据引用[1]引用[2],有几种方法可以实现这个转换,具体取决于字符串的格式。 常见的字符串格式有两种: 1. 字符串是JSON格式(即符合JSON规范,键字符串都用双引号括起来)。 2. 字符串是Python字典的字面量形式(可能使用单引号或双引号,但键可以是各种Python对象,不过通常我们处理的是字符串基本类型的)。 方法: 1. 使用json模块:如果字符串是JSON格式,我们可以使用json.loads()来转换。 2. 使用eval()函数:如果字符串是Python字典的字面量形式,我们可以使用eval()。但要注意,eval()会执行任意代码,存在安全隐患,因此只应在可信的环境中使用。 3. 使用ast.literal_eval():这是一个安全的方法,可以解析字符串中的字面量(如字典、列表、数字、字符串等),不会执行任意代码,因此更安全。 根据引用[2]中的示例,他们使用了json.loads()eval()两种方法。 因此,我们推荐以下方法: - 如果字符串是JSON格式,优先使用json.loads()。 - 如果字符串是Python字典字面量,且来源可信,可以使用eval(),但更推荐使用ast.literal_eval()。 步骤: 1. 导入相应的模块(json或ast)。 2. 根据字符串的格式选择合适的方法。 示例代码: 情况1:JSON字符串 ```python import json # 假设字符串是JSON格式 json_str = '{"name": "Alice", "age": 30, "city": "New York"}' # 使用json.loads转换为字典 data_dict = json.loads(json_str) print(data_dict) ``` 情况2:Python字典字面量字符串使用单引号或双引号,但注意JSON要双引号,而Python字典字面量可以使用单引号) ```python import ast # 假设字符串是Python字典字面量 dict_str = "{'name': 'Alice', 'age': 30, 'city': 'New York'}" # 使用ast.literal_eval转换为字典 data_dict = ast.literal_eval(dict_str) print(data_dict) ``` 注意:如果字符串既不是标准的JSON格式(比如键名没有用双引号而是单引号)也不是一个完整的字典字面量,那么可能需要先进行预处理。 另外,如果字符串中包含其他类型的数据(如元组、列表等),ast.literal_eval也可以处理,但json.loads只能处理JSON支持的类型(字典、列表、字符串、数字、布尔null)。 因此,一般情况下,如果字符串是JSON格式,用json.loads;如果是Python字面量,用ast.literal_eval(更安全)。 如果字符串格式不确定,可以尝试先用json.loads,如果失败再用ast.literal_eval,但要注意json.loads要严格的双引号,而ast.literal_eval可以处理单引号。 但是,请注意:如果字符串中包含非字面量的表达式(如函数调用、变量等),ast.literal_eval会报错,而eval虽然可以执行,但存在安全风险。 总结:优先使用json.loads,如果字符串是单引号或者不是严格JSON,则使用ast.literal_eval。 下面是一个综合处理的函数: ```python import json import ast def str_to_dict(s): try: # 先尝试用json.loads return json.loads(s) except json.JSONDecodeError: try: # 如果失败,尝试用ast.literal_eval return ast.literal_eval(s) except (ValueError, SyntaxError): # 如果都不行,返回None或者抛出异常 return None # 测试 json_str = '{"name": "Alice", "age": 30}' dict_str = "{'name': 'Bob', 'age': 25}" print(str_to_dict(json_str)) # 输出: {'name': 'Alice', 'age': 30} print(str_to_dict(dict_str)) # 输出: {'name': 'Bob', 'age': 25} ``` 注意:这个函数首先尝试JSON解析,因为JSON解析更安全且快速。如果JSON解析失败(因为单引号等原因),再尝试用ast.literal_eval。如果都失败,返回None。 但是,请注意,有些字符串可能既不是JSON也不是字典字面量,比如其他格式的字符串,那么转换就会失败。 因此,在实际应用中,需要确保输入的字符串是有效的JSON或字典字面量。 根据引用[1]引用[2]的内容,我们提供了上述方法。</think>在编程中将字符串转换为字典数据结构是常见需,主要取决于字符串的格式。以下是三种主流方法及其适用场景: ### 方法1:使用 `json` 模块(推荐JSON格式) 当字符串是**标准JSON格式**(键名用双引号包裹)时: ```python import json # JSON格式字符串(注意双引号) json_str = '{"name": "Alice", "age": 30, "city": "Paris"}' # 转换为字典 data_dict = json.loads(json_str) print(type(data_dict)) # <class 'dict'> print(data_dict["city"]) # 输出: Paris ``` > ✅ 优点:安全高效,支持复杂嵌套结构 > ❌ 要:必须严格符合JSON规范(如双引号) ### 方法2:使用 `ast.literal_eval`(推荐Python字典格式) 当字符串是**Python字典字面量**(使用单引号)时: ```python import ast # Python字典格式字符串(单引号) dict_str = "{'name': 'Bob', 'age': 25, 'skills': ['Python', 'SQL']}" # 安全转换(避免eval的安全风险) data_dict = ast.literal_eval(dict_str) print(type(data_dict)) # <class 'dict'> print(data_dict["skills"][0]) # 输出: Python ``` > ✅ 优点:安全解析Python字面量,支持元组/列表等复杂类型 > ❗ 注意:不能解析含函数/表达式的字符串 ### 方法3:使用 `eval`(仅限可信数据源) ```python # 仅适用于完全可信的字符串 dict_str = "{'company': 'Google', 'stock': 2800}" data_dict = eval(dict_str) # 潜在安全风险! ``` > ⚠️ 警告:会执行任意代码,仅用于100%可信的本地数据[^2] ### 格式兼容性处理 当不确定字符串格式时,可组合处理: ```python import json, ast def safe_str_to_dict(s): try: return json.loads(s) # 先尝试JSON解析 except json.JSONDecodeError: return ast.literal_eval(s) # 失败则尝试Python字面量 # 测试不同格式 print(safe_str_to_dict('{"key":"value"}')) # JSON print(safe_str_to_dict("{'key':'value'}")) # Python字典 ``` ### 注意事项 1. **引号规范**:JSON必须用双引号,Python字典可用单/双引号 2. **安全优先**:永远优先使用 `json` 或 `ast.literal_eval` 而非 `eval` 3. **数据清洗**:非标准字符串需预处理(如去除换行符、统一引号) > 通过文件读取JSON数据时,可直接用 `json.load()`: > ```python > with open('data.json') as f: > data_dict = json.load(f) # 直接获得字典 > ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值