Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Object-Oriented Python (retired) Inheritance DRY

Python 2.7 after player.attack() -> Global name 'attack_limit' is not defined even after adding the self. part before it

I am using pythonista on ipad which runs on python 2.7 to input all the code while going along with the videos to better understand.

I have been fine up until this point but when I run:

player.attack()

it throws up the error:

NameError: global name 'attack_limit' is not defined.

Can you shed light on this, or provide a link that might explain the differences in classes from 2.7 to 3+?

5 Answers

Kenneth Love
STAFF
Kenneth Love
Treehouse Guest Teacher

Copied and pasted your code locally and ran it with Python 2.7.

  1. You have a lot of extra indentation. That shouldn't be messing anything up because it seems consistent, but it's also not necessary.
  2. Combat.__init__ doesn't end with a colon. That could be your issue.

Once I fixed the missing colon, I was able to import Character, make one, and call Character.attack() with it and it was fine so...maybe the __init__ is the issue?

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,425 Points

You are correct, attack_limit is not defined (correctly). When you get to the ~4:00 on the video, Kenneth hits the same error. The arguments to Combat.attack() should have been: (self, self.attack_limit) not (self, attack_limit)

Character.py

import random
from combat import Combat

class Character(Combat):
        attack_limit = 10
        experience = 0
        base_hit_points = 10

        def attack(self):
                roll = random.randint(1, self.attack_limit)
                if self.weapon == 'sword':
                        roll += 1
                elif self.weapon == 'axe':
                        roll += 2
                return roll > 4

        def get_weapon(self):
                weapon_choice = raw_input("Weapon ([S]word, [A]xe, [B]ow): ").lower()

                if weapon_choice in 'sab':
                        if weapon_choice == 's':
                                return 'sword'
                        elif weapon_choice == 'a':
                                return 'axe'
                        else:
                                return 'bow'
                else:
                        return self.get_weapon()

        def __init__(self, **kwargs):
                self.name = raw_input('Name: ')
                self.weapon = self.get_weapon()
                self.hit_points =- self.base_hit_points

                for key, value in kwargs.items():
                        setattr(self, key, value)

        def __str__(self):
                return '{}, HP: {}. XP {}'.format(self.name, self.hit_points, self.experience)

        def rest(self):
                if self.hit_points < self.base_hit_points:
                        self.hit_points += 1

        def leveled_up(self):
                return self.experience >= 5

combat.py

import random

class Combat(object):
        def __init__(self)
                self.dodge_limit = 6
                self.attack_limit = 6

        def dodge(self):
                roll = random.randint(1, self.dodge_limit)
                return roll > 4

        def attack(self):
                roll = random.randint(1, self.attack_limit)
                return roll > 4

[edit: add python format - cf]

That looks like it, thanks for taking the time out.

p.s. This was before I finished the videos on writing better python :)