Подтвердить что ты не робот

Есть ли причина для предоставления значения по умолчанию?

Я просматривал какой-то код, и я заметил линию, которая привлекла мое внимание. Код похож на приведенный ниже пример

class MyClass:
    def __init__(self):
        pass

    def call_me(self=''):
        print(self)

Это выглядит как любой другой класс, который я видел, однако str передается как значение по умолчанию для self.

Если я распечатаю self, он будет вести себя как обычно

>>> MyClass().call_me()
<__main__.MyClass object at 0x000002A12E7CA908>

Это прослушивало меня, и я не могу понять, почему это будет использовано. Есть ли причина, по которой экземпляр str будет передан как значение по умолчанию для self?

4b9b3361

Ответ 1

Не совсем, это просто странный способ заставить его не вызывать ошибку при вызове через класс:

MyClass.call_me()

отлично работает, поскольку, несмотря на то, что ничего не косвенно передается как с экземплярами, предоставляется значение по умолчанию для этого аргумента. Если не было задано значение по умолчанию, при вызове это, конечно, повысит значение TypeError для аргументов, которые все мы любим. Что касается того, почему он выбрал пустую строку в качестве значения, только он знает.

Внизу, это более запутанно, чем практично. Если вам нужно сделать что-то подобное, я бы посоветовал простой staticmethod аргумент по умолчанию для достижения аналогичного эффекта.

Таким образом, вы не преследуете никого, кто читает ваш код (например, разработчик, который написал это с вами; -):

@staticmethod
def call_me(a=''):
    print(a)

Если вам нужен доступ к атрибутам класса, вы всегда можете выбрать декоратор classmethod. Оба эти (class и static декораторы) также служат вторичной целью сделать ваше намерение кристально понятным для других, читающих ваш код.

Ответ 2

Короткий ответ - да. Таким образом, вы можете вызвать функцию как:

MyClass.call_me()

без создания экземпляра MyClass, который будет печатать пустую строку.

Чтобы дать более длинный ответ, нам нужно посмотреть, что происходит за кулисами.

Когда вы создаете экземпляр класса, вызываются __new__ и __init__, чтобы создать его, то есть:

a = MyClass()

примерно эквивалентен:

a = MyClass.__new__(MyClass)
MyClass.__init__(a)

Всякий раз, когда вы используете какой-либо метод для созданного экземпляра a:

a.call_me()

Он "заменяется" на MyClass.call_me(a).

Таким образом, наличие параметра по умолчанию для call_me позволяет вызывать эту функцию не только как метод экземпляра, но в этом случае self является самим экземпляром, но также и как метод статического класса.

Таким образом, вместо MyClass.call_me(a) вызывается только MyClass.call_me(). Поскольку список аргументов пуст, аргумент по умолчанию присваивается self и печатается желаемый результат (пустая строка).