如何在不调用__init__的情况下动态创建type(self)的实例?

5 投票
3 回答
6698 浏览
提问于 2025-04-17 05:42

这件事说起来有点复杂。我有一个类,这个类应该支持一个叫做 copy_stateonly() 的方法。这个方法应该返回一个简化版的对象,这个对象只包含我想要的(复制的)数据成员。我希望这个例子能让你更明白:

# everything inherits from this
class SuperBase:
    def __init__(self):
        self.state_var = 3 # this should be copied into future objects
        self.non_state_var = 0 # we don't want to copy this

    def copy_stateonly(self):
        newobj = # ??????????? create instance without calling __init__
        newobj.state_var = self.state_var
        return newobj

# some clases inherit from this
class Base(SuperBase):
    def __init__(self):
        SuperBase.__init__(self)
        self.isflying = True # we want to copy this, this is state
        self.sprite = "sprites/plane_generic.png" # we must drop this

    def copy_stateonly(self):
        newobj = SuperBase.copy_stateonly(self)
        newobj.isflying = self.isflying
        return newobj

class A144fighter(Base):
    def __init__(self, teamname): # note required __init__ argument
        Base.__init__(self)
        self.colors = ["black", "grey"] # we want to copy this, this is state
        self.name = teamname # we must drop this

    def copy_stateonly(self):
        newobj = Base.copy_stateonly(self)
        newobj.colors = self.colors[:]
        return newobj

plane = A144fighter("team_blue")
plane_state = plane.copy_stateonly() # this should return an A144fighter object with only state_var, flying and colors set.

Python 2.7

3 个回答

2

这段代码是用来处理一些数据的。它的主要功能是从一个地方获取信息,然后对这些信息进行一些操作,最后把结果输出。具体来说,它可能会从数据库中提取数据,进行计算或转换,然后把结果显示在屏幕上或者存储到文件里。

在编程中,我们常常需要这样的过程来处理用户输入或者后台数据。通过这样的代码,我们可以让计算机自动完成一些重复的工作,节省时间和精力。

如果你对这段代码有疑问,可以尝试逐行分析,看看每一部分是做什么的,慢慢就能理解它的工作原理了。

# everything inherits from this
class SuperBase:
    def __init__(self):
        self.state_var = 3 # this should be copied into future objects
        self.non_state_var = 0 # we don't want to copy this

    def __getstate__(self):
        return { 'state_var' : self.state_var }

    def __str__(self):
        return self.__class__.__name__ + '(' + str(vars(self)) + ')'

# some clases inherit from this
class Base(SuperBase):
    def __init__(self):
        SuperBase.__init__(self)
        self.isflying = True # we want to copy this, this is state
        self.sprite = "sprites/plane_generic.png" # we must drop this

    def __getstate__(self):
        state = SuperBase.__getstate__(self)
        state['isflying'] = self.isflying
        return state

class A144fighter(Base):
    def __init__(self, teamname): # note required __init__ argument
        Base.__init__(self)
        self.colors = ["black", "grey"] # we want to copy this, this is state
        self.name = teamname # we must drop this

    def __getstate__(self):
        state = Base.__getstate__(self)
        state['colors'] = self.colors[:]
        return state

plane = A144fighter("team_blue")
print plane

import copy
print copy.copy(plane)

# or manually:
import types
print types.InstanceType(plane.__class__, plane.__getstate__())
4

记住,每个对象都有一个叫做 __class__ 的属性。如果你输入 <object>.__class__,它会返回这个对象所属的类(希望这样说你能理解)。这个类对象是可以调用的,所以你可以在后面加上括号来创建这个类的新实例。

newobj = self.__class__()
8

我不知道有没有办法在不调用 __init__() 的情况下创建经典类的新实例(你在例子中用的就是这种类)。不过,对于新式类(也就是从 object 继承的类),可以通过下面的方式来创建新实例:

object.__new__(cls)

这里的 cls 是你想要创建的对象的类型。

另外一种方法是使用 copy.copy() 来复制对象,可能还需要重写 __getstate__()__setstate__() 这两个方法,以定义哪些内容需要被复制。

补充说明:如果你想在不调用 __init__() 的情况下创建经典类 cls 的新实例,可以使用下面这个小技巧:

class EmptyClass:
    pass

new_instance = EmptyClass()
new_instance.__class__ = cls
new_instance.__dict__.update(whatever)

撰写回答