Отвечая как на ваш вопрос, так и на ваш комментарий, да, можно написать такой код, но я не вижу смысла в этом:
class A:
def __new__(cls, value):
return cls.meth1(value)
def meth1(value):
return value + 1
result = A(100)
print(result)
# output:
101
Вы не можете сохранить ссылку на экземпляр класса A, потому что вы получаете результат вашего метода вместо экземпляра A. И из-за этого существующий __init__
не будет вызван.
Так что, если экземпляр просто вычисляет что-то и сразу отбрасывается, вам нужно написать простую функцию, а не класс. Вы нигде не храните состояние.
И если вы посмотрите на это:
result = some_func(value)
выглядит именно так, как люди ожидают, читая его, вызов функции.
Так что нет, это не очень хорошая практика, если вы не придумали для нее хороший вариант использования (сейчас я не могу вспомнить ни одного)
Также имеет отношение к этому вопросу документация здесь , чтобы понять поведение __new__
и __init__
.
Относительно вашего другого комментария под моим ответом:
определение __init__
в классе для установки начального состояния (значений атрибутов) (уже) созданного экземпляра происходит постоянно. Но __new__
имеет другую цель настройки создания объекта . Объект экземпляра еще не существует при запуске __new__
(это функция конструктора). __new__
редко требуется в Python, если вам не нужны такие вещи, как singleton , скажем, класс A
, который всегда возвращает один и тот же экземпляр объекта (из A) при вызове с A()
. Обычные пользовательские классы обычно возвращают новый объект при создании экземпляра. Вы можете проверить это с помощью встроенной функции id()
. Другой вариант использования - когда вы создаете свою собственную версию (путем создания подклассов) неизменяемого типа. Поскольку оно является неизменным, значение уже было установлено, и нет способа изменить значение внутри __init__
или более поздней версии. Отсюда необходимость действовать до этого, добавив код внутри __new__
. Использование __new__
без возврата объекта того же типа класса (это необычный случай) имеет дополнительную проблему не __init__
.
Если вы просто группируете множество методов внутри класса, но в каждом экземпляре по-прежнему нет состояния для хранения / управления (вы заметите это также из-за отсутствия использования self
в теле методов), не используйте Классы и организации этих методов теперь превратились в самоотверженные функции в модуле или пакете для импорта. Потому что, похоже, вы группируете только для организации связанного кода.
Если вы придерживаетесь классов, поскольку в них присутствует состояние, рассмотрите возможность разбить класс на более мелкие классы, используя не более пяти-семи методов. Подумайте также о том, чтобы придать им некоторую структуру, сгруппировав несколько небольших классов в различные модули / подмодули и используя подклассы, потому что длинный простой список небольших классов (или функций в любом случае) может быть ментально трудным для понимания.
Это не имеет ничего общего с __new__
использованием.
Таким образом, используйте синтаксис вызова для вызова функции, которая возвращает результат (или нет), или для создания объекта путем вызова имени класса. В этом случае обычно возвращается объект заданного типа (вызываемый класс). Возврат результата метода обычно включает в себя возврат другого типа, что может показаться пользователю класса неожиданным. Для этого есть пример близкого использования, когда некоторые кодеры возвращают self
из своих методов, чтобы учесть подобный поезду синтаксис:
my_font = SomeFont().italic().bold()
Наконец, если вам не нравится result = A().method(value)
, рассмотрите псевдоним:
func = A().method
...
result = func(value)
Обратите внимание, что вы остались без ссылки на экземпляр A () в вашем коде.
Если вам нужна ссылка, разделите ее дальше:
a = A()
func = a.method
...
result = func(value)
Если ссылка на A () не нужна, то вам, вероятно, тоже не нужен экземпляр, и класс просто группирует методы. Вы можете просто написать
func = A.method
result = func(value)
где бескорыстные методы должны быть украшены @staticmethod
, потому что здесь нет ни одного экземпляра Также обратите внимание, как статические методы можно превратить в простые функции вне классов.
Edit:
Я настроил пример, аналогичный тому, что вы пытаетесь выполнить.Также трудно судить, является ли использование методов для внедрения результатов в следующий метод лучшим выбором для многоэтапной процедуры.Поскольку они имеют некоторое общее состояние, они связаны друг с другом и, таким образом, также могут легче вводить ошибки друг другу.Я предполагаю, что вы хотите разделить некоторые данные между ними таким образом (и именно поэтому вы настраиваете их в классе):
Так что это пример класса, где открытый метод создает результат, вызывая цепочку внутреннихметоды.Все методы зависят от состояния объекта, в данном случае self.offset
, несмотря на получение входного значения для вычислений.
Из-за этого имеет смысл, что каждый метод использует self для доступа к состоянию.Также имеет смысл, что вы можете создавать экземпляры разных объектов, содержащих разные конфигурации, поэтому я не вижу здесь смысла для @staticmethod
или @classmethod
.
Начальная конфигурация экземпляра выполняется в __init__
как обычно.
# file: multistepinc.py
def __init__(self, offset):
self.offset = offset
def result(self, value):
return self._step1(value)
def _step1(self, x):
x = self._step2(x)
return self.offset + 1 + x
def _step2(self, x):
x = self._step3(x)
return self.offset + 2 + x
def _step3(self, x):
return self.offset + 3 + x
def get_multi_step_inc(offset):
return MultiStepInc(offset).result
--------
# file: multistepinc_example.py
from multistepinc import get_multi_step_inc
# get the result method of a configured
# MultiStepInc instance
# with offset = 10.
# Much like an object factory, but you
# mentioned to prefer to have the result
# method of the instance
# instead of the instance itself.
inc10 = get_multi_step_inc(10)
# invoke the inc10 method
result = inc10(1)
print(result)
# creating another instance with offset=2
inc2 = get_multi_step_inc(2)
result = inc2(1)
print(result)
# if you need to manipulate the object
# instance
# you have to (on file top)
from multistepinc import MultiStepInc
# and then
inc_obj = MultiStepInc(5)
# ...
# ... do something with your obj, then
result = inc_obj.result(1)
print(result)
Выходы:
37
13
22