class MyClass:
def __init__(self, arg):
if isinstance(arg, int):
self.method_for_int(arg)
elif isinstance(arg, str):
self.method_for_string(arg)
else:
raise TypeError("Неподдерживаемый тип аргумента")
def method_for_int(self, value):
print(f"Обработка целого числа: {value}")
def method_for_string(self, text):
print(f"Обработка строки: {text}")
2. Использование множественной диспетчеризации (functools.singledispatchmethod в Python 3.8+):
from functools import singledispatchmethod
class MyClass:
@singledispatchmethod
def __init__(self, arg):
raise TypeError("Неподдерживаемый тип аргумента")
@__init__.register(int)
def _(self, arg: int):
self.method_for_int(arg)
@__init__.register(str)
def _(self, arg: str):
self.method_for_string(arg)
def method_for_int(self, value):
print(f"Обработка целого числа: {value}")
def method_for_string(self, text):
print(f"Обработка строки: {text}")
3. Использование паттернов Factory Method или Abstract Factory (более сложные, но гибкие варианты):
Эти паттерны предполагают создание отдельных классов или функций для конструирования объектов в зависимости от типа данных.
Они позволяют отделить логику создания объекта от его использования и облегчают добавление новых типов данных в будущем.
Для создания конструктора, который вызывает разные методы в зависимости от типа переданных параметров в Python, можно использовать несколько подходов. Самый распространённый и рекомендуемый - это использование classmethod
и статического метода @staticmethod
в комбинации с проверкой типов или диспетчеризацией на основе аргументов. Второй способ это использование библиотеки singledispatchmethod
.
Пример с classmethod
и проверкой типов:
class MyClass:
def __init__(self, value):
self.value = value
def process_string(self, s):
print(f"Обработка строки: {s}")
self.value = s
def process_number(self, n):
print(f"Обработка числа: {n}")
self.value = n * 2
@classmethod
def from_string(cls, data):
instance = cls(None) # Создаем экземпляр класса
instance.process_string(data) # Вызываем метод для обработки строки
return instance
@classmethod
def from_number(cls, data):
instance = cls(None) # Создаем экземпляр класса
instance.process_number(data) # Вызываем метод для обработки числа
return instance
@classmethod
def create(cls, data):
if isinstance(data, str):
return cls.from_string(data)
elif isinstance(data, (int, float)):
return cls.from_number(data)
else:
raise ValueError("Неподдерживаемый тип данных")
# Пример использования:
obj1 = MyClass.create("Hello") # Создание из строки
print(obj1.value)
obj2 = MyClass.create(10) # Создание из числа
print(obj2.value)
#obj3 = MyClass.create([1,2,3]) # Вызовет ValueError
В этом примере MyClass
имеет конструктор __init__
, а также два classmethod
: from_string
и from_number
. Метод create
выступает в роли фабричного метода, который принимает данные и, в зависимости от их типа, вызывает соответствующий classmethod
для создания и инициализации объекта. Этот подход позволяет инкапсулировать логику создания объектов и выбирать ее в зависимости от входных данных.
Альтернативный пример с использованием singledispatchmethod
(начиная с Python 3.8):
from functools import singledispatchmethod
class MyClass:
def __init__(self, value):
self.value = value
@singledispatchmethod
def process_data(self, data):
raise TypeError("Неподдерживаемый тип данных")
@process_data.register
def _(self, data: str):
print(f"Обработка строки: {data}")
self.value = data
@process_data.register
def _(self, data: int):
print(f"Обработка числа: {data}")
self.value = data * 2
@classmethod
def create(cls, data):
instance = cls(None)
instance.process_data(data)
return instance
# Пример использования:
obj1 = MyClass.create("Hello")
print(obj1.value)
obj2 = MyClass.create(10)
print(obj2.value)
#obj3 = MyClass.create([1,2,3]) # Вызовет TypeError
В этом примере singledispatchmethod
используется для диспетчеризации вызова метода process_data
на основе типа аргумента. Это делает код более читаемым и расширяемым, особенно если требуется поддержка большего количества типов данных. Конструктор `create` остается простым и вызывает соответствующий обработчик данных.
Важно:
classmethod
- это метод класса, который может быть вызван без создания экземпляра класса. Он получает сам класс (cls
) в качестве первого аргумента.singledispatchmethod
позволяет более элегантно обрабатывать различные типы данных, но требует Python 3.8 или более поздней версии.classmethod
с проверкой типов проще для простых случаев, а singledispatchmethod
лучше подходит для более сложных сценариев.