TypeError: method () 1 konum bağımsız değişkeni alır, ancak 2'si verilir


270

Bir dersim varsa ...

class MyClass:

    def method(arg):
        print(arg)

... bir nesne oluşturmak için kullandığım ...

my_object = MyClass()

... method("foo")böyle dediğim ...

>>> 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 neden bana sadece bir tane verdiğimde iki argüman verdiğimi söylüyor?


Bu mesajın on beş nedeni var; Buradaki özel neden, tüm örnek yöntemlerinin, özel olarak adlandırdığımız ilk argümanı beklemesidir self. Yani def method(arg):bir yöntem için bildirmek yanlış, öyle olmalı def method(self, arg):. Yöntem dağıtımı method(arg):iki parametreyi çağırmaya ve eşleştirmeye çalıştığında self, arg, bu hatayı alırsınız.
smci

Yanıtlar:


367

Python'da bu:

my_object.method("foo")

... tercümanın perde arkasına çevirdiği sözdizimsel şekerdir :

MyClass.method(my_object, "foo")

... gördüğünüz gibi, aslında iki argümanı var - sadece ilk görüş, arayanın bakış açısından örtük.

Bunun nedeni, çoğu yöntemin bazılarının çağrıldıkları nesneyle çalışmasıdır, bu nedenle o nesnenin yöntemin içinde belirtilmesi için bir yol olması gerekir. Kural olarak, bu ilk argüman selfyöntem tanımının içinde çağrılır :

class MyNewClass:

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

Örneğini çağırırsanız method("foo"), MyNewClassbeklendiği gibi çalışır:

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

Bazen (ama çoğunlukla), gerçekten yok senin yöntem bağlı olduğu nesne önemsemez, ve bu koşulda şunları yapabilirsiniz süslemeleri yerleşik olan yöntem staticmethod()bunu söylemek fonksiyonu:

class MyOtherClass:

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

... bu durumda selfyöntem tanımına bağımsız değişken eklemenize gerek yoktur ve yine de çalışır:

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

99
Kısacası: selfYönteme ilk argüman olarak eklemek sorunu çözer.
amoebe

@amoebe - kişinin tipim
Carlos

21

Bu tür bir hatayla karşılaşıldığında dikkate alınması gereken başka bir şey:

Bu hata iletisiyle karşılaşıyordum ve bu gönderiyi yararlı buldum. Benim durumumda __init__(), nesne mirasının olduğu bir yeri geçersiz kıldığım ortaya çıkıyor.

Devralınan örnek oldukça uzun, bu yüzden miras kullanmayan daha basit bir örneğe geçeceğim:

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

Sonuç:

<__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 bu yazım hatasını yakalamadı. Notepad ++ (diğer editörler / IDE'ler de olabilir).

Bu bir "parametre almaz" TypeError, Python'da nesne başlatma açısından birini beklerken "iki tane var" dan çok farklı değildir.

Konuyu ele alma: Sözdizimsel olarak doğru ise aşırı yükleme başlatıcısı kullanılacaktır, ancak değilse yok sayılır ve bunun yerine yerleşik kullanılır. Nesne bunu beklemez / işlemez ve hata atılır.

Sytax hatası durumunda: Düzeltme basittir, sadece özel init deyimini düzenleyin:

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

1
Burada yok SyntaxError. Kod sözdizimsel olarak doğrudur; ___init__özel yöntem yerine kimsenin arayamayacağı bir yöntemi doğru bir şekilde tanımlar __init__. Bu yüzden hiçbir hata algılanmaz - çünkü algılanacak bir tane yoktur.
abarnert

14

Basit bir deyişle.

Python'da self, sınıfta tanımlanan tüm yöntemlere ilk argüman olarak argüman eklemelisiniz :

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

Ardından yönteminizi sezginize göre kullanabilirsiniz:

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

Bu probleminizi çözmeli :)

Daha iyi bir anlayış için, şu sorunun cevaplarını da okuyabilirsiniz: Benliğin amacı nedir?


2
Bu sorunun nesi var? Neden birisi ona olumsuz bir nokta verdi? Sonuçta, sorunun cevabıdır ve bir cevap arayan bazı insanlar için önemli olabilecek diğer cevaplara kıyasla basitliği ile ayırt edilir. Öyle değil mi?
simhumileco

10

Python'a yeni gelen, Python'un **özelliğini yanlış bir şekilde kullanırken bu sorunu yaşadım . Bu tanımı bir yerden aramaya çalışıyorum:

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

çift ​​yıldız olmadan çağrı kullanmak soruna neden oluyordu:

self.create_properties_frame(frame, kw_gsp)

TypeError: create_properties_frame () 2 konum bağımsız değişkeni alır, ancak 3 konum verilir

Çözüm, **argümana eklemektir :

self.create_properties_frame(frame, **kw_gsp)

1
JavaScript'ten gelince, bir liste veya sözlüğü bağımsız değişken olarak geçirebilmeyi umuyorum. Ama öyle görünüyor ki Python böyle çalışmıyor: listeyi * veya ** ile yıkmanız gerekiyor;
Küçük Beyin

1
@LittleBrain: evet, işlevin içinde bir liste (/ dict) olarak ele alınmasını istiyorsanız bir liste (veya dict) iletebilirsiniz. Ancak, ayrı ayrı değerlerinin paketten çıkarılmasını ve işlevdeki bağımsız değişkenlerle (/ kwargs) eşleştirilmesini istiyorsanız, *args(/ **kwargs) sözdizimine ihtiyacınız vardır .
smci

9

__init__()Herhangi bir parametre veya arayan başka bir yöntem belirtmediğinizde ortaya çıkar .

Örneğin:

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

Yukarıdaki programı çalıştırdığınızda, size böyle bir hata verir:

TypeError: __init __ () 1 konumsal argüman alır ancak 6'sı verilir

Bu şeyden nasıl kurtulabiliriz?

Sadece parametreleri geçin, hangi __init__()yöntemi arıyor

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

Aslında bir sınıf oluşturmalısınız:

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

0

Benim durumumda eklemeyi unuttum ()

Böyle bir yöntemi çağırıyordum

obj = className.myMethod

Ama böyle olmalı

obj = className.myMethod()

-1

Geçiş clsiçine parametreyi @classmethodBu sorunu gidermek için.

@classmethod
def test(cls):
    return ''
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.