调用类方法会在Python中引发TypeError


71

我不明白如何使用类。当我尝试使用该类时,以下代码给我一个错误。

class MyStuff:
    def average(a, b, c): # Get the average of three numbers
        result = a + b + c
        result = result / 3
        return result

# Now use the function `average` from the `MyStuff` class
print(MyStuff.average(9, 18, 27))

错误:

File "class.py", line 7, in <module>
    print(MyStuff.average(9, 18, 27))
TypeError: unbound method average() must be called with MyStuff instance as first argument (got int instance instead)

怎么了?


5
将类视为模子。您实际上并没有与模具本身进行交互,而是使用模具来创建可以与之交互的对象。为了对该对象执行某些操作,必须首先创建它。
Tim S.

Answers:


88

您可以通过声明变量并像调用一个函数一样实例化该类:

x = mystuff()
print x.average(9,18,27)

但是,这不适用于您提供给我们的代码。在给定对象(x)上调用类方法时,调用该函数时,它始终将指向该对象的指针作为第一个参数传递。因此,如果您现在运行代码,则会看到以下错误消息:

TypeError: average() takes exactly 3 arguments (4 given)

要解决此问题,您需要修改平均值方法的定义以采用四个参数。第一个参数是对象引用,其余3个参数用于3个数字。


你的意思是应该接受自我吗?
Josh Smeaton

8
您可以根据需要调用它。“自我”只是一个约定。
nosklo

11
@JoshSmeaton您应该真正使用“ self”,因为即使在技术上不是必需的,它也是一个非常标准的约定,它将使您的代码在其他python开发人员中更加主流。
Tim S.

34

从您的示例来看,在我看来您想使用静态方法。

class mystuff:
  @staticmethod
  def average(a,b,c): #get the average of three numbers
    result=a+b+c
    result=result/3
    return result

print mystuff.average(9,18,27)

请注意,在python中大量使用静态方法通常会引起一些不良气味的征兆-如果您确实需要函数,则直接在模块级别上声明它们。


2
对不起,我很抱歉,但我认为您误解了这个问题。似乎stu是Python的新手,因此,将其引向具有Python基础知识的丰富资源可能比向他展示如何使用静态方法更好;)
Dirk Stoop,

9
另一方面,Python中“ self”的显式使用以及对静态方法的错误信念对于来自其他语言的人们来说是一个普遍的陷阱。由于这里有许多指向的文档和资源,我认为至少应该有一个“直接”的答复。感谢您的评论!

1
除非你正在做一个实用工具类,这是很好的做的很多静态方法和类方法
伊兰摩西

13

为了最小化您的示例,您可以将代码修改为:

class myclass(object):
        def __init__(self): # this method creates the class object.
                pass

        def average(self,a,b,c): #get the average of three numbers
                result=a+b+c
                result=result/3
                return result


mystuff=myclass()  # by default the __init__ method is then called.      
print mystuff.average(a,b,c)

或者更全面地扩展它,允许您添加其他方法。

class myclass(object):
        def __init__(self,a,b,c):
                self.a=a
                self.b=b
                self.c=c
        def average(self): #get the average of three numbers
                result=self.a+self.b+self.c
                result=result/3
                return result

a=9
b=18
c=27
mystuff=myclass(a, b, c)        
print mystuff.average()

如果我们简单地做就可以myclass().average(a,b,c)吗?
DJ_Stuffy_K

1
@DJ_Stuffy_K该代码适用于我的第一个代码示例。但是最初的问题与实例化类有关,因此我包括了def __init __()方法。您的代码段实例化了该类,但是没有“句柄”可用来访问可能使用相同实例变量的其他方法。也许有帮助。
cmoman

4

一个类中的每个函数以及每个类变量都必须采用self所指出参数。

class mystuff:
    def average(a,b,c): #get the average of three numbers
            result=a+b+c
            result=result/3
            return result
    def sum(self,a,b):
            return a+b


print mystuff.average(9,18,27) # should raise error
print mystuff.sum(18,27) # should be ok

如果涉及类变量:

 class mystuff:
    def setVariables(self,a,b):
            self.x = a
            self.y = b
            return a+b
    def mult(self):
            return x * y  # This line will raise an error
    def sum(self):
            return self.x + self.y

 print mystuff.setVariables(9,18) # Setting mystuff.x and mystuff.y
 print mystuff.mult() # should raise error
 print mystuff.sum()  # should be ok

1

您需要花更多的时间在一些面向对象编程的基础知识上。

这听起来很刺耳,但这很重要。

  • 您的类定义不正确-尽管语法碰巧是可以接受的。这个定义是错误的。

  • 您完全没有使用该类创建对象。

  • 您使用类进行计算是不合适的。可以完成这种事情,但是需要高级概念@staticmehod

由于示例代码在很多方面都是错误的,因此您无法获得整洁的“解决此问题”答案。有太多事情要修复。

您需要查看更好的类定义示例。目前尚不清楚您正在使用的原始资料,但是无论您阅读的是错误还是不完整的书。

请丢弃您正在使用的任何书籍或资源,以找到更好的书籍。说真的 他们在类定义的外观和用法上误导了您。

您可能需要查看http://homepage.mac.com/s_lott/books/nonprog/htmlchunks/pt11.html,以更好地介绍类,对象和Python。


该链接现在无法使用。我可以改用课程名称/书名吗?
Veronica Wenqian Cheng

1

在python中,类的成员函数需要显式self参数。与thisC ++中的隐式指针相同。有关更多详细信息,请查看页面。


3
不同意。不是强制性的是“自我”的名称。但是Python成员函数的第一个参数是对对象的引用。当然,您具有类和静态方法,但适用于实例方法的规则。
Abgan

1
@Abgan:实际上,它甚至适用于类和静态方法-装饰器只是进行一些自动处理,以便包装函数接收与包装器不同的参数。
坎普

1

尝试这个:

class mystuff:
    def average(_,a,b,c): #get the average of three numbers
            result=a+b+c
            result=result/3
            return result

#now use the function average from the mystuff class
print mystuff.average(9,18,27)

或这个:

class mystuff:
    def average(self,a,b,c): #get the average of three numbers
            result=a+b+c
            result=result/3
            return result

#now use the function average from the mystuff class
print mystuff.average(9,18,27)

-2

您从未创建实例。

您已经将平均值定义为实例方法,因此,要使用平均值,您需要先创建一个实例。


3
对不起,不好意思;您绝对正确,但这不是一个非常有用的答案
Dirk Stoop

这个问题的字面意思是“怎么了?” 这个答案确实说明了问题所在,所以我认为这是一个答案。
递归

1
@recursive(响应7年后的评论,即2年后的评论),我认为真正的问题在标题中,字面上是“如何实例化一个类”。在尝试学习如何创建实例时指出需要创建一个实例是无济于事的;指出答案是根据上下文(标题)进行的脚。您甚至没有阐述或指导正确的答案,其他人为您做了。在某些时候,我们都是编程新手,也是措词不一的新手。
BLaZuRE
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.