954,515 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

AttributeError: My custom module doesn't have an attribute?

This is my custom module:

class Player(object):
    def __init__(self, name, score = 0):
        self.name = name
        self.score = score
        
    def __str__(self):
        rep = self.name + ":\t" + str(self.score)
        return rep
    
    def ask_yes_no(self, question):
        response = None
        while response not in ("y", "n"):
            response = input(question).lower()
        return response
    
    def ask_number(self, question, low, high):
        response = None
        while response not in range (low, high):
            response = int(input(question))
        return response


The program:

import games, random

print "Welcome to the world's simplest game!\n"

again = None
while again != "n":
    players = []
    num = games.ask_number(question = "How many players? (2-5): ", low = 2, high = 5)    
    for i in range(num):
        name = raw_input("Player name: ")
        score = random.randrange(100) +1
        player = games.Player(name, score)
        players.append(player)
    
    print "\nHere are the game results: "
    for player in players:
        print(player)
    
    again = games.ask_yes_no("\nDo you want to play again? (y/n): ")

raw_input("Press enter to exit.")


This is the error I get when I run the program:

AttributeError: 'module' object has no attribute 'ask_number'

Please help me. Thanks!

abders
Newbie Poster
17 posts since Aug 2011
Reputation Points: 10
Solved Threads: 0
 

Unindent the ask_number() and ask_yes_no() definitions and remove the self parameter.

Gribouillis
Posting Maven
Moderator
2,786 posts since Jul 2008
Reputation Points: 1,044
Solved Threads: 691
 

I'm still an ameture at programming, so could you please be a bit more specific about the solution. I don't quite know what you mean by 'Unindent'. Thanks for helping me! :)

abders
Newbie Poster
17 posts since Aug 2011
Reputation Points: 10
Solved Threads: 0
 
I'm still an ameture at programming, so could you please be a bit more specific about the solution. I don't quite know what you mean by 'Unindent'. Thanks for helping me! :)


I mean remove the definitions from the Player class and write them at the beginning of the line.

Gribouillis
Posting Maven
Moderator
2,786 posts since Jul 2008
Reputation Points: 1,044
Solved Threads: 691
 

Is that the only way? I'm learning from a book at the moment, and this should be possible.

abders
Newbie Poster
17 posts since Aug 2011
Reputation Points: 10
Solved Threads: 0
 

Gribouillis means that obviously those two functions have no business in being in the class Player.

Interestingly I have exactly same functions in module called games for a Blackjack game from one book, without the class Player.

in range(low, high) is not the world's most efficient way to check value is between two limits, here is my code (looks like my coding style, maybe I coded it quickly myself, anyway...)

try:
    input = raw_input
except:
    pass

def ask_yes_no(prompt='Yes or no (y/n)? '):
    while True:
          answer = input(prompt).lower()
          if answer and answer in 'yn':
             return answer

def ask_number(prompt='Number: ', low = None, high = None):
    while True:
          try:
              answer = int(input(prompt))
              if low and answer < low:
                 raise ValueError('Too low')
              if high and answer >= high:
                 raise ValueError('Too high')
              return answer
          except ValueError as e :
              print(e)
              print('Try again')
pyTony
pyMod
Moderator
5,359 posts since Apr 2010
Reputation Points: 782
Solved Threads: 852
 

Thanks for the help guys.

My book is called "Python Programmin, third edition: For the absolute beginner." maybe you know it from somewhere..

So, I usually write the programs directly from the book, and sometimes there are some errors here and there, I often I can take care of it myself. But stuff like this I can't, because I just plainly don't understand the problem. Thanks for helping my understand!

Do you think you could maybe explain why the two functions shouldn't be in the Player class?

Thanks again!

abders
Newbie Poster
17 posts since Aug 2011
Reputation Points: 10
Solved Threads: 0
 

You use different style with classes, mostly you like to access methods through an instance of class:

test_module.py

import t_class2

t_class2.hello()

p = t_class2.Player()
p.hello()

test_class2.py

class Player(object):
    def hello(self, message='Hello from class Player'):
        print(message)

def hello(message='Hello from module %s' % __file__):
    print(message)
pyTony
pyMod
Moderator
5,359 posts since Apr 2010
Reputation Points: 782
Solved Threads: 852
 
Do you think you could maybe explain why the two functions shouldn't be in the Player class?


It's a matter of class design. Normally, functions in a class Player execute player's action or report about player's state, or they may execute code relative to all players (in this case they are class methods or static methods). Technically, one says that each class has a certain number of "responsibilities". General utility functions like ask_yes_or_no() are unrelated to this class.

If you absolutely want to have this functions in the class, write

@staticmethod
    def ask_yes_or_no(): # no self parameter
      ...

and then use game.Player.ask_yes_or_no()

Gribouillis
Posting Maven
Moderator
2,786 posts since Jul 2008
Reputation Points: 1,044
Solved Threads: 691
 

Okay, thanks. This helped me understand.

I'll try to remember this when a similar problem occurs later.

Just curious, for how long have you been programming?

abders
Newbie Poster
17 posts since Aug 2011
Reputation Points: 10
Solved Threads: 0
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: