Плохо ли вызывать метод класса как метод экземпляра?
Заголовок: Правильно ли использовать методы класса без явного обращения к классу в Python?
Я столкнулся с вопросом, касающимся использования методов класса в Python. Вот пример кода, который у меня есть:
class C(object):
@classmethod
def f(cls, x):
return x + x
Этот код работает следующим образом:
c = C()
print(c.f(2)) # Вывод: 4
Однако, возникает вопрос: является ли такой подход плохой практикой? Должен ли я вызывать метод так:
C.f(2)
или же так:
c.__class__.f(2)
Я понимаю, что это имеет смысл только в тех случаях, когда метод f
не взаимодействует с self
/cls
, ожидая, что это будет класс.
Какой из этих вариантов считается более корректным и соответствует принципам хорошего стиля программирования в Python?
5 ответ(ов)
Если вас тянет вызвать метод класса из экземпляра, вероятно, вам не нужен метод класса.
В приведенном вами примере статический метод будет более подходящим именно из-за последнего замечания (отсутствие взаимодействия с self/cls).
class C(object):
@staticmethod
def f(x):
return x + x
Таким образом, "правильный подход" здесь позволяет делать как
c = C()
c.f(2)
так и
C.f(2)
Я не припоминаю случаев использования класса-метода из вне, но, безусловно, нормально, если метод экземпляра вызывает класс-метод на себе (например, self.foo()
, где foo
— это класс-метод). Это гарантирует, что наследование работает как ожидается, и вызов .foo()
произойдет в правильном подклассе, а не в базовом классе.
Это в основном просто сбивает с толку. Если бы я использовал ваш класс и увидел это, у меня бы возникли сомнения по поводу других «сюрпризов», которые могут скрываться внутри. Это выглядит как плохой дизайн.
Есть ли причина, по которой это реализовано не как статический метод?
C.f()
более понятен, чем c_instance.f()
, а c_instance.__class__.f()
выглядит просто ужасно. Поскольку ясность и красота являются очень важными характеристиками в Python-сообществе, я бы сказал, что C.f()
— это наилучший вариант.
Есть ли у вас какие-то конкретные причины, по которым вы хотите вызывать метод именно так или иначе?
В вашем коде действительно присутствует интересный механизм взаимодействия между обычными методами и методами класса. Давайте по шагам рассмотрим, как это работает, и почему это не вызывает ошибок в Python 3.6.
Вы создали класс A
с обычным методом a
, который вызывает два метода класса b
и c
. Это совершенно допустимо, поскольку методы класса имеют доступ к классу через аргумент cls
, даже если они вызываются из обычного метода экземпляра.
Вот краткая разбивка, что происходит при выполнении вашего кода:
- Создается экземпляр класса
A
под именемb
. - Вызывается метод
a
с аргументом3
. - Внутри метода
a
выполняется выводprint
, который выводит информацию о текущем экземпляре и переданном числе. - Затем вызывается метод класса
b
, который, как видно, соответствует синтаксису, позволяющему ему действовать независимо от конкретного экземпляра класса. - В методе
b
также происходит вывод информации, и здесь используется переданное число, увеличенное на единицу. - Метод
b
затем вызывает метод классаc
, передавая число, которое будет умножено на 2.
В итоге вы видите, что, несмотря на то что метод b
и c
являются методами класса, они вызываются из обычного метода экземпляра, и это работает без каких-либо ошибок или исключений.
Таким образом, код деликатно подчеркивает гибкость Python, где обычные методы экземпляра могут взаимодействовать с методами класса, сохраняя при этом весь функционал.
Если вам нужно больше разъяснений или у вас есть другие вопросы, пожалуйста, дайте знать!
Как изменить порядок столбцов в DataFrame?
'pip' не распознан как командa внутреннего или внешнего формата
Почему statistics.mean() работает так медленно?
Преобразование строки даты JSON в datetime в Python
Есть ли разница между поднятием экземпляра класса Exception и самого класса Exception?