如何在python中在运行时动态创建新的类实例?

时间:2014-11-10 14:33:41

标签: python oop

我正在尝试解决这个问题:

  

想象一下(文字)一叠盘子。如果堆栈太高,那就是   可能会倒下。因此,在现实生活中,我们可能会开始一个新的   当前一个堆栈超过某个阈值时堆栈。实施数据   结构模拟这个的SetOfStacks。 SetOf- Stacks应该是   由几个堆栈组成,并应该创建一个新的堆栈   前一个超过容量。 SetOfStacks.push()和   SetOfStacks.pop()的行为应该与单个堆栈相同(即   是的,pop()应该返回相同的值,如果有的话   单个堆栈)。额外:实现一个函数popAt(int index)   在特定的子堆栈上执行弹出操作。

所以我写了代码:

#!/bin/env python

from types import *

class Stack:

    def __init__(self):
        self.items = []
        self.capacity = 3
        self.stackscount = 0

    def create(self):
        id = self.stackscount + 1
        id = str(id) + "_stack"
        # How to create a new instance of Stack class at runtime ?
        # the __init__ must be run too.

    def push(self, item):
        if self.size() <= self.capacity:
            self.items.append(item)
        else:
            self.create()

    def pop(self):
        return self.items.pop()

    def popAt(self):
        pass

    def peek(self):
        return self.items[len(self.items)-1]

    def size(self):
        return len(self.items)

s = Stack()
s.push(10)

如何在运行时动态创建新的s类型对象?我在互联网上搜索并发现使用new.instance or new.classobj是解决方案,但是当我这样做时,我的新对象似乎没有来自items函数的__init__。在python3中,type()似乎是答案,但docs没有任何示例。

3 个答案:

答案 0 :(得分:2)

你通过引用“类型对象”来迷惑自己。在Python中,这意味着类本身,而不是它的实例。

要创建新的Stack对象,只需执行您正在执行的操作:调用Stack类。您可以将它们附加到列表中:

stacks = [Stack() for _ in range(5)]

然而,正如jon指出的那样,由于您尚未定义SetOfStacks类,因此无法解决您的问题。

答案 1 :(得分:1)

type()功能确实是您正在寻找的功能。可以在此处找到文档:https://docs.python.org/2/library/functions.html#type

您可以这样称呼它:

# Bases is a tuple of parent classes to inherit
bases = Stack,

# Dict contains extra properties for the class, for example if you want to add a class variable or function
dict_ = {}

# Construct the class
YourClass = type('YourClass', bases, dict_)

# Create an instance of the class
your_instance = YourClass()

看起来你只是在看实例创建:

class Stack(object):

    def create(self):
        id = self.stackscount + 1
        id = str(id) + "_stack"
        # How to create a new instance of Stack class at runtime ?
        # the __init__ must be run too.
        stack = Stack()

答案 2 :(得分:1)

您可以简单地使用父子关系:当Stack已满时,它会创建一个子节点,然后委托将其推送到它。它可能导致:

class Stack:

    def __init__(self, parent = None, id=None):
        self.stackscount = 0
        self.capacity = 3
        self.items = []
        self.parent = parent
        self.id = id
        self.child = None

    def create(self):
        id = self.stackscount + 1
        id = str(id) + "_stack"
        return Stack(self, id)

    def push(self, item):
        if self.size() <= self.capacity:
            self.items.append(item)
        else:
            if self.child is None:
                self.child = self.create()
            self.child.push(item)

    def pop(self):
        if self.child is not None:
            item = self.child.pop()
            if len(self.child.items) == 0:
                self.child = None
        else:
            item = self.items.pop()
        return item

    def popAt(self):
        pass

    def peek(self):
        if self.child is not None:
            item = self.child.peek()
        else:
            item = self.items[len(self.items)-1]
        return item

    def size(self):
        l = len(self.items)
        if self.child is not None:
            l += self.child.size()
        return l

s = Stack()
s.push(10)

popAt仍有待实施,但我测试了它,并且在推送和清空时正确创建新堆栈,并在弹出时删除它们。

popAt的实现需要对当前pop实现进行一些改进,以允许删除中间堆栈:

def pop(self):
    if self.child is not None:
        item = self.child.pop()
        if len(self.child.items) == 0:
            self.child = self.child.child
            if self.child is not None:
                self.child.parent = self
    else:
        item = self.items.pop()
    return item

def popAt(self, stacknumber):
    s = self
    for i in range(stacknumber):
        s = s.child
        if s is None:
            return None
    if len(s.items) == 0:
        return None
    item = s.items.pop()
    if len(s.items) == 0 and s.parent is not None:
        s.parent.child = s.child
        if s.child is not None:
            s.child.parent = s.parent
    return item