欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

不通过调用__Init__来创建实例

程序员文章站 2022-04-04 16:41:27
老样子,抛出个问题,我们想要创建一个实例,但是由于某些原因想绕过__init__方法,用别的方式来进行创建。 举个栗子 小贱贱反序列化数据,或者说实现一个类方法将其作为备选的构造函数,都属于这种情况。举个栗子: 采用下面的方法可以不用调用__init__()创建一个Date实例: 但是注意,此时使用 ......

老样子,抛出个问题,我们想要创建一个实例,但是由于某些原因想绕过__init__方法,用别的方式来进行创建。

举个栗子不通过调用__Init__来创建实例

小贱贱反序列化数据,或者说实现一个类方法将其作为备选的构造函数,都属于这种情况。举个栗子:

class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

采用下面的方法可以不用调用__init__()创建一个Date实例:

d = Date.__new__(Date)

但是注意,此时使用d.year就会给你报个错

因为得到的实例是未经初始化的,因此给实例变量设定合适的初始值现在就成了我们的责任。

ok……在下面的例子中给出:

from time import localtime

class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

    @classmethod
    def today(cls):
        d = cls.__new__(cls)
        t = localtime()
        t.year = t.tm_year
        t.month = t.tm_mon
        t.day = t.tm_mday
        return d

类似的,假如正在反序列化JSON数据,要产生下面酱紫的字典:

要产生类似字典的数据咋搞呢?

不通过调用__Init__来创建实例
from time import localtime

class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

    @classmethod
    def today(cls):
        d = cls.__new__(cls)
        t = localtime()
        T = {}
        T['year'] = t.tm_year
        T['month'] = t.tm_mon
        T['day'] = t.tm_mday
        for key, value in T.items():
            setattr(d, key, value)
        return d
x = Date(2018,6,5)
youxi=x.today()
print(youxi.year, youxi.month, youxi.day)
View Code

总结:

当通过非标准方法去创建实例的时候,最好不要对他们的实现做过多的假设,不要直接操作底层的字典__dict__的代码,除非你保证它完全被定义了,否则,一旦类中使用了

__slots__、proprety属性、描述符(魔术方法),那么你的代码就会崩溃。通过使用setattr()来为属性定值,代码就会尽可能的通用。