TypeError: method () accetta 1 argomento posizionale ma ne sono stati forniti 2


271

Se ho una lezione ...

class MyClass:

    def method(arg):
        print(arg)

... che utilizzo per creare un oggetto ...

my_object = MyClass()

... su cui chiamo method("foo")così ...

>>> my_object.method("foo")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: method() takes exactly 1 positional argument (2 given)

... perché Python mi dice che gli ho dato due argomenti, quando ne ho dato solo uno?


Quel messaggio ha innumerevoli cause; il motivo specifico qui è che tutti i metodi di istanza prevedono un primo argomento che di solito chiamiamo self. Quindi dichiarare def method(arg):è sbagliato per un metodo, dovrebbe essere def method(self, arg):. Quando il metodo di invio tenta di richiamare method(arg):e abbinare due parametri self, argcontro di esso, si ottiene quell'errore.
smci

Risposte:


368

In Python, questo:

my_object.method("foo")

... è lo zucchero sintattico , che l'interprete traduce dietro le quinte in:

MyClass.method(my_object, "foo")

... che, come puoi vedere, ha davvero due argomenti: è solo che il primo è implicito, dal punto di vista del chiamante.

Questo perché la maggior parte dei metodi funziona un po 'con l'oggetto a cui sono chiamati, quindi deve esserci un modo per far riferimento quell'oggetto all'interno del metodo. Per convenzione, questo primo argomento è chiamato selfall'interno della definizione del metodo:

class MyNewClass:

    def method(self, arg):
        print(self)
        print(arg)

Se si chiama method("foo")un'istanza di MyNewClass, funziona come previsto:

>>> my_new_object = MyNewClass()
>>> my_new_object.method("foo")
<__main__.MyNewClass object at 0x29045d0>
foo

Di tanto in tanto (ma non spesso), davvero non importa circa l'oggetto che il metodo è destinato a, e in quella circostanza, si può decorare il metodo con il comando incorporato staticmethod()la funzione di dirlo:

class MyOtherClass:

    @staticmethod
    def method(arg):
        print(arg)

... nel qual caso non è necessario aggiungere un selfargomento alla definizione del metodo, e funziona ancora:

>>> my_other_object = MyOtherClass()
>>> my_other_object.method("foo")
foo

99
In breve: l'aggiunta selfcome primo argomento al metodo risolve il problema.
amoebe,

@amoebe - il mio tipo di persona
Carlos,

21

Qualcos'altro da considerare quando si incontra questo tipo di errore:

Mi sono imbattuto in questo messaggio di errore e ho trovato utile questo post. Risulta che nel mio caso avevo scavalcato un luogo in __init__()cui c'era l'ereditarietà degli oggetti.

L'esempio ereditato è piuttosto lungo, quindi passerò a un esempio più semplice che non utilizza l'ereditarietà:

class MyBadInitClass:
    def ___init__(self, name):
        self.name = name

    def name_foo(self, arg):
        print(self)
        print(arg)
        print("My name is", self.name)


class MyNewClass:
    def new_foo(self, arg):
        print(self)
        print(arg)


my_new_object = MyNewClass()
my_new_object.new_foo("NewFoo")
my_bad_init_object = MyBadInitClass(name="Test Name")
my_bad_init_object.name_foo("name foo")

Il risultato è:

<__main__.MyNewClass object at 0x033C48D0>
NewFoo
Traceback (most recent call last):
  File "C:/Users/Orange/PycharmProjects/Chapter9/bad_init_example.py", line 41, in <module>
    my_bad_init_object = MyBadInitClass(name="Test Name")
TypeError: object() takes no parameters

PyCharm non ha riscontrato questo errore di battitura. Né Notepad ++ (altri editor / IDE potrebbero).

Certo, si tratta di un TypeError "non accetta parametri", non è molto diverso da "ottenerne due" quando ne prevede uno, in termini di inizializzazione dell'oggetto in Python.

Affrontare l'argomento: un inizializzatore di sovraccarico verrà utilizzato se sintatticamente corretto, ma in caso contrario verrà ignorato e verrà invece utilizzato il built-in. L'oggetto non si aspetta / gestisce questo e viene generato l'errore.

Nel caso dell'errore sytax: la correzione è semplice, basta modificare l'istruzione init personalizzata:

def __init__(self, name):
    self.name = name

1
Non c'è SyntaxErrorqui. Il codice è sintatticamente corretto; definisce correttamente un metodo chiamato ___init__, che nessuno chiamerà mai, invece del metodo speciale __init__. Ecco perché non viene rilevato alcun errore, perché non ce n'è uno da rilevare.
abarnert,

14

In parole semplici.

In Python dovresti aggiungere l' selfargomento come primo argomento a tutti i metodi definiti nelle classi:

class MyClass:
  def method(self, arg):
    print(arg)

Quindi puoi usare il tuo metodo in base al tuo intuito:

>>> my_object = MyClass()
>>> my_object.method("foo")
foo

Questo dovrebbe risolvere il tuo problema :)

Per una migliore comprensione, puoi anche leggere le risposte a questa domanda: qual è lo scopo di sé?


2
Cosa c'è di sbagliato in questa risposta? Perché qualcuno le ha dato un punto negativo? Dopotutto, è la risposta alla domanda e si distingue per la sua semplicità rispetto ad altre risposte, che può essere importante per alcune persone che cercano una risposta. No?
simhumileco,

10

Nuovo arrivato in Python, ho riscontrato questo problema quando utilizzavo la **funzionalità di Python in modo errato. Cercare di chiamare questa definizione da qualche parte:

def create_properties_frame(self, parent, **kwargs):

l'utilizzo di una chiamata senza una doppia stella stava causando il problema:

self.create_properties_frame(frame, kw_gsp)

TypeError: create_properties_frame () accetta 2 argomenti posizionali ma ne sono stati forniti 3

La soluzione è aggiungere **all'argomento:

self.create_properties_frame(frame, **kw_gsp)

1
Provenendo da JavaScript, mi aspetto di poter passare un elenco o un dizionario come argomento. Ma sembra che non sia così che funziona Python: devi distruggere l'elenco con * o **, quest'ultimo essendo un elenco di argomenti con parole chiave.
Little Brain,

1
@LittleBrain: sì, puoi passare un elenco (o dict) se vuoi che vengano trattati come un elenco (/ dict) all'interno della funzione. Ma se vuoi che i loro valori individuali vengano decompressi e confrontati con args (/ kwargs) nella funzione, allora hai bisogno della sintassi *args(/ **kwargs).
smci

9

Si verifica quando non si specifica il no di parametri __init__()o qualsiasi altro metodo che si sta cercando.

Per esempio:

class Dog:
    def __init__(self):
        print("IN INIT METHOD")

    def __unicode__(self,):
        print("IN UNICODE METHOD")

    def __str__(self):
        print("IN STR METHOD")

obj=Dog("JIMMY",1,2,3,"WOOF")

Quando esegui il programma sopra, ti dà un errore del genere:

TypeError: __init __ () accetta 1 argomento posizionale ma ne sono stati forniti 6

Come possiamo liberarci di questa cosa?

Basta passare i parametri, quale __init__()metodo cercare

class Dog:
    def __init__(self, dogname, dob_d, dob_m, dob_y, dogSpeakText):
        self.name_of_dog = dogname
        self.date_of_birth = dob_d
        self.month_of_birth = dob_m
        self.year_of_birth = dob_y
        self.sound_it_make = dogSpeakText

    def __unicode__(self, ):
        print("IN UNICODE METHOD")

    def __str__(self):
        print("IN STR METHOD")


obj = Dog("JIMMY", 1, 2, 3, "WOOF")
print(id(obj))

1

Dovresti effettivamente creare una classe:

class accum:
    def __init__(self):
        self.acc = 0
    def accumulator(self, var2add, end):
        if not end:
            self.acc+=var2add
    return self.acc

0

Nel mio caso, ho dimenticato di aggiungere il ()

Stavo chiamando il metodo in questo modo

obj = className.myMethod

Ma dovrebbe essere così

obj = className.myMethod()

-1

Passare il clsparametro in @classmethodper risolvere questo problema.

@classmethod
def test(cls):
    return ''
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.