Doval

Python 3.2 Classes tutorial

Dec 18th, 2011
419
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.17 KB | None | 0 0
  1. ###########
  2. # CLASSES #
  3. ###########
  4.  
  5. #Classes allow you to define your own arbitrarily complex data types. This allows
  6. #you to both model the problem you're trying to solve and manage the program's
  7. #complexity better. For example, suppose we wanted to create a Pokémon battle
  8. #simulator, like ShoddyBattle. Each Pokémon has a myriad of attributes: 6 base
  9. #stats, 6 IVs, 6 EVs, an EXP total, its level, Original Trainer, Trainer ID,
  10. #Secret ID, Nature, Gender, 4 learned moves, species name, nickname, Pokédex
  11. #number, location of capture, region of capture, and level of capture. That's an
  12. #overwhelming number of stats to keep track of, and you'll have a copy of those
  13. #variables for each Pokémon in your team (and the opponent's team!)
  14.  
  15. #Now suppose you wanted to write a function that operates on two Pokémon - for
  16. #example, a function to calculate the damage an attack will do. It'd be extremely
  17. #cumbersome and error-prone to write a function that accepts over 50 parameters.
  18. #You're not really trying to pass 50+ variables - you're trying to pass only two
  19. #Pokémon. We want to *encapsulate* all those attributes into a new variable type:
  20. #a Pokemon.
  21.  
  22. #Classes also allow us to initialize (give proper initial values to) the attri-
  23. #butes of each new Pokémon properly. This is extremely important-for example, it
  24. #makes no sense to create a Level 100 Pokémon that has 0 EXP, because a Pokémon's
  25. #level is a function of its EXP. Likewise, it makes no sense for a new Pokémon's
  26. #stats to be initialized 0, because their stats depend on their base stats, IVs,
  27. #EVs, and level. In fact, that would be an extremely dangerous thing to do - the
  28. #game's damage formula involves a division between Attack and Defense. If stats
  29. #were initialized to 0, and we forgot to properly set the defending Pokémon's
  30. #Defense, you would have a division by 0 on your hands and the program would
  31. #crash.
  32.  
  33. #Without further ado, let's create a basic Pokémon class.
  34.  
  35. class Pokemon:
  36.   """A simple Pokémon class; it only stores its level and final stats.
  37.  
  38.  The Pokemon is created at level 100 by default."""
  39.   #The above is a documentation string. It's good practice to document what
  40.   #your classes and functions do.
  41.  
  42.   #Here we set the default values of the class's *attributes*. Attributes are
  43.   #the variables that each instance of our Pokemon class holds.
  44.   level = 100
  45.  
  46.   #__init__ is the class's constructor. A constructor is a special function
  47.   #that's called when a new instance (a new Pokemon object) of the class is
  48.   #created. Its job is to properly intialize the class's attributes.
  49.   def __init__(self, hp, attack, defense, sp_attack, sp_defense, speed):
  50.       #It's incredibly important to realize there are two variables called "hp"
  51.       #inside this function. The one that's a parameter of the constructor is
  52.       #a local variable, just like the ones you've encountered in the past.
  53.       #It'll be destroyed when the function finishes. self.hp on the other hand
  54.       #refers to the Pokemon Class's hp attribute, and will live on when the
  55.       #constructor exits.
  56.       self.hp = hp
  57.       self.attack = attack
  58.       self.defense = defense
  59.       self.sp_attack = sp_attack
  60.       self.sp_defense = sp_defense
  61.       self.speed = speed
  62.       #If we want to set an attribute, we must always refer
  63.       #to it as self.<attribute name>. Otherwise, we'd be creating a local
  64.       #variable inside the constructor. For example:
  65.       #  name = "VENUSAUR"
  66.       #would create a local variable called name inside this function.
  67.       #  self.name = "VENUSAUR"
  68.       #would create an attribute called name inside the class instead.
  69.       #However, outside of functions, self isn't necessary - look at the level
  70.       #attribute before the constructor.
  71.  
  72.   #This function will print out all of the Pokémon's attributes (its variables)
  73.   #for us. Like I said earlier, methods will have at least one parameter - the
  74.   #Pokemon object they're acting upon.
  75.   def print_stats(self):
  76.       print("STATS:")
  77.       print("Level: ", self.level)
  78.       print("HP: ", self.hp)
  79.       print("Attack: ", self.attack)
  80.       print("Defense: ", self.defense)
  81.       print("Special Attack: ", self.sp_attack)
  82.       print("Special Defense: ", self.sp_defense)
  83.       print("Speed: ", self.speed)
  84.  
  85. #And that's it. Now we've defined a Pokemon class that contains two methods
  86. #and seven members. One of those two methods is a constructor. We can now
  87. #easily create a new Pokemon by calling the constructor like this:
  88. venusaur = Pokemon(404, 317, 266, 298, 261, 350)
  89.  
  90. #Note that we only passed 6 parameters - the Pokémon's stats - not 7. The hidden
  91. #first parameter "self" is passed automatically to the constructor and refers
  92. #to the venusaur variable we just created. As proof, we can directly verify
  93. #venusaur's attributes:
  94. print("Venusaur's level: ", venusaur.level) #prints 100
  95. print("Venusaur's HP: ", venusaur.hp)       #prints 404
  96.  
  97. #In a similar fashion, we can call the print_stats method:
  98. venusaur.print_stats()
  99. #Again, note that the self parameter is actually venusaur, so we don't pass it
  100. #ourselves when we call the function.
  101.  
  102. #we can just as easily create a new Pokemon by calling the constructor again:
  103. charizard = Pokemon(300, 410, 197, 383, 266, 360)
  104.  
  105. #We can now write a function to have one Pokemon attack the other, without
  106. #explicitly passing each Pokemon's stats!
  107. def attack(attacker, defender, move_bp, type_effectiveness):
  108.     """Doesn't take crits, randomness, burn, etc into account"""
  109.     #Don't worry about the details of the formula.
  110.     damage = ( ((attacker.level * 2/5 + 2) * move_bp * (attacker.attack/50)
  111.                / defender.defense + 2) * type_effectiveness )
  112.     #It's good practice to keep your lines under 80 characters. If you need to
  113.     #do really long calculations, wrap the whole thing in parentheses so you
  114.     #can break it up into multiple lines.
  115.     defender.hp -= damage #subtract the damage from the defender's hp.
  116.     return damage #return the damage done
  117.  
  118. #And now we have charizard use Flamethrower on venusaur:
  119. print("Damage done: ", attack(charizard, venusaur, 100, 2))
  120.  
  121. #Let's verify Venusaur's HP to be sure:
  122. print("Venusaur's HP after attack: ", venusaur.hp)
Advertisement
Add Comment
Please, Sign In to add comment