我需要解析一些文本文件,为文本中遇到的各种实体创建对象,并将它们放在某些数据结构(例如列表)中以供进一步处理。文本示例:
laptop
17" dell, weight: 12 lb
desktop
24" hp
我事先知道文本中可能存在哪些实体,以及它们应该具有哪些属性。在这个例子中,我已经定义了笔记本电脑和桌面类(可能是类计算机的子类)。解析器只需要创建对象laptop('dell',17,12)和dekstop('hp',24)。
如果我遵循这条路线,我需要从字符串中检索类名,并创建这些类的对象。这是Pythonic的做事方式吗?如果是这样,最好的方法是什么(使用Python 3.1)?如果没有,我该怎么做呢?
谢谢!
什么
答案 0 :(得分:11)
如果在computers.py
中定义了类,那么你可以做
import computers
getattr( computers, "Laptop" )( <params> )
实例化computers.Laptop
。如果它们在您运行代码的同一文件中定义(以便它们是全局变量),则可以执行
globals()[ "Laptop" ]
但这不那么优雅;将它们放在一个单独的范围内会更好。
或者,如果你想要一个更强大的映射(比如你想要“Nettop”,“Lapbook”和“Laptop”都要实例化Laptop
),你可以保持字符串到它们相应的构造函数的映射,用那个:
mapping = { "Laptop": Laptop, "Nettop": Laptop, ... }
mapping[ "Laptop" ]()
答案 1 :(得分:5)
您可以使用以下代码
按名称创建类的实例obj = globals()[classname]()
其中classname
是一个字符串
答案 2 :(得分:4)
从技术上讲,你所要求的(或至少每个人都在解释它的方式)并不是很好的做法,特别是如果你可能从不受信任的来源那里获取意见(记住,任何来源其他通常应该认为不是自己不受信任!)。你应该明确地将这些事情列入白名单,因为有人可能会触发一个函数的执行或者你不想要的属性的创建你真正不想要的属性......
你可以做的是这样的事情(这当然是非常不完整的,但应该给你一般的想法):
class Laptop(object):
pass
class Desktop(object):
pass
possible_classes = {
"laptop": Laptop,
"desktop": Desktop,
}
new_object = possible_classes[identifier_string](propA, propB, propC, ...)
然后只需将每种新对象的映射添加到possible_classes dict。
答案 3 :(得分:1)
我认为基于检查的方法可能非常脆弱并且不易改变。如果您想使用其他模块中的类,该怎么办?
为什么不是对象工厂?它可以是一个简单的函数或类。
示例:
class ComputerFactory:
def __init__(self):
self._classes = {}
def register(moniker, creator):
"""Moniker is a name for the class.
Creator is a callable that creates the object
for the moniker.
"""
self._classes[moniker] = creator
def create(moniker, *args, **kwargs):
return self._classes[moniker](*args, **kwargs)
# Example usage
fac = ComputerFactory()
# Register constructor
fac.register("laptop", Laptop) # Laptop class is also a callable (the constructor)
# Register construction proxy
def sony_laptop_builder(make):
return Laptop("Sony")
fac.register("laptop", sony_laptop_builder)
答案 4 :(得分:0)
不确定python代码的语法,但这是你想要的吗?
for item in parsedString:
if item == "laptop":
laptops.add(laptop()) #laptops is a list of laptops you
#have encountered so far in your list
# add the next elements to your laptop instance
if item == "desktop":
# code for desktop...