【问题标题】:Python: get type and convert to this typePython:获取类型并转换为这种类型
【发布时间】:2017-03-07 10:09:01
【问题描述】:

我是 Python 新手。我有一个包含一些字段的对象,并且我有一个字段名称和值的列表,但是此列表中的所有值都是字符串。我需要找到一个对象字段并分配值。我已经知道如何找到该字段。但是,我遇到了类型转换的问题。

例如:

class SomeEntity:

    def __init__(self):
        self.id = 0
        self.name = ""
        self.some_attr = {}


 def applyValues(entity, list_of_values):
     for key, value in list_of_values:
         if hasattr(entity, key):
             setattr(entity, key, value) # !!! here is the problem to convert to type

我需要这样的东西:

x = getattr(entity, key)
type_attr = type(x)
converted = type_attr(value)
setattr(entity, key, converted)

我该怎么做?或者我可以使用其他方式吗?

【问题讨论】:

  • 这看起来像是众多问题之一的副本,这些问题的公认答案是“改用字典”。
  • 我不能用字典代替类,因为我有这个类是从 protobuf 生成的

标签: python type-conversion


【解决方案1】:

如果值字符串是有效的 Python 文字,您可以使用 ast.literal_eval 将这些字符串安全地评估为 Python 对象。

import ast

class SomeEntity:
    def __init__(self):
        self.id = 0
        self.name = ""
        self.some_attr = {}

def apply_values(entity, list_of_values):
    for key, value in list_of_values:
        if hasattr(entity, key):
            converted = ast.literal_eval(value)
            setattr(entity, key, converted)

entity = SomeEntity()

attr_list = [
    ('id', '42'), 
    ('name', '"the entity"'), 
    ('some_attr', '{"one": 1, "two": 2}'),
]
apply_values(entity, attr_list)

x = entity.id
print(x, type(x))
x = entity.name
print(x, type(x))
x = entity.some_attr
print(x, type(x))

输出

42 <class 'int'>
the entity <class 'str'>
{'one': 1, 'two': 2} <class 'dict'>

请注意,我们也可以将属性名称和值字符串放入dict

attr_dict = {
    'id': '42', 
    'name': '"the entity"', 
    'some_attr': '{"one": 1, "two": 2}'
}

apply_values(entity, attr_dict.items())

正如 Alfe 在 cmets 中提到的,该代码忽略了实体属性的类型。这是一个将现有属性类型考虑在内的修改版本。

import ast

class SomeEntity:
    def __init__(self):
        self.id = 0
        self.name = ""
        self.some_attr = {}
        self.level = 0.0

def apply_values(entity, list_of_values):
    for key, value in list_of_values:
        if hasattr(entity, key):
            type_attr = type(getattr(entity, key))
            converted = type_attr(ast.literal_eval(value))
            setattr(entity, key, converted)

entity = SomeEntity()

attr_dict = {
    'id': '42', 
    'name': '"the entity"', 
    'some_attr': '{"one": 1, "two": 2}',
    'level': '5',
}

apply_values(entity, attr_dict.items())

for k, v in entity.__dict__.items():
    print(repr(k), repr(v), type(v))

输出

'id' 42 <class 'int'>
'name' 'the entity' <class 'str'>
'some_attr' {'one': 1, 'two': 2} <class 'dict'>
'level' 5.0 <class 'float'>

【讨论】:

  • 这会将int 用于输入"5" 放入一个应该包含float 的变量中。但我想在大多数情况下这不会造成任何问题。 ⁺¹ 使用 ast.literal_eval(),即使它显然超出了 OP 的水平。
  • 非常感谢!它非常适合我
【解决方案2】:

修复了 Garjy 解决方案中的大量错误:

converted = eval(value)

也许您想在之后将其显式转换为正确的类型:

converted type(getattr(entity, key))(eval(value))

完全合二为一:

setattr(entity, key, type(getattr(entity, key))(eval(value)))

【讨论】:

    猜你喜欢
    • 2018-11-04
    • 2012-03-28
    • 2013-03-28
    • 2020-12-02
    • 2017-11-17
    • 2011-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多