TypeError:method()は1つの位置引数を取りますが、2つが指定されました


271

クラスがあると...

class MyClass:

    def method(arg):
        print(arg)

...オブジェクトの作成に使用します...

my_object = MyClass()

...私はそのmethod("foo")ように呼んでいます...

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

...なぜPythonは2つの引数を与えたのに、1つしか与えなかったのですか?


そのメッセージには多くの原因があります。ここでの特定の理由は、すべてのインスタンスメソッドが、カスタムで呼び出す最初の引数を期待するためですself。したがってdef method(arg):、メソッドの宣言は間違っていますdef method(self, arg):。メソッドディスパッチがmethod(arg):2つのパラメーターを呼び出して照合しようとすると、self, argそのエラーが発生します。
smci

回答:


368

Pythonでは、これ:

my_object.method("foo")

... 構文糖であり、インタプリタが舞台裏で次のように変換します。

MyClass.method(my_object, "foo")

...ご覧のとおり、実際には2つの引数があります-呼び出し元の観点からすると、最初の引数は暗黙的です。

これは、ほとんどのメソッドが呼び出されたオブジェクトを処理するため、メソッド内でそのオブジェクトを参照する方法が必要になるためです。慣例により、この最初の引数はselfメソッド定義内で呼び出されます。

class MyNewClass:

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

method("foo")インスタンスを呼び出すと、MyNewClass期待どおりに動作します。

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

ときどき(ただし、それほど頻繁ではありませんが)、メソッドがバインドされているオブジェクトを本当に気にしなくても、その場合は、組み込み関数を使用してメソッドを修飾し、次のstaticmethod()ように言うことができます。

class MyOtherClass:

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

...その場合self、メソッド定義に引数を追加する必要はなく、それでも機能します。

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

99
つまりself、メソッドに最初の引数として追加すると、問題が解決します。
amoebe 2017年

@amoebe-私のタイプの人
Carlos

21

このタイプのエラーが発生したときに考慮すべき他のこと:

私はこのエラーメッセージに遭遇し、この投稿が役に立ちました。私の場合、__init__()オブジェクトの継承があった場所をオーバーライドしたことがわかりました。

継承された例はかなり長いので、継承を使用しないより単純な例にスキップします。

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

結果は次のとおりです。

<__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はこのタイプミスを理解できませんでした。Notepad ++もしませんでした(他のエディター/ IDEの可能性があります)。

確かに、これは「パラメータをとらない」TypeErrorであり、Pythonでのオブジェクトの初期化に関して、1つを期待する場合は「2つ取得」とそれほど変わりません。

トピックの対処:構文的に正しい場合はオーバーロード初期化子が使用されますが、そうでない場合は無視され、代わりに組み込みが使用されます。オブジェクトはこれを予期/処理せず、エラーがスローされます。

構文エラーの場合:修正は簡単です。カスタムのinitステートメントを編集するだけです。

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

1
SyntaxErrorここはありません。コードは構文的に正しいです。これ___init__は、特別なメソッドではなく、と呼ばれるメソッドを正しく定義します__init__。エラーが検出されないのはそのためです。検出するエラーがないためです。
abarnert

14

簡単な言葉で。

Pythonではself、クラスのすべての定義済みメソッドに最初の引数として引数を追加する必要があります。

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

次に、直感に従ってメソッドを使用できます。

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

これはあなたの問題を解決するはずです:)

よりよく理解するために、この質問への回答を読むこともできます:自己の目的は何ですか?


2
この答えの何が問題になっていますか?なぜ誰かが彼女に否定的なポイントを与えたのですか?結局のところ、それは質問への回答であり、他の回答と比較してその単純さによって区別されます。これは、回答を探している一部の人々にとって重要かもしれません。だよね?
simhumileco

10

Pythonの初心者ですが、Pythonの**機能を間違って使用しているときにこの問題が発生しました。どこかからこの定義を呼び出そうとしています:

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

ダブルスターなしで通話を使用すると問題が発生していました:

self.create_properties_frame(frame, kw_gsp)

TypeError:create_properties_frame()は2つの位置引数を取りますが、3つが指定されました

解決策は**引数に追加することです:

self.create_properties_frame(frame, **kw_gsp)

1
JavaScriptから来るので、リストまたは辞書を引数として渡すことができると期待しています。しかし、それはPythonが機能する方法ではないようです:*または**でリストを分解する必要があります。後者はキーワード付き引数リスト用です。
リトルブレイン

1
@LittleBrain:はい、関数内でリスト(/ dict)として扱いたい場合は、リスト(またはdict)を渡すことができます。ただし、個別の値をアンパックして、関数の引数(/ kwargs)と照合する場合は、*args(/ **kwargs)構文が必要です。
smci

9

パラメータの数を指定しない場合に発生します __init__()や場合や、他のメソッドが探している。

例えば:

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

上記のプログラムを実行すると、次のようなエラーが発生します。

TypeError:__init __()は1つの位置引数を取りますが、6つが指定されました

どうすればこれを取り除くことができますか?

パラメータを渡すだけで、どの__init__()メソッドが探しているのか

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

実際にクラスを作成する必要があります。

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

0

私の場合、追加するのを忘れていました ()

私はこのようなメソッドを呼び出していました

obj = className.myMethod

でもこうあるべきです

obj = className.myMethod()

-1

この問題を解決するには、clsパラメータを@classmethodに渡してください。

@classmethod
def test(cls):
    return ''
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.