несвязанный метод f () должен вызываться с экземпляром fibo_ в качестве первого аргумента (вместо этого был получен экземпляр classobj)

140

В Python я пытаюсь запустить метод в классе и получаю сообщение об ошибке:

Traceback (most recent call last):
  File "C:\Users\domenico\Desktop\py\main.py", line 8, in <module>
    fibo.f()
  TypeError: unbound method f() must be called with fibo instance 
  as first argument (got nothing instead)

Код: (swineflu.py)

class fibo:
    a=0
    b=0

    def f(self,a=0):
        print fibo.b+a
        b=a;
        return self(a+1)

Скрипт main.py

import swineflu

f = swineflu
fibo = f.fibo

fibo.f()            #TypeError is thrown here

Что означает эта ошибка? Что вызывает эту ошибку?

КуполWTF
источник
1
Вы хотите создать экземпляр объекта или нет?
Thomas
2
Название класса должно быть написано с заглавной буквы.
CDT
1
fibo = f.fibo()Необходимо создать экземпляр класса с помощью скобок.
Kotlinboy
Вы можете использоватьfibo().f()
Беньямин Джафари

Ответы:

179

Хорошо, во-первых, вам не нужно получать ссылку на модуль под другим именем; у вас уже есть ссылка (из import), и вы можете просто использовать ее. Если вы хотите другое имя, просто используйте import swineflu as f.

Во-вторых, вы получаете ссылку на класс, а не создаете его экземпляр.

Так должно быть:

import swineflu

fibo = swineflu.fibo()  # get an instance of the class
fibo.f()                # call the method f of the instance

Связанный метод является тот , который присоединен к экземпляру объекта. Несвязанные методы , конечно, тот , который не присоединен к экземпляру. Ошибка обычно означает, что вы вызываете метод в классе, а не в экземпляре, что и произошло в данном случае, потому что вы не создали экземпляр класса.

любезный
источник
1
Вы также можете сделать это, swineflu.fibo().f()если позвоните ему только один раз.
Kit
81

Как воспроизвести эту ошибку, используя как можно меньше строк:

>>> class C:
...   def f(self):
...     print "hi"
...
>>> C.f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method f() must be called with C instance as 
first argument (got nothing instead)

Это не удается из-за TypeError, потому что вы сначала не создали экземпляр класса, у вас есть два варианта: 1: либо сделать метод статическим, чтобы вы могли запускать его статическим способом, либо 2: создать экземпляр своего класса, чтобы у вас был экземпляр для захвата на, чтобы запустить метод.

Похоже, вы хотите запустить метод статическим способом, сделайте следующее:

>>> class C:
...   @staticmethod
...   def f():
...     print "hi"
...
>>> C.f()
hi

Или вы, вероятно, имели в виду использовать созданный экземпляр следующим образом:

>>> class C:
...   def f(self):
...     print "hi"
...
>>> c1 = C()
>>> c1.f()
hi
>>> C().f()
hi

Если это вас смущает, задайте следующие вопросы:

  1. В чем разница между поведением статического метода и поведением обычного метода?
  2. Что значит создать экземпляр класса?
  3. Различия между запуском статических методов и обычными методами.
  4. Различия между классом и объектом.
Эрик Лещински
источник
Я создал экземпляр своего класса, но он работает только при использовании @staticmethod. Это можно объяснить?
abeltre1
9

fibo = f.fiboссылается на сам класс. Вероятно, вы хотели fibo = f.fibo()(обратите внимание на круглые скобки) создать экземпляр класса, после чего все fibo.f()должно пройти правильно.

f.fibo.f()терпит неудачу, потому что вы, по сути, звоните, f(self, a=0)не предоставляя self; self"привязывается" автоматически, когда у вас есть экземпляр класса.

Марк Рушаков
источник
4

fявляется методом (экземпляра). Однако вы вызываете его через fibo.f, где fiboнаходится объект класса. Следовательно, fне привязан (не привязан ни к одному экземпляру класса).

Если бы ты сделал

a = fibo()
a.f()

тогда это fпривязано (к экземпляру a).

Лиджи
источник
2
import swineflu

x = swineflu.fibo()   # create an object `x` of class `fibo`, an instance of the class
x.f()                 # call the method `f()`, bound to `x`. 

Вот хороший учебник, чтобы начать работу с классами в Python.

user225312
источник
2

В Python 2 (3 имеет другой синтаксис):

Что делать, если вы не можете создать экземпляр своего родительского класса до того, как вам понадобится вызвать один из его методов?

Используйте super(ChildClass, self).method()для доступа к родительским методам.

class ParentClass(object):
    def method_to_call(self, arg_1):
        print arg_1

class ChildClass(ParentClass):
    def do_thing(self):
        super(ChildClass, self).method_to_call('my arg')
Питер Грэм
источник
0

Различия в версиях Python 2 и 3:

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

Если вам нужны методы класса, но вы объявили их как методы экземпляра.

Метод экземпляра - это метод, который используется при создании экземпляра класса.

Примером может быть

   def user_group(self):   #This is an instance method
        return "instance method returning group"

Метод метки класса:

   @classmethod
   def user_group(groups):   #This is an class-label method
        return "class method returning group"

В версиях python 2 и 3 различаются классы @classmethod для записи в python 3, он автоматически получает это как метод метки класса и не нужно писать @classmethod, я думаю, это может вам помочь.

Прожеш Бхумик
источник
0

Попробуй это. Для python 2.7.12 нам нужно определить конструктор или добавить self к каждому методу с последующим определением экземпляра класса с именем object.

import cv2

class calculator:

#   def __init__(self):

def multiply(self, a, b):
    x= a*b
    print(x)

def subtract(self, a,b):
    x = a-b
    print(x)

def add(self, a,b):
    x = a+b
    print(x)

def div(self, a,b):
    x = a/b
    print(x)

 calc = calculator()
 calc.multiply(2,3)
 calc.add(2,3)
 calc.div(10,5)
 calc.subtract(2,3)
НИХИЛ БХАЛОДИЯ
источник