为什么我不能从我的Python类中调用一个方法?

7
我正在学习Python,并且正在使用类。我尝试制作一个基本的游戏来帮助学习它,但在调用方法时遇到了奇怪的问题。我有一个main.py文件,它从Character.py文件中创建一个类的实例。
这是Character.py文件:
class Character:  
    name=""  

    def __init__(Name):  
        name=Name  

    def getName():  
        return name

这是 main.py 文件:
from Character import *

player = Character("James")
print(player.getName())

我不确定问题出在哪里。这是我得到的错误:

Traceback (most recent call last):
  File "C:\Users\dstei\Documents\Python\It 102\Final Project\Main.py", line 
12, in <module>
    print(player.getName())
TypeError: getName() takes 0 positional arguments but 1 was given

提示说我只提供了一个位置参数,但是我不知道我在哪里提供了。我错过了什么吗?

3个回答

10

因为您有一个带实例方法的类,所以需要包含第一个参数(按惯例为self)以引用当前实例。此外,请确保使用当前实例的self设置变量作为实例变量

class Character:  
    def __init__(self, Name): #self is the current instance
        self.name=Name  #set the variable on the instance so that every instance of Character has a name

    def getName(self):  
        return self.name #refer to the name with the instance

Python内部将类的新实例作为第一个参数传递给所有类方法,就像Java等语言中的this一样。错误来自于Python在内部将实例作为第一个参数传递,但是您的getter没有定义接受参数。

使用上述代码时,当您在实例上调用该方法时,实例会作为第一个参数在内部传递,并且Python不会抱怨,因为您指定它需要一个名为self的参数,并且name正确设置在实例上。


注意:按照惯例,Python不使用驼峰命名法,而是使用下划线,因此您的getter应该按照惯例如下所示:

def get_name(self):
    #...

还可以查看chepner的答案,其中解释了为什么通常不需要使用Getter和Setter。只需使用点符号表示法获取并修改实例变量:

print(player.name) #get
player.name = "Jeff" #set

1
专家已经发言,解释得很好,谢谢分享,点赞! - developer_hatch
谢谢您创建了一个像setName这样的设置方法,它应该是这样的吗? def setName(newName): self.name = newName - D. Stei
@D.Stei每个实例方法都应该包括self作为其第一个参数:def set_name(self, new_name): self.name = new_name - Andrew Li
好的,非常感谢你,安德鲁。驼峰命名法只是我从Java中习惯了的,我知道应该使用下划线。 - D. Stei
在我们整理代码的同时,我们应该谈论一下from Character import *这一行。引用Python代码风格指南的话:“应避免使用通配符导入(from <module> import *)”。 - Matthias

4

正如其他人提到的那样,即使是实例方法也必须使用额外的参数进行声明,通常命名为self(尽管这只是一种惯例而非必需名称)。

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

    def get_name(self):
        return name

然而,Python没有强制可见性(例如public或private),因此通常不需要编写这种琐碎的getter和setter。有关哪些属性可以被修改的文档被认为是足够的保护。
class Character:
    def __init__(self, name):
        self.name = name

c = Character("Bob")
print(c.name)  # instead of c.get_name()
c.name = "Charlie"  # instead of c.set_name("Charlie")

啊,是的,我忘了提到这一点。+1 - Andrew Li
那很好知道,谢谢。这个也适用于列表吗? - D. Stei

0
你忘记添加self参数了。self是一个对象引用,指向对象本身,因此它们是相同的。Python方法不是在对象本身的上下文中调用的。在Python中,self可以用于处理自定义对象模型或...
class Character:  

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

    def getName(self):  
        return self.name

要了解为什么需要这个参数,请参考以下优秀的答案:

self 的目的是什么?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接