插入数据后更改类的类类型

use*_*139 8 python class python-3.x

我想在python中创建一个类,它应该像这样工作:

  1. 分配的数据,可能绑定到变量(例如a = exampleclass(data)或只是exampleclass(data))

  2. 插入数据后,它应自动确定数据的某些属性,如果某些属性已满,则会自动...

  3. ...将班级改为另一班级

第3部分是我遇到问题的部分.我如何真正改变班级内的课程?例如:

如果我有两个班,一个是Small_Numbers,另一个是Big_numbers; 现在我希望任何small_number小于1000的转移到a Big_number,反之亦然,testcode:

a = Small_number(50)
type(a) # should return Small_number.
b = Small_number(234234)
type(b) # should return Big_number.
c = Big_number(2)
type(c) # should return Small_number.
Run Code Online (Sandbox Code Playgroud)

这可能吗?

jul*_*ria 13

为什么不使用工厂方法?这个将根据传递的数据决定实现哪个类.使用你的例子:

def create_number(number):
    if number < 1000:
        return SmallNumber(number)
    return BigNumber(number)
Run Code Online (Sandbox Code Playgroud)


Cat*_*lus 10

别.请改用工厂功能.

def create_number(source):
    if source < 1000:
       return Small_number(source)
    else:
       return Big_number(source)

a = create_number(50)
b = create_number(234234)
c = create_number(2)
Run Code Online (Sandbox Code Playgroud)


Mar*_*ler 9

使用工厂方法是解决此问题的常用方法,尤其是因为实例化类与在Python中调用函数无法区分.

但是,如果您真的想要,可以指定self.__class__:

THRESHOLD = 1000

class Small(object):
    def __init__(self, n):
        if n < THRESHOLD:
            self.n = n
        else:
            self.__class__ = Big
            self.__init__(n)

class Big(object):
    def __init__(self, n):
        if n < THRESHOLD:
            self.__class__ = Small
            self.__init__(n)
        else:
            self.n = n
Run Code Online (Sandbox Code Playgroud)

这按预期工作:

>>> a = Small(100)
>>> type(a)
<class 'Small'>
>>> b = Small(1234)
>>> type(b)
<class 'Big'>
>>> c = Big(2)
>>> type(c)
<class 'Small'>
Run Code Online (Sandbox Code Playgroud)

如果分配self.__class__似乎太奇怪,那么你可以改写__new__.在调用之前__init__调用此方法,它可用于选择要实例化的类:

THRESHOLD = 1000

class Switcher(object):
    def __new__(cls, n):
        if n < THRESHOLD:
            new_cls = Small
        else:
            new_cls = Big
        instance = super(Switcher, new_cls).__new__(new_cls, n)
        if new_cls != cls:
            instance.__init__(n)
        return instance

class Small(Switcher):
    def __init__(self, n):
        self.n = n

class Big(Switcher):
    def __init__(self, n):
        self.n = n
Run Code Online (Sandbox Code Playgroud)

  • 我强烈建议 *not* 更改对象的类型(即,不要分配给 `__class__`)。请参阅 [文档中的此评论](http://docs.python.org/reference/datamodel.html#id5),并考虑在您执行此操作后特殊方法可能无法预测地工作。即使你认为你确切地知道会发生什么,你也可以接受,你可能会被下一个版本的 Python 搞砸——毕竟,Python 没有明确的承诺它会(或不会)如何工作。 (2认同)
  • 覆盖`__new__`的解决方案需要检查new_cls不是cls的子类(如果不是issubclass(client_cls,cls)`),或者除了调用`__init__`之外还要做一些事情,因为这将导致` __init__`为子类调用两次.您可以通过在每个子类的`__init__`中添加一个print语句来测试它. (2认同)