TypeError: method () mengambil 1 argumen posisi tetapi 2 diberikan

271

Jika saya memiliki kelas ...

class MyClass:

    def method(arg):
        print(arg)

... yang saya gunakan untuk membuat objek ...

my_object = MyClass()

... yang saya sebut method("foo")seperti itu ...

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

... mengapa Python memberitahuku bahwa aku memberikan dua argumen, padahal aku hanya memberikan satu?

Zero Piraeus
sumber
Pesan itu memiliki beberapa penyebab; alasan spesifik di sini adalah bahwa semua metode instance mengharapkan argumen pertama yang menurut kebiasaan kita panggil self. Jadi, menyatakan def method(arg):metode itu salah, seharusnya begitu def method(self, arg):. Ketika metode pengiriman mencoba untuk memanggil method(arg):dan mencocokkan dua parameter self, argterhadapnya, Anda mendapatkan kesalahan itu.
smci

Jawaban:

368

Dengan Python, ini:

my_object.method("foo")

... adalah gula sintaksis , yang diterjemahkan oleh penerjemah di belakang layar menjadi:

MyClass.method(my_object, "foo")

... yang, seperti yang Anda lihat, memang memiliki dua argumen - hanya saja yang pertama adalah implisit, dari sudut pandang si penelepon.

Ini karena sebagian besar metode melakukan beberapa pekerjaan dengan objek yang mereka panggil, jadi perlu ada beberapa cara agar objek tersebut dirujuk di dalam metode. Dengan konvensi, argumen pertama ini disebut selfdi dalam definisi metode:

class MyNewClass:

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

Jika Anda memanggil method("foo")sebuah instance MyNewClass, itu berfungsi seperti yang diharapkan:

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

Kadang-kadang (tetapi tidak sering), Anda benar - benar tidak peduli dengan objek yang terikat metode Anda, dan dalam keadaan itu, Anda dapat menghias metode dengan staticmethod()fungsi bawaan untuk mengatakannya:

class MyOtherClass:

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

... dalam hal ini Anda tidak perlu menambahkan selfargumen ke definisi metode, dan masih berfungsi:

>>> my_other_object = MyOtherClass()
>>> my_other_object.method("foo")
foo
Zero Piraeus
sumber
99
Singkatnya: Menambahkan selfargumen pertama ke metode akan menyelesaikan masalah.
amoebe
@amoebe - tipe orang saya
Carlos
21

Hal lain yang perlu dipertimbangkan ketika jenis kesalahan ini ditemukan:

Saya menemukan pesan kesalahan ini dan menemukan posting ini bermanfaat. Ternyata dalam kasus saya, saya telah menimpa di __init__()mana ada objek warisan.

Contoh yang diwarisi agak panjang, jadi saya akan beralih ke contoh yang lebih sederhana yang tidak menggunakan warisan:

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")

Hasilnya adalah:

<__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 tidak menangkap kesalahan ketik ini. Notepad ++ (kekuatan editor / IDE lain) juga tidak.

Memang, ini adalah TypeError "tidak mengambil parameter", itu tidak jauh berbeda dari "punya dua" ketika mengharapkan satu, dalam hal inisialisasi objek dalam Python.

Mengatasi topik: Inisialisasi overloading akan digunakan jika secara sintaksis benar, tetapi jika tidak akan diabaikan dan built-in digunakan sebagai gantinya. Objek tidak akan mengharapkan / menangani ini dan kesalahan dilemparkan.

Dalam kasus kesalahan sytax: Perbaikannya sederhana, cukup edit pernyataan init khusus:

def __init__(self, name):
    self.name = name
Jonru2016
sumber
1
Tidak ada SyntaxErrordisini. Kode secara sintaksis benar; itu dengan tepat mendefinisikan metode bernama ___init__, yang tidak akan pernah dipanggil oleh siapa pun, alih-alih metode khusus __init__. Itu sebabnya tidak ada kesalahan yang terdeteksi — karena tidak ada yang terdeteksi.
abarnert
14

Dengan kata-kata sederhana.

Dalam Python Anda harus menambahkan selfargumen sebagai argumen pertama ke semua metode yang didefinisikan di kelas:

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

Kemudian Anda dapat menggunakan metode Anda sesuai dengan intuisi Anda:

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

Ini harus menyelesaikan masalah Anda :)

Untuk pemahaman yang lebih baik, Anda juga dapat membaca jawaban atas pertanyaan ini: Apa tujuan diri?

simhumileco
sumber
2
Apa yang salah dengan jawaban ini? Mengapa seseorang memberinya poin negatif? Bagaimanapun, itu adalah jawaban untuk pertanyaan dan dibedakan oleh kesederhanaannya dibandingkan dengan jawaban lain, yang mungkin penting bagi beberapa orang yang mencari jawaban. Bukan?
simhumileco
10

Pendatang baru di Python, saya mengalami masalah ini ketika saya menggunakan fitur Python **dengan cara yang salah. Mencoba memanggil definisi ini dari suatu tempat:

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

menggunakan panggilan tanpa bintang ganda menyebabkan masalah:

self.create_properties_frame(frame, kw_gsp)

TypeError: create_properties_frame () mengambil 2 argumen posisi tetapi 3 diberikan

Solusinya adalah dengan menambahkan **argumen:

self.create_properties_frame(frame, **kw_gsp)
Stanislav Pankevich
sumber
1
Berasal dari JavaScript, saya berharap dapat melewati daftar atau kamus sebagai argumen. Tapi sepertinya itu bukan cara kerja Python: Anda harus merusak daftar dengan * atau **, yang terakhir adalah untuk daftar argumen kata kunci.
Little Brain
1
@LittleBrain: ya Anda bisa memberikan daftar (atau dict) jika Anda ingin mereka diperlakukan sebagai daftar (/ dict) di dalam fungsi. Tetapi jika Anda ingin nilai masing-masing dibongkar dan dicocokkan dengan args (/ kwargs) dalam fungsi, maka Anda memerlukan sintaks *args(/ **kwargs).
smci
9

Ini terjadi ketika Anda tidak menentukan parameter no __init__()atau metode lain yang dicari.

Sebagai contoh:

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")

Ketika Anda menjalankan program di atas, itu memberi Anda kesalahan seperti itu:

TypeError: __init __ () mengambil 1 argumen posisi tetapi 6 diberikan

Bagaimana kita bisa menyingkirkan hal ini?

Cukup berikan parameter, __init__()metode apa yang dicari

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))
Trinadh Koya
sumber
1

Anda sebenarnya harus membuat kelas:

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

Dalam kasus saya, saya lupa menambahkan ()

Saya memanggil metode seperti ini

obj = className.myMethod

Tapi harusnya begini

obj = className.myMethod()
Justice Bringer
sumber
-1

Lewati clsparameter ke @classmethoduntuk mengatasi masalah ini.

@classmethod
def test(cls):
    return ''
Ruan Nawe
sumber