更改插入数据后的类类型

10 投票
3 回答
19988 浏览
提问于 2025-04-17 12:20

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

  1. 首先,给这个类一些数据,可能是绑定到一个变量上,比如 a = exampleclass(data) 或者直接 exampleclass(data)

  2. 当数据被插入后,它应该自动判断一些数据的特性,如果满足某些特性,它会自动...

  3. ...将类更改为另一个类

第三部分是我遇到问题的地方。我该如何在类内部真正改变类呢?比如:

如果我有两个类,一个是 Small_Numbers,另一个是 Big_numbers;现在我想让任何小于1000的 small_number 转换为 Big_number,反之亦然,测试代码:

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.

这样做可能吗?

3 个回答

11

别这样做。用工厂函数来代替。

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)
15

为什么不使用工厂方法呢?这个方法会根据传入的数据来决定实例化哪个类。用你的例子来说:

def create_number(number):
    if number < 1000:
        return SmallNumber(number)
    return BigNumber(number)
11

使用工厂方法是解决这个问题的常见方式,特别是因为在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

这样做会按预期工作:

>>> a = Small(100)
>>> type(a)
<class 'Small'>
>>> b = Small(1234)
>>> type(b)
<class 'Big'>
>>> c = Big(2)
>>> type(c)
<class 'Small'>

如果给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

撰写回答