15/14 and 15/15


#1

Hey guys, I just wanted to ask quickly about these lessons. Probably a noob question but I just want to have a better understanding rather than just moving to the next lessons. They use a bit of a different syntax than (for i in word:) etc.

choices = ['pizza', 'pasta', 'salad', 'nachos']

print 'Your choices are:'
for index, item in enumerate(choices):
print index+1, item

I am a bit confused as to what the comma is doing, and what the syntax is doing.

Same with this one:

list_a = [3, 9, 17, 15, 19]
list_b = [2, 4, 8, 10, 30, 40, 50, 60, 70, 80, 90]

for a, b in zip(list_a, list_b):
# Add your code here!

Could somebody explain this kind of syntax on a for loop, and what is actually happening? I understand a normal for loop and how the first variable is generally looking at and doing an increment through something, but what is up with the comma and two variables? Thanks guys.


#2

Well, unlike a normal for loop, enumerate gives back a tuple. you can also use the same format with dicts to get the key and value at the same time.

EXAMPLE:

dict_one = {'a': 1, 'b': 2, 'c': 3}
for key, value in dict_one:
    print(key, value)

With enumerate it's the same but the built-in gives back the index for the items it's enumerating.

Example:

a_list = [6, 5, 4, 3, 2, 1]
for index, value in enumerate(a_list):
    print(index, value)

This allows us to do all types of fancy programing in less steps. You will see some later but here is an example of what you can do with it.

Example:

a = 'string'

def reverse(word):
    hold = []
    for index, value in enumerate(word):
        hold.append(word[-(index + 1)])
    return ''.join(hold)

While I am not using the value in this instance and using enumerate instead of range(len()) there is no functional difference and is just used as an example.

As always best of luck


#3

Appreciate the great reply, this is making a lot more sense now. Just a side note, since I am still learning, do you know any other good practice resources out there? I am pretty set on finishing the whole python course here on code academy, but I want a good place to practice beginner / intermediate problems and also learn how to implement APIs.


#4

I would wait on the apis until you get a firm grasp on classes. it will ease moving into them as you will be referring to them and thier class methods quite often.

This is a good resource too.

Here is an example of what I am working on right now for my Battleship game's AI. I have it generating a point map each turn to determine the best move so I have to be able to debug it.

I created a tkinter app that reads my point maps and displays them graphically so I can see turn by turn what my algorithm was doing. You can generally see what type of APIs or modules people are using by the imports.

In python using modules is just like using APIs so get plenty of practice, also read your APIs code so you know what it's doing.

(NOTE: I still have some work to do on this but it does what I need it to right now.)

__author__ = 'Charles Engen'

import tkinter
from os.path import join as join_
from os import getcwd
from os import listdir
import re

_path = getcwd()
_path_gamedata = join_(_path, "GameData")
_path_gamedata_pointmaps = join_(_path_gamedata, "point_maps")

point_map = {(x, y): None for x in range(1, 11) for y in range(1, 11)}


class PointMaps(object):

    def __init__(self):
        self._point_map_files = listdir(_path_gamedata_pointmaps)
        self.point_maps = dict()

    def _load_point_map(self, file):
        with open(join_(_path_gamedata_pointmaps, file)) as file:
            temp = {}
            for line in file:
                match = re.search(r"turn_(.*)'", line)
                temp[int(match.group()[5:-1])] = (eval(line))
            return temp

    def file_load(self):
        for number, file in enumerate(self._point_map_files):
            self.point_maps[number] = self._load_point_map(file)


class Table(tkinter.Frame):

    def __init__(self, parent):
        global point_map
        tkinter.Frame.__init__(self, parent)
        self._widgets = []
        for x in range(1, 11):
            current_row = []
            for y in range(1, 11):
                string_var = tkinter.StringVar()
                string_var.set(point_map[(x, y)])
                text = tkinter.Label(self, height=2, width=2, textvariable=string_var)
                text.grid(column=x, row=y)
                current_row.append(string_var)
            self._widgets.append(current_row)

    def set(self, row, column, value):
        widget = self._widgets[row-1][column-1]
        widget.set(value)


class MainFrame(tkinter.Tk):

    def __init__(self):
        tkinter.Tk.__init__(self)
        self.data = PointMaps()
        self.data.file_load()
        print(self.data.point_maps[0])

        self.player_number = 0
        self.player_1_turn = 0
        self.player_2_turn = 1
        self.game_number = 0

        self.point_map = Table(self)
        self.point_map.pack()

        self._widgets = []

        self.menu_item = tkinter.Menu(self)
        self.config(menu=self.menu_item)

        self.file_menu = tkinter.Menu(self.menu_item, tearoff=0)
        self.sub_file_item_01 = tkinter.Menu(self.file_menu)
        self.menu_item.add_cascade(label="Load map", menu=self.sub_file_item_01)

        self.sub_file_item_01.add_separator()

        self.sub_file_item_01.add_command(label="Load Player One", command=self.load_player_1)
        self.sub_file_item_01.add_command(label="Load Player Two", command=self.load_player_2)

        self.sub_file_item_01.add_separator()

        self.sub_file_item_01.add_command(label="Next map", command=self.cycle_point_map_up)

        self.level_var = tkinter.StringVar()
        self.player_var = tkinter.StringVar()

        self.level_label = tkinter.Label(self, textvariable=self.level_var)
        self.player_label = tkinter.Label(self, textvariable=self.player_var)

        self.level_label.pack(side='left')
        self.player_label.pack(side='left')

        self.button_up = tkinter.Button(text='Game Up', command=self.cycle_point_map_up)
        self.button_down = tkinter.Button(text='Game Down', command=self.cycle_point_map_down)

        self.button_up.pack()
        self.button_down.pack()

    def _load_point_map(self, p_number):
        global point_map
        try:
            point_map = self.data.point_maps[p_number][eval("self.player_%s_turn" % (self.player_number + 1))]['turn_%s' % str(eval("self.player_%s_turn" % (self.player_number + 1)))]
            self.level_var.set(eval("self.player_%s_turn" % (self.player_number + 1)))
            for x, y in point_map:
                self.point_map.set(x, y, point_map[(x, y)])
        except KeyError:
            self.level_var.set("No more turns to look at")

    def cycle_point_map_up(self):
        self.player_1_turn += (2 if int(self.player_var.get()[-1]) == 1 and self.player_1_turn >= 0 else 0)
        self.player_2_turn += (2 if int(self.player_var.get()[-1]) == 2 and self.player_2_turn >= 1 else 0)
        self._load_point_map((self.game_number + self.player_number))

    def cycle_point_map_down(self):
        self.player_1_turn -= (2 if self.player_1_turn >= 0 and int(self.player_var.get()[-1]) == 1 else 0)
        self.player_2_turn -= (2 if self.player_2_turn >= 1 and int(self.player_var.get()[-1]) == 2 else 0)
        self._load_point_map((self.game_number + self.player_number))

    def load_player_1(self):
        self.player_number = 0
        self.player_var.set("Player: %s" % (self.player_number + 1))
        self._load_point_map((self.game_number + self.player_number))

    def load_player_2(self):
        self.player_number = 1
        self.player_var.set("Player: %s" % (self.player_number + 1))
        self._load_point_map((self.game_number + self.player_number))

if __name__ == "__main__":
    root = MainFrame()
    root.mainloop()