7

I am learning Python and currently working with classes. I am trying to make a basic game to help learn it and am having a weird issue with calling methods from it. I have the main.py file which creates an instance from the class in the Character.py file.

This is the Character.py file:

class Character:  
    name=""  

    def __init__(Name):  
        name=Name  

    def getName():  
        return name

This is the main.py file:

from Character import *

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

I am not sure what the issue is. This is the error I get:

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

It is saying I am giving 1 positional argument but I don't see where I gave any. What am I missing?

Andrew Li
  • 55,805
  • 14
  • 125
  • 143
D. Stei
  • 73
  • 1
  • 1
  • 4

3 Answers3

10

Since you have a class with instance methods, you need to include the first argument (self by convention) to refer to the current instance. Also, make sure to set the variable as an instance variable by using self, the current instance:

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 internally passes the new instance of a class as the first argument to all the class methods, like this in languages such as Java. The error comes from the fact that Python passes the instance as the first argument internally but your getter is not defined to take an argument.

With the above code, when you call the method upon an instance, the instance is internally passed as the first argument and Python doesn't complain as you specify that it takes an argument, self, and name is set correctly on the instance.


Note: By convention, Python does not use camelCase, but underscores, so your getter should by convention look like this:

def get_name(self):
    #...

Also see chepner's answer which explains why getters and setters aren't usually needed. Just get and modify the instance variable by using dot notation:

print(player.name) #get
player.name = "Jeff" #set
Andrew Li
  • 55,805
  • 14
  • 125
  • 143
  • 1
    and the expert has spoken, good explanation, thanks for sharing, plus one – developer_hatch Jun 01 '17 at 01:04
  • Thank you, for making a set method such as setName it would be this? def setName(newName): self.name = newName – D. Stei Jun 01 '17 at 01:10
  • @D.Stei Every instance method should include self as its first argument: `def set_name(self, new_name): self.name = new_name` – Andrew Li Jun 01 '17 at 01:11
  • Okay thank you very much Andrew. And the camel case is just habit from Java, I know I should use underscores. – D. Stei Jun 01 '17 at 01:14
  • While we're cleaning up the code we should talk about the line `from Character import *`. To cite the [Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/#imports): "Wildcard imports (`from import *`) should be avoided". – Matthias Jun 01 '17 at 06:29
4

As others have mentioned, even instance method must be declared with an extra argument, typically named self (although that is a conventional, not a required, name).

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

    def get_name(self):
        return name

However, Python does not have any kind of enforced visibility (such as public or private), so such trivial getters and setters aren't usually written. Documentation about which attributes you are "allowed" to modify are considered sufficient protection.

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")
chepner
  • 497,756
  • 71
  • 530
  • 681
0

You are forgetting to add the parameter self. self is an object reference to the object itself, therefore, they are same. Python methods are not called in the context of the object itself. self in Python may be used to deal with custom object models or

class Character:  

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

    def getName(self):  
        return self.name

To see why this parameter is needed, there are so good answers here:

What is the purpose of self?

developer_hatch
  • 15,898
  • 3
  • 42
  • 75