向对象属性添加类型信息的python方法是什么?

2024-10-02 10:20:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我构建的类中我知道属性的预期类型,但是Python当然不知道。虽然想要告诉它不是Python式的,假设我想告诉它,那么有没有一种惯用的方法来这么做?在

为什么:我读的是外来格式的数据(没有类型信息),其中包含嵌套在对象中的对象。将它放入嵌套字典很容易,但我希望它在类类型的对象中,以获得正确的行为以及数据。例如:假设我的类Book有一个属性isbn,我将用一个ISBNumber对象填充该属性。我的数据将isbn作为字符串提供给我;我希望能够查看Book并说“该字段应该由ISBNumber(theString)填充。”

如果这个解决方案可以应用于我从别人那里得到的类而不必编辑他们的代码,那我就更高兴了。在

(我只限于2.6版,尽管我对3.x版的解决方案感兴趣,如果有的话)


Tags: 数据对象方法字符串类型字典属性格式
3条回答

有很多方法可以达到这样的效果。如果将输入格式耦合到对象模型是可以接受的,那么可以使用描述符来创建类型适配器:

class TypeAdaptingProperty(object):
    def __init__(self, key, type_, factory=None):
        self.key = key
        self.type_ = type_
        if factory is None:
            self.factory = type_

    def __get__(self, instance, owner):
        if instance is None:
            return self
        return getattr(instance, self.key)

    def __set__(self, instance, value):
        if not isinstance(value, self.type_):
            value = self.factory(value)
        setattr(instance, self.key, value)

    def __delete__(self, instance):
        delattr(instance, self.key)

class Book(object):
    isbn = TypeAdaptingProperty('isbn_', ISBNNumber)

b = Book()
b.isbn = 123 # Does the equivalent of b.isbn = ISBNNumber(123)

但是,如果您不能完全控制消息结构,那么这种耦合不是一个好主意。在这种情况下,我喜欢使用解释器模式使输入消息适应输出类型。我创建了一个小框架,使我能够构建声明性对象结构来处理输入数据。在

框架可能如下所示:

^{pr2}$

消息适配器如下所示:

book_message_adaptor = ObjectAdaptor(Book, kwargs={
    'isbn': Pick('isbn_number', TypeWrapper(ISBNNumber)),
    'authors': Pick('authorlist', ListAdaptor(TypeWrapper(Author)))
})

请注意,消息结构名称可能与对象模型不同。在

消息处理本身如下所示:

message = {'isbn_number': 123, 'authorlist': ['foo', 'bar', 'baz']}
book = book_message_adaptor(message)
# Does the equivalent of:
# Book(isbn=ISBNNumber(message['isbn_number']),
#      authors=map(Author, message['author_list']))

我假设您已经考虑过pickle模块,它不适合您的目的。在这种情况下,可以将属性附加到类中,该属性指定每个属性的类型:

class MyClass(object):
    _types = {"isbn": ISBNNumber}

在重建时,迭代_types并尝试强制执行类型:

^{pr2}$

在上面的代码示例中,obj是正在重建的对象,我假设属性已经以字符串格式(或者从非序列化中获得的任何内容)分配。在

如果您希望它与无法更改源代码的第三方类一起使用,可以在从其他地方导入该类之后在运行时将_types属性附加到该类。例如:

>>> from ConfigParser import ConfigParser
>>> cp = ConfigParser()
>>> cp._types
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: ConfigParser instance has no attribute '_types'
>>> ConfigParser._types = {"name": "whatever"}
>>> cp._types
{"name": "whatever"}

我也同意使用__repr__和{},如果你能完全控制从你的输入文件中得到什么,那么使用eval会导致任意代码执行的可能性,这是相当危险的。在

至少在原则上,这是一个对象的__repr__函数应该实现的功能:对象的无歧义重建。在

如果类的定义如下:

class ISBN(object):
    def __init__(self, isbn):
        self.isbn = isbn

    def __repr__(self):
        return 'ISBN(%r)' % self.isbn

那么您就离重建原始对象一步之遥了。另请参见pickle module。在

在ISBN类上进行即兴表演,然后给你一个书本类

^{pr2}$

当然,你的对象可能不仅仅是构造和重建它们自己。。。还有塔玛斯提到的关于评估的警告。在

相关问题 更多 >

    热门问题