#python-3.x #elasticsearch #inheritance
#python-3.x #elasticsearch #наследование
Вопрос:
Я пытаюсь создать класс python, который наследует класс Elasticsearch и основывается на нем с помощью некоторых пользовательских методов. Проблема, с которой я сталкиваюсь, заключается в том, что я хотел бы, чтобы конструктор класса подключался к серверу, поэтому инициализация проста. Обычно для подключения к серверу это выглядит примерно так:
from elasticsearch import Elasticsearch
es = Elasticsearch([{'host': 'XXXXXXX', 'port': XXXX}]
В моем классе, который я называю «Эластичным», я хотел бы подключиться к серверу и вернуть объект Elasticsearch при инициализации класса, т.е.:
es = Elastic()
который я могу затем использовать для выполнения существующих методов класса Elasticsearch и моих собственных пользовательских операций, например:
es.search() # existing class method
es.custom_method_example1() # new class method
Я пытался и не смог придумать способ сделать это — моя последняя попытка заключалась в использовании метода __new__
dunder, чтобы я мог вернуть подключенный es
объект в качестве нового класса:
class Elastic(Elasticsearch):
def __new__(cls, timeout=10, max_retries=5, retry_on_timeout=True, *args, **kwargs):
"Connect to our ES server."
return Elasticsearch([{'host': 'XXXXX', 'port': XXXX}], timeout=10, max_retries=5, retry_on_timeout=True, *args, **kwargs)
def custom_method_example1(self, *args, **kwargs):
"""
Performs some custom method that wasn't possible with the standalone Elasticsearch class
"""
Во-первых, это не работает:
AttributeError: 'Elasticsearch' object has no attribute 'custom_method_example1'
кажется, что он больше не наследует, а заменяет класс?
И, во-вторых, я понял, прочитав об этом, что __new__
обычно не имеет большого смысла (особенно для программистов-любителей, таких как я), поэтому я, вероятно, использую неправильный подход / усложняю его здесь. Если кто-нибудь знает «правильный» способ сделать это, он был бы очень признателен — я немного читал о дизайне фабрики, и в целом это кажется правильным путем, но я все еще понимаю все это (я аналитик по профессии). Я полагаю, что декораторы могут где-то использоваться??
Спасибо и извините за вафлю
Ответ №1:
Действительно, я очень сильно усложнял это. Не учел, что наследование класса включает в себя наследование самого конструктора — поэтому я могу вызвать подкласс Elastic
так же, как и для родительского Elasticsearch
:
from elasticsearch import Elasticsearch
class Elastic(Elasticsearch):
def custom_method_example1(self, *args, **kwargs):
"""
Performs some custom method that wasn't possible with the standalone Elasticsearch class
"""
Для инициализации класса и вызова его методов:
es = Elastic([{'host': 'XXXXX', 'port': XXXX}], timeout=10, max_retries=5, retry_on_timeout=True)
es.custom_method_example1()
РЕДАКТИРОВАТЬ: у меня все еще была проблема с желанием установить новые параметры по умолчанию для моего конструктора подкласса — теперь я узнал, как это сделать, используя super()
который явно вызывает родительский конструктор, передавая аргументы, которые я установил в конструкторе подкласса, оставляя меня с:
from elasticsearch import Elasticsearch
class Elastic(Elasticsearch):
def __init__(self, hosts=[{'host':'XXXXXX', 'port':XXX}], timeout=10, max_retries=5, retry_on_timeout=True):
super().__init__(hosts=hosts,timeout=timeout,max_retries=max_retries,retry_on_timeout=retry_on_timeout)
def custom_method_example1(self, *args, **kwargs):
"""
Performs some custom method that wasn't possible with the standalone Elasticsearch class
"""
что позволяет мне инициализировать класс следующим образом:
es = Elastic()