以惯用方式将BaseClass对象转换为SubClass对象? [英] Convert a BaseClass object into a SubClass object idiomatically?

查看:168
本文介绍了以惯用方式将BaseClass对象转换为SubClass对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个基类 Base 和一个子类 Special

There is a base class Base and a subclass Special.

class Base(object):
    def __init__(self, name):
        self.name = name
    def greet(self):
        return 'Hello %s' % self.name

class Special(Base):
    def __init__(self, name):
        super(Special, self).__init__(name)
    def rhyme(self):
        return 'Hi %s! How are you? Fine, thanks. What about you?' % self.name

如何转换基本到实例特殊?目前我在特殊上定义了一个 classmethod ,只需重新显示 __ dict __

How can I turn an instance of Base into an instance Special? Currently I have a classmethod defined on Special that just reassignes __dict__:

class Special(Base):
    ...
    @classmethod
    def from_base(cls, baseobj):
        special = Special()
        special.__dict__ = baseobj.__dict__
        return special

这是惯用的吗?如果不是这样的话?

Is this idiomatic? If not what would be?

P.S。示例场景:基类是一些默认实现。在野外,您可能会找到基类的对象。现在在某个项目中,基类已经是子类,并且已经在子类中添加了特殊方法。现在你大部分时间仍然使用基类对象,但有时你会想要升级到特殊类,因为你需要访问一些方法。

P.S. An example scenario: The base class is some default implementation. In the wild, you'll likely find objects of the base class. Now in some project, the base class has been subclasses and special methods have been added to the subclass. Now you mostly still work with base class objects, but from time to time you'll want to "upgrade" to the special class, because you'll need access to some methods.

推荐答案

您可以通过定义备用构造函数并重新分配实例的 __ class __ attribute。

You can achieve this by defining an alternate constructor and reassigning the instance's __class__ attribute.

class Base(object):
    def __init__(self, name):
        self.name = name

    def greet(self):
        return 'Hello %s' % self.name

    @classmethod
    def alt_constructor(cls, *args, **kwargs):
        obj = cls(*args, **kwargs)
        obj.__class__ = Special
        return obj


class Special(Base):
    def __init__(self, name):
        super(Special, self).__init__(name)

    def rhyme(self):
        return 'Hi %s! How are you? Fine, thanks. What about you?' % self.name


>>> s = Base.alt_constructor("test")
>>> print s.rhyme()
Hi test! How are you? Fine, thanks. What about you?

编辑:

将构造函数从 Special 移至 Base

如果你不能修改 Base 类,你可以添加一个classmethod到 Special ,这将改变类传递给它的任何对象。

If you can't modify the Base class you can add a classmethod to Special that will change the class of any object passed to it.

class Base(object):
    def __init__(self, name):
        self.name = name

    def greet(self):
        return 'Hello %s' % self.name


class Special(Base):
    def __init__(self, name):
        super(Special, self).__init__(name)

    def rhyme(self):
        return 'Hi %s! How are you? Fine, thanks. What about you?' % self.name

    @classmethod
    def convert_to_special(cls, obj):
        obj.__class__ = Special

>>> b = Base("test")
>>> print type(b)
<class '__main__.Base'>

>>> Special.convert_to_special(b)
>>> print type(b)
<class '__main__.Special'>

一个更通用的解决方案是创建一个可以添加到任何类的mixin。

A more all purpose solution would be to create a mixin that can be added to any class.

class ConverterMixin(object):

    @classmethod
    def convert_to_class(cls, obj):
        obj.__class__ = cls


class Special(ConverterMixin, Base):
    def __init__(self, name):
        super(Special, self).__init__(name)

    def rhyme(self):
        return 'Hi %s! How are you? Fine, thanks. What about you?' % self.name

>>> b = Base("test")
>>> print type(b)
<class '__main__.Base'>

>>> Special.convert_to_class(b)
>>> print type(b)
<class '__main__.Special'>

这篇关于以惯用方式将BaseClass对象转换为SubClass对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆