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.