Почему метод класса Python, объявленный без "self" и без декораторов, не вызывает исключения? - PullRequest
0 голосов
/ 16 октября 2018

Я думал, что следующий код приведет к ошибке, потому что, насколько я читал, метод в классе Python должен иметь либо «self» (или любую другую метку, но «self» по соглашению) в качестве первогоаргумент, или «cls», или аналогичный, если используется декоратор @classmethod, или нет, если используется декоратор @staticmethod.

Почему я не получаю ошибку при запуске этого с Python 3.5 в терминале, дажехотя test_method не соответствует этим требованиям?Кажется, он работает как статический метод, но без декоратора.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys

class MyClass:

    def test_method(args):
        print(args[1])

    @staticmethod
    def static_method():
        print("static_method")

    @classmethod
    def class_method(cls):
        print("class_method")


def main(args):
    MyClass.test_method(args)


if __name__ == '__main__':
    sys.exit(main(sys.argv))

Вывод:

$ python3 testscript.py "testing"
$ testing

РЕДАКТИРОВАТЬ :

Myвопрос также можно сформулировать по-другому, отвлекая внимание от self и @staticmethod: «Почему я получаю, казалось бы, работающий статический метод без декоратора @staticmethod?»

Ответы [ 3 ]

0 голосов
/ 16 октября 2018

В этом нет ничего особенного.В питоне 3 нет разницы между функцией, определенной внутри класса, и функцией, определенной вне класса.Они оба нормальные функции.

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

Однако, если вы немного измените свой код, чтобы он выглядел следующим образом, вы получите ожидаемую ошибку.

def main(args):
    MyClass().test_method(args)
    # Should throw an error

РЕДАКТИРОВАНИЕ:

  • @staticmethod будет работать с обоими экземплярами класса, такими как MyClass().test_method(args), и только с обычным прямым вызовом, таким как MyClass.test_method(args)
  • Однакообычный метод (без self в нем) не может быть вызван для экземпляра класса.Так что вам всегда придется называть это MyClass.test_method(args)
0 голосов
/ 16 октября 2018

В Python 2 функции, определенные в теле класса, автоматически преобразуются в «несвязанные методы» и не могут вызываться напрямую без декоратора статического метода.В Python 3 эта концепция была удалена;MyClass.text_method - это простая функция, которая находится внутри пространства имен MyClass и может вызываться напрямую.

Основная причина по-прежнему использовать staticmethod в Python 3 состоит в том, что вы также хотите вызывать метод для экземпляр .Если вы не используете декоратор, метод всегда будет передавать экземпляр в качестве первого параметра, вызывая ошибку TypeError.

0 голосов
/ 16 октября 2018

self необязательно.Однако, если вы хотите сослаться на любую переменную или значение, связанное с объектом (создание экземпляра класса) (например, для класса об автомобилях, это скорость, self.speed), вам нужно иметь self в качестве параметрав функции.По этой причине обычной практикой является всегда указывать self в качестве аргумента, в противном случае вы на самом деле не используете класс по правильной причине.

EDIT: на самом деле это вызовет ошибку, если вы выполните следующее:

class a():
    def __init__(self, x):
        self.asd = x
    def hello(x):
        print(x)

>>> g = a(4)
>>> g.hello(5)

Как и при вызове «hello», оба «self» и «4» будут переданы в качестве параметров.Это будет работать в следующем случае, о чем я говорил выше:

>>> g = a
>>> g.hello(4)

или

>>> a.hello(4)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...