我想确定一个类中属性的类型。我使用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)
我想在调用value
之前测试setattr
是否是正确的类型。
编辑2-我需要验证类型的原因是我使用Google AppEngine的db.Model作为object_to_populate
的基本类型,并且它不喜欢放置字符串成int
类型。我试图让问题尽可能简单,但也许这些信息会对某人的回答产生影响。(?)
答案 0 :(得分:6)
在AppEngine中,每个模型都有一个properties()
类方法,它返回您在模型中声明的属性的字典。您可以使用它来检查模型对每个属性所期望的类型:
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)
答案 1 :(得分:1)
您似乎误解了Python(语言)的设计方式。属性没有先验类型(语言是动态类型的),因此在大多数情况下,在设置属性时尝试明确强制属性没什么意义。
答案 2 :(得分:0)
如果要检查类型是否符合预期,请检查。__class__
或isinstance(obj,class)。
>>> a = 1
>>> a.__class__
<type 'int'>
>>> isinstance(a, int)
True
更重要的是你可能:
>>> b = "10"
>>> isinstance(b, str)
True
>>> isinstance(b, int)
False
>>> int(b)
10
如果您的唯一目标是设置属性,如果给定的参数可以表示为整数,您还可以使用以下内容:
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:
value = int( values_as_strings.get(k) )
except ValueError, e:
# It's not an int or string with int contents, what to do?
raise
导致:
try:
setattr(object_to_populate, k, int( values_as_strings.get(k) ))
except:
setattr(object_to_populate, k, None)
答案 3 :(得分:0)
您可以使用type(a.v)
进行检查,但如果它没有默认值,则可以是None或undefined。
>> 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'>
用于内省的Python内置工具在这里并不完全有用。在这种情况下我不会依赖它们。例如,xmlrpc libs提供了更有用的方法。
如果您只知道名称,请在上面的代码中使用a.getattr('v')而不是a.v.
if type(getattr(object_to_populate, k))==type('a'):
setattr(object_to_populate, k, value)
或使用外部建议的实例,它也是一样的。
答案 4 :(得分:0)
由于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)
进一步阅读:
答案 5 :(得分:0)
通常,Python类(或其实例)不携带任何给定属性“期望”的类型的信息,因为它没有这样的“期望”。
当您需要对这些元数据进行编码时,您可以使用现有的第三方扩展程序(如Enthought的Traits - 在Traits中,而不是“自己动手”),以及其他功能,您将获得:
验证:特质属性的类型 明确声明。类型是 在代码中很明显,只有值 满足程序员指定的集合 标准(即特征) 定义)可以分配给它 属性。请注意默认值 不必满足为之定义的标准 分配价值。
答案 6 :(得分:0)
由于显式类型检查是非pythonic的,因此请考虑将值包装在int()
中。然后,如果值(无论是什么)可以被强制转换为int
,那么它就是。{如果无法将其强制转换为int
,则无论如何都需要抛出错误(它会自动执行)。
这是“在你跳跃之前看”和“请求宽恕比要求许可更容易”之间的根本区别的一个例子。 Python不是一种“在你跳跃之前”的语言,它是一种“请求宽恕而不是请求许可”的语言。 :)
答案 7 :(得分:0)
您可以通过结合使用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))]
方法来获取类的属性名称和类型:
COUNTER