Python:是否可以从父类的实例构造子类的实例?

时间:2011-07-09 02:20:00

标签: python inheritance

这可能是一个可怕的想法(随时告诉我它是否可以),但我正在探索Python的界限,我可以看到它是如何有用的(事实上,我正在看一个潜力现在的情况)。

以下是设置:

---(API文件)---

class APINode(object):
    def __init__(self, *args, **kwargs):
        # initialize some instance variables

    def render(self, arg1, arg2):
        # do some stuff and return something

def api_function( arg1, arg2 ):
    # do some stuff
    return APINode(args, kwargs)

----(我的档案)----

class MyNode(APINode):
    def render(self, arg1, arg2):
        #My override of APINode's render 


def my_function( arg1, arg2 ):
    api_parent_instance = api_function( arg1, arg2 )
    #Can I some how create an instance of MyNode from api_parent_instance here?

我想略微修改api_function的输出,基本上只是为了覆盖它返回的对象中的render函数。我觉得我的选择是:(1,yuck)将api_function的内容复制到my_function中,但只是构造并返回一个MyNode而不是一个APINode,或者(2,可能?)只是从my_function调用api_function,让它做它的工作 - 构造和返回一个APINode类型的对象,然后我可以以某种方式从该对象创建一个MyNode,以覆盖该方法。

归结为:在Python中,是否可以从父类的实例构造子类的实例?

(看起来很熟悉或想知道实际情况是什么?我正在尝试扩展Django模板标签。)

6 个答案:

答案 0 :(得分:6)

我认为你会更乐意使用MyNode包装APINode,而不是扩展它。您可以实现自己的render()方法,并将所有其他方法委托给包装的APINode。然后,您将能够从现有的APINode创建新的MyNode。

无法从父实例创建子实例。父实例是APINode的实例,您无法更改对象的类。

答案 1 :(得分:2)

不要在家里这样做。

>>> class A:
...     def hi(self):
...         print "I am an A!"
... 
>>> class B:
...     def hi(self):
...         print "I am a B!"
... 
>>> a = A()
>>> a.hi()
I am an A!
>>> # Doing this will likely lead to hard to find bugs.
>>> a.__class__ = B
>>> a.hi()
I am a B!
>>> 

猴子修补API而不是!

def render(self, arg1, arg2):
    #My override of APINode's render 
APINode.render = render
#congratulations, now APINode uses your render function.

这仍然可能导致难以发现的错误,但它有点清洁。

答案 2 :(得分:1)

覆盖分配器。

class B(object):
  def __new__(cls, val):
    if val:
      return D()
    return super(B, cls).__new__(cls)

  def foo(self):
    return 'bar'

class D(object):
  def foo(self):
    return 'baz'

b1 = B(False)
b2 = B(True)
print b1.foo()
print b2.foo()

答案 3 :(得分:1)

这不是我推荐的,但无论如何:

>>> class Monkey(object):
...     def eat(self, smth):
...             if self.likes(smth):
...                     print "Yummy!"
...             else:
...                     print "Yuck!"
...     def likes(self, smth):
...             return smth == "banana"
... 
>>> m = Monkey()
>>> m.eat("banana")
Yummy!
>>> m.eat("cheezburger")
Yuck!
>>> def patch(self, smth):
...     return True
...
>>> m.likes = type(m.likes)(patch, m.likes, Monkey)
>>> m.eat("cheezburger")
Yummy!
>>> 

在您的特定情况下,它看起来像:

def my_render(self, arg1, arg2):
    #My override of APINode's render 

def my_function( arg1, arg2 ):
    api_parent_instance = api_function( arg1, arg2 )
    api_parent_instance.render = type(api_parent_instance.render)(
        api_parent_instance,
        api_parent_instance.render,
        api_parent_instance.__class__)

    ...

答案 4 :(得分:0)

我认为你想要做的是研究超类或其他什么。就像是,a = obj。 _ class _ () 我无法完全记住,但你应该查看python文档。

除非那不是你想要的。但是obj。 _ class _ ()应该生成同一个类的新对象。

答案 5 :(得分:0)

以下是从父类的方法生成子类的新实例的一种非常简单且安全的方法:

class Parent(object):
    def __init__(self):
        pass

    def generate_new_child_object(self):
        print "Generating a new object of type " + str(type(self))
        return type(self)()

class Child(Parent):
    pass

您可以在终端中查看以下内容:

>>> child = Child()
>>> type(child)
<class 'Child'>
>>> generated_child = child.generate_new_child_object()
Generating a new object of type <class 'Child'>
>>> type(generated_child)
<class 'Child'>