【问题标题】:How to dynamically add a reify property to a Python3 object如何动态地将 reify 属性添加到 Python3 对象
【发布时间】:2018-12-22 19:23:54
【问题描述】:

我正在尝试做一些高级魔法,但我并不完全理解这个问题,这无疑是我无法解决它的原因。

如果我做一些超级 hacky 并让孩子 (DailyPic) 知道它的父母 (Site) 那么我可以让一切正常工作,但我无法弄清楚如何仅从 @987654324 动态地做到这一点@。

我正在尝试将奇妙的reify(稍作修改)动态添加到DailyPic,但让DailyPic 实例调用Site 实例上的方法。

很老套,但它可以工作

class reify():
    def __init__(self, wrapped, name=None):
        self.wrapped = wrapped

        if name is None:
            from functools import update_wrapper
            update_wrapper(self, wrapped)
        else:
            self.wrapped.__name__ = name

    def __get__(self, inst, objtype=None):
        if inst is None:
            return self
        val = self.wrapped(inst)
        setattr(inst, self.wrapped.__name__, val)
        return val

class Site:
    def __init__(self):
        self.counter = 0

    def mk_filename(self, pic):
        self.counter += 1
        return f"{self.__class__.__name__}-{self.counter}.{pic.ext()}"

    def save(self):
        pic = DailyPic()

        from functools import partial
        pic._mk_filename = partial(self.mk_filename, pic)

        return pic


class DailyPic:
    def ext(self):
        return 'gif' # simplified for example

    @reify
    def filename(self):
        return self._mk_filename() # YUCK!!!

# works but ugly...

class Site1(Site): pass
class Site2(Site): pass

pic1 = Site1().save()
pic2 = Site2().save()

print(pic1.filename) # Site1-1
print(pic2.filename) # Site2-1

我正在尝试这样的事情:

class Site:
    def save(self):
        pic = DailyPic()
        DailyPic.filename = reify(
            functools.partial(lambda pic: self.mk_filename(pic)),
            'filename'
        )
        return pic

# sorta works...

print(pic1.filename) # Site2-1 , should be Site1-1
print(pic2.filename) # Site2-2 , should be Site2-1

如果一个高级巫师能插话那就太棒了!

【问题讨论】:

  • 你在这里一般想做什么?从网站下载图片?并用计数器命名?在您的目标示例中,尚不清楚 pic1pic2 来自何处,因此很难说出您想要什么...
  • 是的,我已经删掉了很多额外的代码(比如 Site.save 确实需要一个 url),但我想要完成的并不是重点。我在问如何使用适当的实例绑定动态添加reify(可能适用于property)。
  • 我认为这是相关的,这听起来很像 XY 问题,但很难说。我的意思是,您访问filename 的顺序决定了文件名,这有点奇怪。
  • 是的,这是一个非常奇怪的命令,这就是为什么我要尝试使用 reify 技巧。 ;)

标签: python python-3.x decorator python-decorators


【解决方案1】:

除非你真的,真的,需要它成为一个属性,否则只需忽略 reify 和属性,并在每个实例上设置一个函数,该函数在运行一次时会覆盖自身。

class Site:
    def save(self):
        pic = DailyPic()

        def filename(pic_self):
            val = self.mk_filename(pic_self)
            pic_self.filename = lambda _: val
            return val

        pic.filename = filename
        return pic

那就是:

print(pic1.filename())

如果您真的希望它成为一个属性,您可以始终设置pic._filename = filename 并在DailyPic 上拥有一个返回self._filename() 的属性。这基本上就是你开始做的事情。

【讨论】:

    猜你喜欢
    • 2012-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-05
    • 2011-10-05
    • 2017-10-14
    • 2011-01-15
    • 1970-01-01
    相关资源
    最近更新 更多