【问题标题】:Pythonic Way to set Multiple Properties Based on another class基于另一个类设置多个属性的 Pythonic 方式
【发布时间】:2015-01-16 10:40:36
【问题描述】:

当我只想将get 传递给另一个对象时,是否有一种优雅的方式来处理类的所有get 请求?

这是一个 Django 项目,我有一个视频模型;视频可以来自不同的网站(例如 YouTube、Vimeo 等)。该模型是通用的,将获取适当的backend 来解析数据(根据站点的不同,repr 会有所不同)。所有视频都将具有相同的属性,但我有不同的 backend 来正确解析它们。示例如下:

BACKEND_VIDEO_TYPE = (
    (1, 'YouTube'),
    (2, 'Vimeo'),
)

class Video(ItemBase):
    video_id = models.CharField(max_length=25)
    video_type = models.PositiveIntegerField(choices=BACKEND_VIDEO_TYPE)
    video_data = models.TextField(editable=False)

    class Meta:
        unique_together = ("video_id", "video_type")

    def __init__(self, *args, **kwargs):
        super(Video, self).__init__(*args, **kwargs)

        for k, v in BACKEND_VIDEO_TYPE:
            if k == self.video_type:
                VideoBackend = import_string( 'video.backends.' + v )
                # load the backend that matches the video type and supply it with the data to parse
                self.backend = VideoBackend(self.video_id, self.video_data)

    @property
    def link(self):
        return self.backend.link

    @property
    def thumbnail(self):
        return self.backend.thumbnail

    @property
    def is_public(self):
        return self.backend.is_public()

    @property
    def duration(self):
        return self.backend.duration

我觉得这不是处理这个问题的最佳方法,但我太新了,不知道要寻找什么。在我确定要实现哪个后端类之后,是否有一种简单的方法可以return self.backend.property 而无需添加后端中的每个属性?这份清单将会变得相当长。一个通用的__get__ 或类似的?

感谢您的帮助。

【问题讨论】:

    标签: python django class model getter


    【解决方案1】:

    您可以覆盖Video 类上的__getattr__,以便它获取backend 的属性。

    def __getattr__(self, attr):
        try:
            return getattr(self.backend, attr)
        except:
            raise AttributeError('No attribute named ' + attr)
    

    __getattr__ 只会在Video 对象上找不到该属性时调用(例如,如果用户要求Video.video_id,它根本不会调用)所以这是扩展暴露属性的一种巧妙方法Video 类。缺点是哪些属性可用可能并不明显,或者它可能会暴露一些您不希望的属性。您可以通过让VideoBackend 类提供允许的属性列表来解决此问题。

    def __getattr__(self, attr):
        if attr in self.backend.get_allowed_attr():
            return getattr(self.backend, attr)
        else:
            raise AttributeError('No attribute named ' + attr)
    

    【讨论】:

    • 我明白了 - 但它不会单独显示为可用属性(就像在 shell 或文档中使用 @property 定义的属性一样)?这就是该功能的用武之地……不过,这可以节省一些打字和重新打字,因为它们只是一面镜子。这就是我一直在寻找的想法。
    • 是的,很遗憾,您的代码编辑器不会提示您输入属性。
    • 如果我已经存储了一个列表,我可以遍历__init__ 上的列表并以这种方式设置属性(从而允许提示?)
    • 我不这么认为,因为它在运行时再次依赖于纯代码。如果你让Video 继承VideoBackend 类,你可能会得到你想要的,但不确定这是否适合你的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-02
    • 2020-03-23
    • 2011-11-05
    • 2016-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多