如何动态地将reify属性添加到Python3对象

时间:2018-12-22 19:23:55

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

我正在尝试做一些高级向导,但我并没有完全理解这个问题,这无疑是为什么我在解决它时遇到麻烦。

如果我做些超级骇客的事,让孩子(class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate )知道它的父母(DailyPic),那么我可以使所有工作正常进行,但是我不知道该如何动态地做到这一点。仅仅来自Site

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

hacky,但是有效

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

如果高级向导可以发出警报,那就太好了!

1 个答案:

答案 0 :(得分:1)

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

print(pic1.filename())

然后就是:

pic._filename = filename

如果您确实希望将其作为属性,则可以始终设置DailyPic并在self._filename()上具有返回if (str.length()==0){ return str; // the above if statement (length = 0) does not work } 的属性。基本上就是您要做的。