Изменение типа класса после вставленных данных

Я хочу создать класс в python, который должен работать следующим образом:

  • Назначенные данные, возможно связанные с переменной (например, a = exampleclass(data) или просто exampleclass(data))

  • После ввода данных он должен автоматически определять некоторые свойства данных, и если некоторые определенные свойства заполняются, он автоматически...

  • ... изменить класс на другой класс

Часть 3 - это та часть, с которой у меня проблема. Как действительно изменить класс внутри класса? например:

Если у меня есть два класса, один из них Small_Numbers, а другой - Big_numbers; теперь я хочу, чтобы любой small_number, меньший, чем 1000, был перенесен в 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.

Можно ли это сделать?

Ответ 1

Использование метода factory является обычным способом его решения, тем более, что создание экземпляра класса неотличимо от вызова функции в 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

Ответ 2

Почему бы не использовать метод factory? Этот вопрос будет определять, какой класс должен инициировать в зависимости от переданных данных. Используя ваш пример:

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

Ответ 3

не делать. Вместо этого используйте factory.

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)