Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在类中查找属性的类型_Python_Google App Engine - Fatal编程技术网

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))]