我希望能够使用基类来构造派生类的对象。返回的特定子类依赖于无法传递给构造函数/工厂方法的信息,因为它还不可用。相反,这些信息被下载并解析以确定子类
因此,我认为我想惰性地初始化我的对象,只传递一个URL,它可以从中下载所需的信息,但等待实际生成子对象,直到程序需要它为止(即第一次访问)
因此,当第一次创建对象时,它是基类的对象。但是,当我第一次访问它时,我希望它下载其信息,将自身转换为适当的派生类,并返回所请求的信息
在python中如何实现这一点?我想我想要一个类似工厂方法的东西,但是有一些延迟的初始化特性。这个有设计模式吗
Tags:
在Python中,这可以通过几种方式实现——甚至可能不需要使用元类
如果您可以创建类实例,直到需要时为止,那么只需要创建一个可调用的(可能是部分函数)即可计算类并创建实例
但您的文本描述了您希望类在“首次访问”时只是“初始化”——包括更改自己的类型。这是可行的——但是它需要在类特殊方法中进行一些连接——如果“first access”指的是jsut调用方法或读取属性,这很容易——我们只需要定制
__getattribute__
方法来触发初始化机制。另一方面,如果您的类将实现Python的“神奇”dunder方法,例如__len__
、__getitem__
或__add__
,那么“首次访问”可能意味着在实例上触发这些方法之一,这有点棘手-每个dunder方法都必须由代码包装,这将导致初始化发生-因为对这些方法的访问不经过__getattribute__
至于设置子类类型本身,就是将
__class__
属性设置为实例上正确的子类。Python允许,如果两个类(旧类和新类)的所有祖先都具有 相同的__slots__
集-因此,即使使用__slots__
功能, 你不能在子类上改变这一点因此,有三种情况:
1-后期实例化
将类定义本身包装到一个函数中,预先加载URL或它需要的其他数据。调用函数时,将计算并实例化新类
这可以用作:
2-在属性/方法访问时初始化-没有特殊的
__magic__
方法在类
__getattribute__
方法中触发类计算和初始化在创建实例后,这将无缝地:
但是,计算子类所需的参数必须以某种方式传递——在本例中,我要求在“url”参数中传递给基类——但如果url此时不可用,即使是本例也可以工作。在使用实例之前,您可以通过执行
instance._initial_kwargs["url"] = "i.got.it.now"
来更新url另外,对于演示,我必须使用普通Python而不是IPython,因为IPython CLI将内省新实例,从而触发其转换
3-在运算符上初始化使用-专用的
__magic__
方法有一个元类,它用一个装饰器包装基类魔术方法 这将计算新类并执行初始化
这方面的代码与前一个非常相似,但是在
Base
的元类上,__new__
方法必须检查所有__magic__
方法,然后用对self._initialize
的调用来修饰这有一些曲折,使魔术的方法表现正常 无论是在子类中重写它们,还是在初始基中调用它们。不管怎样,所有可能的魔法方法 子类要使用,必须在Base中定义,即使所有子类 要做的是提出一个“NotImplementedError”——
在终端上:
相关问题 更多 >
编程相关推荐