首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何向Python3对象动态添加reify属性

如何向Python3对象动态添加reify属性
EN

Stack Overflow用户
提问于 2018-12-23 03:23:55
回答 1查看 110关注 0票数 0

我正在尝试一些高级魔法,但我不能完全理解这个问题,这无疑是我在解决它时遇到困难的原因。

如果我做一些非常棘手的事情,并让孩子(DailyPic)知道它的父(Site),那么我可以让一切正常工作,但我不能仅仅从Site动态地做到这一点。

我试图动态地将神奇的reify (稍作修改)添加到DailyPic中,但让DailyPic实例调用Site实例上的方法。

虽然不太好用,但还行得通

代码语言:javascript
复制
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

我想要达到这样的效果:

代码语言:javascript
复制
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

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

EN

回答 1

Stack Overflow用户

发布于 2018-12-23 12:59:13

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

代码语言:javascript
复制
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

然后就是:

代码语言:javascript
复制
print(pic1.filename())

如果你真的想让它成为一个属性,你总是可以设置pic._filename = filename,并在DailyPic上有一个返回self._filename()的属性。这基本上就是你一开始所做的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53898670

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档