Python 在类中查找属性的类型
我想确定类中属性的类型。我正在使用Python 在类中查找属性的类型,python,google-app-engine,Python,Google App Engine,我想确定类中属性的类型。我正在使用setattr设置该值,我想检查预期的类型,以便在调用setattr之前正确转换字符串值 如何在python中实现这一点 编辑1- 根据到目前为止的答案提供的一些附加信息: 我只知道我想要类型的属性的名称,下面是一些代码: def populate_object_properties(values_as_strings, object_to_populate,
setattr
设置该值,我想检查预期的类型,以便在调用setattr
之前正确转换字符串值
如何在python中实现这一点
编辑1-
根据到目前为止的答案提供的一些附加信息:
我只知道我想要类型的属性的名称,下面是一些代码:
def populate_object_properties(values_as_strings,
object_to_populate,
properties_to_populate):
for k in properties_to_populate:
value = values_as_strings.get(k)
if value:
setattr(object_to_populate, k, value)
else:
setattr(object_to_populate, k, None)
在调用setattr
之前,我希望能够测试value
是否是正确的类型
编辑2-我需要验证类型的原因是,我使用Google AppEngine的db.Model作为要填充的
对象的基本类型,它不喜欢将字符串放入int
类型。我试图让问题尽可能简单,但也许这条信息会改变人们的回答方式。(?检查a.\uuuuu类
,或者如果你想检查类型是否如预期的那样,可能是isinstance(obj,class)
>>> a = 1
>>> a.__class__
<type 'int'>
>>> isinstance(a, int)
True
如果您的唯一目标是设置一个属性,如果给定的参数可以表示为整数,那么您还可以使用以下内容:
def convert(x):
try:
return int(x) # Or do something else with it
except ValueError, e:
print "The value", x, "is not an integer"
raise
convert(123) # => 123
convert("123") # => 123
convert("abc") # => ValueError
问题中的一些额外文本让我想到了改变:
value = values_as_strings.get(k)
到
导致:
try:
setattr(object_to_populate, k, int( values_as_strings.get(k) ))
except:
setattr(object_to_populate, k, None)
您可以使用type(a.v)
来检查它,但是如果它没有默认值,那么它也可以是无或未定义的
>> class A:
>> v=10
>> u=None
>> a=A()
>> print type(a.v)
<type 'int'>
>> print type(a.u)
<type 'NoneType'>
>> print type(a.w)
AttributeError
>> a.w=20
>> print type(a.w)
<type 'int'>
或者使用extraneon建议的isinstance,也一样。因为python在这种情况下不进行类型检查,所以您必须手动实现此功能(或者使用现有库;请参阅Alex Martellis的答案)
一种方法:通过isinstance
检查该值是否为所需类型的实例
这是你的代码的一个修改版本,我从
# 'pdict' is a dictionary of property-value pairs { 'property' : 'value', ... }
def populate_object_properties(object_to_populate, pdict):
for p, v in pdict.items():
setattr(object_to_populate, p, v)
然后我们添加类型检查,对于这个例子,我们只想用与当前使用的值类型相同的对象填充对象的属性
def populate_object_properties(object_to_populate, pdict):
for p, v in pdict.items():
current_value = getattr(p, v, None)
klass = type(current_value)
# allow setting the attribute, when
#
# - the attribute did not exist before,
# - the attribute value was 'None',
# - the value to be inserted is of the same type as the current value
if not current_value or isinstance(v, klass):
setattr(object_to_populate, p, v)
有几个旁注:
# why don't you just take two parameters? 1) the object, 2) a dict with
# property-value pairs?
def populate_object_properties(values_as_strings,
object_to_populate,
properties_to_populate):
for k in properties_to_populate:
value = values_as_strings.get(k)
# here you are branching on 'value', just to populate
# property 'k' with whah might have been 'value' before ..
# it's nothing serious, though, just a bit too much to read
if value:
setattr(object_to_populate, k, value)
else:
setattr(object_to_populate, k, None)
# you could simply write:
# setattr(object_to_populate, k, value)
进一步阅读:
您似乎误解了Python(语言)的设计方式。属性没有先验类型(语言是动态类型化的),因此,在大多数情况下,在设置属性时尝试显式强制属性是没有意义的。通常,Python类(或其实例)不包含关于它“期望”任何给定属性具有什么类型的信息,因为它没有此类属性“期望”
当您需要对这些元数据进行编码时,而不是“滚动您自己的元数据”,您可以使用现有的第三方扩展,如Enthough的——在Traits中,除其他功能外,您可以获得:
验证:特征属性的类型
显式声明。类型为
在代码中很明显,并且只有值
满足程序员指定集合的
标准(即特征
定义)可以分配给该
属性。请注意,默认值
不需要满足为定义的标准
赋值
由于显式类型检查是不带Pythic的,所以只需在int()/Cux>中包装该值。然后,如果该值(无论它是什么)都可以强制转换成<代码> int <代码>,它将是。如果它不能被强制转换成<代码> int <代码>,那么无论如何都需要抛出一个错误(它将自动执行)。
这是“三思而后行”和“请求原谅比请求许可更容易”之间根本区别的一个例子。Python不是“三思而后行”语言,它是一种“请求原谅比请求许可更容易”语言。:
在AppEngine中,每个模型都有一个属性()
class方法,该方法返回您在模型中声明的属性的dict。您可以使用它来检查模型对每个属性所期望的类型:
def populate_object_properties(values_as_strings,
object_to_populate,
properties_to_populate):
model_properties = object_to_populate.properties()
for k in properties_to_populate:
value = values_as_strings.get(k)
model_property = model_properties.get(k)
if value:
if isinstance(model_property, StringProperty):
setattr(object_to_populate, k, str(value))
elif isinstance(model_property, IntegerProperty):
setattr(object_to_populate, k, int(value))
else:
setattr(object_to_populate, k, None)
通过组合使用dir()
、eval()
和type()
方法,可以获得类的属性名称和类型,如下所示:
def GetFieldNamesAndTypes(self):
attributes = dir(self)
typenames = [eval("type(self." + dir(self)[i] + ").__name__") for i in range(len(dir(self)))]
return [attributes[i] + ":" + typenames[i] for i in range(len(attributes))]
isinstance()根据类型模块的库参考手册中的注释,似乎是首选方法。我的问题没有应该的那么清楚,我已经更新了。我的问题没有应该的那么清楚,我已经更新了。为什么要这样做?只需设置值。如果任何对象的实际类型与类型不兼容他期望方法,但它会崩溃。为什么在使用duck类型的语言中浪费这么多的处理时间在类型检查上呢?我使用的是Google AppEngine的db.model,并且我的db.model类的属性被强制为一个类型。因此,如果我尝试将Int属性设置为字符串,它会抛出一个异常。你可能想看看db.djangoforms:我使用的是Google AppEngine的db.model和我的db.model类的属性被强制为一个类型。因此,如果我尝试将Int属性设置为字符串,它会抛出一个异常。那么问题是,为什么要尝试将Int属性设置为字符串?您的应用程序应该知道它接收的是什么类型(例如,来自用户),以及它应该转换为什么类型,因此转换很简单(例如,如果要进行字符串到int的转换,则转换为y=int(x)
)。我使用了一个函数,这样我就可以传入request对象、db.model对象以及我想要从request对象移动到db.model中的属性列表。这样,我就可以从任何web处理程序调用它,使用任何db.model,只需更改属性列表,我想这会减少大量的复制&粘贴代码。所以我需要在运行时弄清楚我处理的是什么类型,并从请求对象转换字符串。
# why don't you just take two parameters? 1) the object, 2) a dict with
# property-value pairs?
def populate_object_properties(values_as_strings,
object_to_populate,
properties_to_populate):
for k in properties_to_populate:
value = values_as_strings.get(k)
# here you are branching on 'value', just to populate
# property 'k' with whah might have been 'value' before ..
# it's nothing serious, though, just a bit too much to read
if value:
setattr(object_to_populate, k, value)
else:
setattr(object_to_populate, k, None)
# you could simply write:
# setattr(object_to_populate, k, value)
def populate_object_properties(values_as_strings,
object_to_populate,
properties_to_populate):
model_properties = object_to_populate.properties()
for k in properties_to_populate:
value = values_as_strings.get(k)
model_property = model_properties.get(k)
if value:
if isinstance(model_property, StringProperty):
setattr(object_to_populate, k, str(value))
elif isinstance(model_property, IntegerProperty):
setattr(object_to_populate, k, int(value))
else:
setattr(object_to_populate, k, None)
def GetFieldNamesAndTypes(self):
attributes = dir(self)
typenames = [eval("type(self." + dir(self)[i] + ").__name__") for i in range(len(dir(self)))]
return [attributes[i] + ":" + typenames[i] for i in range(len(attributes))]