Вызов staticmethod из класса __init__() вызывает «принимает 1 позиционный аргумент, но было задано 2» Ошибка типа

#python #visual-studio-code #static-methods

#python #visual-studio-code #статические методы

Вопрос:

Я создал класс со staticmethod:

 class DetfileDetector(Detector):
    def __init__(self, file_path, **kwargs):
        super().__init__(**kwargs)
        self.detections = self.parse_detfile(file_path)

    @staticmethod
    def parse_detfile(file_path):
        #do somthing with file_path
  

Когда я вызываю parse_defile без создания экземпляра класса, я получаю ожидаемый результат

 DetfileDetector.parse_detfile('foo.txt')
  

Однако, когда я вызываю его из функции init(), я получаю сообщение об ошибке:

Ошибка типа: parse_detfile() принимает 1 позиционный аргумент, но было задано 2

Я предполагаю, что смысл в том, что ‘self’ также передается в staticmethod, но это staticmethod, поэтому я ожидал, что self не будет передан.

Мои попытки исправить заключались в том, чтобы установить ‘file_path’ в качестве необязательного аргумента с None по умолчанию, но я получил TypeEroor из

Ошибка типа: parse_detfile() получил несколько значений для аргумента ‘file_path’

Я буду признателен, если кто-нибудь подскажет мне, как правильно его написать.

Редактировать: спасибо за ваши ответы, добавив дополнительную информацию:

  • Теперь я вижу, что он терпит неудачу, когда я запускаю его из «интерактивной оболочки python» VSCode (версия 1.50.0-insider), но проходит при запуске из командной строки или без интерактивной оболочки. Я сообщу об этой проблеме разработчикам VSCode.
  • Я использую python 3.7.7

Edit2: содержимое Detector класса

 class Detector:
    def __init__(self, **kwargs):
        self.every = kwargs.pop('every', 1)
        self.min_confidence = kwargs.pop('min_confidence', .8)
        self.min_wh = kwargs.pop('min_wh', 5)
        self.min_ar = kwargs.pop('min_ar', .1)
        self.sensor_noise_cov = np.square(np.diag(kwargs.pop('sensor_noise', [10, 10, 1, 10])))
        self.classes = object_classes(kwargs.pop('cars_only', True))
  

Комментарии:

1. Я не могу воспроизвести вашу ошибку. Это работает, как показано в моем ответе ниже.

2. Можете ли вы поделиться содержимым Detector class ?

3. @PraysonW. Дэниел, я отредактировал вопрос с помощью Detector

Ответ №1:

Ваш код на самом деле правильный.

Я протестировал его с помощью Python 3.8 и не увидел никаких проблем.

Вы можете вызвать staticmethod, используя класс или экземпляр этого класса.

Смотрите здесь: https://docs.python.org/3/library/functions.html#staticmethod

Он работал так даже в более старых версиях Python, я проверил весь путь до Python 2.7. Так что остается загадкой, почему вы получаете эту ошибку.

Может быть, дать больше контекста для вашего кода?

Комментарии:

1. Это тоже было мое предложение. Проблема не в коде, который представлен здесь

2. @PraysonW. Дэниел, мы на одной странице. Мне любопытно, откуда берется проблема.

3. Мне тоже интересно. Возможно, что-то в Detector ?

4. Спасибо, Прайсон В. Дэниел и Хокли за ваши ответы, я отредактировал вопрос с дополнительной информацией

Ответ №2:

Я думаю, что проблема не в коде, который вы показали. Протестировано на Python 3.6, это работает:

 class Detector:
    pass

class DetfileDetector(Detector):
    def __init__(self, file_path, **kwargs):
        super().__init__(**kwargs)
        self.detections = self.parse_detfile(file_path)

    @staticmethod
    def parse_detfile(file_path):
        #do somthing with file_path
        print(file_path)


DetfileDetector('get.txt')
# get.txt

DetfileDetector.parse_detfile('tex.txt')
# tex.txt
  

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

Поэтому проверьте Detector и посмотрите, есть ли проблема.

Ответ №3:

Измените свой код на это, и он должен работать

 class DetfileDetector(Detector):
    def __init__(self, file_path, **kwargs):
        super().__init__(**kwargs)
        self.detections = DetfileDetector.parse_detfile(file_path)

    @staticmethod
    def parse_detfile(file_path):
        #do somthing with file_path
  

Комментарии:

1. Было бы лучше использовать self.detections = self.parse_detfile(file_path) , потому что это не требует жесткого кодирования имени класса в коде (и его не нужно было бы изменять, если имя содержащего класса когда-либо изменится).

Ответ №4:

Я предполагаю, что смысл в том, что ‘self’ также передается в staticmethod, но это staticmethod, поэтому я ожидал, что self не будет передан.

Правильно.

Половина смысла a staticmethod заключается в том, что вам не нужен экземпляр. Однако он по-прежнему является атрибутом класса, а не функцией верхнего уровня, поэтому:

Я буду признателен, если кто-нибудь подскажет мне, как правильно его написать.

вам нужно искать его внутри класса, таким образом:

 def __init__(self, file_path, **kwargs):
    super().__init__(**kwargs)
    self.detections = DetfileDetector.parse_detfile(file_path)
  

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

Ответ №5:

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

Как вы можете видеть ниже, проблема вызвана тем, что я вызываю file1.Foo и предоставляю параметр, хотя его конструктор не принимает ни одного параметра. Я был сбит с толку, потому что упоминается ошибка Foo.__init__() , поэтому я подумал, что это относится к Foo классу in file1.py или к тому, в file2.py котором он находится.

file1.py

 class Foo():
    def __init__(self):
        print('Hello from file1.py')
  

file2.py

 import file1

class Foo():

    def __init__(self, text):
        pass

    def f1(text):
        return 'Hello from f1 - '   text

    def f2(self):
        bar = file1.Foo(Foo.f1('a'))

a = Foo()
a.f2()
  

Результаты выполнения

 python file2.py
  
 Traceback (most recent call last):
  File "/home/myusername/e/file2.py", line 15, in <module>
    a.f2()
  File "/home/myusername/e/file2.py", line 12, in f2
    bar = file1.Foo(Foo.f1('a'))
TypeError: Foo.__init__() takes 1 positional argument but 2 were given
  

Как и следовало ожидать, проблема была просто решена путем добавления параметра в конструктор file1.py .

file1.py

 class Foo():
    def __init__(self, text):
        print(f'Hello from file1.py')
  

file2.py

 import file1

class Foo():

    def __init__(self):
        pass

    def f1(text):
        return 'Hello from f1 - '   text

    def f2(self):
        bar = file1.Foo(Foo.f1('a'))

a = Foo()
a.f2()
  

Результаты выполнения

 python file2.py
  
 Hello from file1.py
  

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