我希望能够获取一个动态创建的字符串,比如“Pigeon”,并在运行时确定 Google App Engine 是否在该项目中定义了一个名为“Pigeon”的模型类。如果“Pigeon”是现有模型类的名称,那么我想获得对如此定义的 Pigeon 类的引用。
另外,我根本不想使用 eval,因为在这种情况下,动态字符串“Pigeon”来自外部。
我希望能够获取一个动态创建的字符串,比如“Pigeon”,并在运行时确定 Google App Engine 是否在该项目中定义了一个名为“Pigeon”的模型类。如果“Pigeon”是现有模型类的名称,那么我想获得对如此定义的 Pigeon 类的引用。
另外,我根本不想使用 eval,因为在这种情况下,动态字符串“Pigeon”来自外部。
您可以尝试,尽管可能非常非常糟糕的做法:
def get_class_instance(nm) :
try :
return eval(nm+'()')
except :
return None
另外,为了更安全,你可以给 eval 一个本地哈希:eval(nm+'()', {'Pigeon':pigeon})
我不确定这是否可行,它肯定有一个问题:如果有一个名为 value of 的函数nm
,它将返回:
def Pigeon() :
return "Pigeon"
print(get_class_instance('Pigeon')) # >> 'Pigeon'
编辑:如果您知道模块,另一种方法可能是(未经测试):(
对不起,我一直忘记它不是 obj.hasattr,它的 hasattr(obj)!)
import models as m
def get_class_instance(nm) :
if hasattr(m, nm) :
return getattr(m, nm)()
else : return None
编辑2:是的,它确实有效!哇!
实际上,通过查看源代码和互联网,我发现了一个似乎符合要求的未记录方法。
from google.appengine.ext import db
key = "ModelObject" #This is a dynamically generated string
klass = db.class_for_kind(key)
如果类不存在,此方法将抛出描述性异常,因此如果键字符串来自外部,您可能应该捕获它。
有两种相当简单的方法可以做到这一点,而不依赖于内部细节:
使用 google.appengine.api.datastore API,如下所示:
from google.appengine.api import datastore
q = datastore.Query('EntityType')
if q.get(1):
print "EntityType exists!"
另一种选择是使用 db.Expando 类:
def GetEntityClass(entity_type):
class Entity(db.Expando):
@classmethod
def kind(cls):
return entity_type
return Entity
cls = GetEntityClass('EntityType')
if cls.all().get():
print "EntityType exists!"
后者的优点是您可以使用 GetEntityClass 为任何实体类型生成 Expando 类,并以与普通类相同的方式与之交互。