Python Forum
Feedback on simple 'Mock Up' scripts
Thread Rating:
  • 1 Vote(s) - 4 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Feedback on simple 'Mock Up' scripts
#1
Hello, I'm new to Python. I've mainly used Java and decided to learn Python. I'm still getting used to syntax and logic of Python, so all feedback is welcome.

I've coded a simple mapper and inventory. Also 'main' script so I can easily test out different 'Mock Ups' just by commenting out other executions.

main.py
import inventory, mapper


def main():
    # inventory.execute()
    mapper.execute()


if __name__ == '__main__':
    main()
inventory.py
class Item(object):
    def __init__(self, name, stack_size=64):
        self.name = name
        self.size_stack = stack_size
        self.size = 1

    def is_capped(self):
        return self.size == self.size_stack

    def does_exist(self):
        return self.size > 0

    def get_name(self):
        return self.name

    def get_maximum_stack_size(self):
        return self.size_stack

    def get_stack_size(self):
        return self.size

    def add_to_stack(self):
        if not self.is_capped():
            self.size += 1
            return True
        else:
            print('Item [' + self.name + '] has reached it\'s stack capacity!')
            return False

    def drop_from_stack(self):
        self.size -= 1


class Inventory(object):
    def __init__(self, size):
        self.size = size
        self.inv = []

    def is_full(self):
        return len(self.inv) == self.size

    def does_contain(self, item):
        return self.inv.count(item) > 0

    def get_size(self):
        return self.size

    def get_item_at(self, index):
        if index <= self.size:
            return self.inv[index]
        else:
            print('Invalid Inventory Slot Index')

    def add_item(self, item):
        if self.does_contain(item):
            if self.inv[self.inv.index(item, 0, self.size - 1)].add_to_stack():
                print('Added to Stack | [' + item.get_name() + ']')
            else:
                if not self.is_full():
                    self.inv.append(item)
                    print('Added new Item [' + item.get_name() + '] to the Inventory')
        else:
            if not self.is_full():
                self.inv.append(item)
                print('Added new Item [' + item.get_name() + '] to the Inventory')
            else:
                print('Inventory is full, can\'t add the Item [' + item.get_name() + ']')

    def drop_item(self, item):
        if self.does_contain(item):
            self.inv[self.inv.index(item, 0, self.size - 1)].drop_from_stack()
            print('Dropped Item [' + item.get_name() + '] from the Inventory')
            if not self.inv[self.inv.index(item, 0, self.size - 1)].does_exist():
                self.inv.remove(item)
                # del self.inv[self.inv.index(item, 0, self.size - 1)]
                print('There are no stacks of Item [' + item.get_name() + '] in the Inventory')
        else:
            print('Inventory doesn\'t contain Item [' + item.get_name() + ']')


def execute():
    inventory = Inventory(4)
    print(inventory.get_size())

    pickaxe_stone = Item('Stone Pickaxe', 1)
    pickaxe_iron = Item('Iron Pickaxe', 1)
    torch = Item('Torch', 99)

    inventory.add_item(pickaxe_stone)
    inventory.add_item(pickaxe_iron)
    inventory.drop_item(pickaxe_stone)

    inventory.add_item(torch)
    inventory.add_item(torch)
    inventory.drop_item(torch)
    inventory.add_item(torch)

    # print (inventory.inv)
    for obj in inventory.inv:
        print(obj.get_name() + ' [' + str(obj.get_stack_size()) + ']')
My notes:
  • I could make another class used for storing Items / stacks of Items to make it easier to control. My thoughts, maybe I'm wrong
  • I should add a function to create items instead of using the same object, in which case previous note would help a ton.

map.py
class Tile(object):
    def __init__(self, char_tag, x, y):
        self._tag = char_tag
        self._pos = (x, y)

    def get_tag(self):
        return self._tag

    def get_pos(self):
        return self._pos

    def get_pos_x(self):
        return self._pos[0]

    def get_pos_y(self):
        return self._pos[1]


class Map():
    def __init__(self):
        self.grid = []
        self.width = 0
        self.height = 0

    def load_map(self, file_path, width, height):
        self.width = width
        self.height = height

        file = open(file_path)
        x, y = 0, 0
        for line in file.readlines():
            for char in line:
                if not char.isspace():
                    self.create_tile(char, x, y)
                    x += 1
            x = 0
            y += 1
        file.close()

    def create_tile(self, char, x, y):
        tile = Tile(char, x, y)
        self.grid.append(tile)


def execute():
    m = Map()
    m.load_map('map.txt', 10, 10)
    for y in range(m.height):
        for x in range(m.width):
            print(m.grid[x + (y * m.width)].get_tag(), end='')
        print('\n', end='')
Also, here is an example map I used in the test
map.txt

Aside from feedback I would like few questions answered:
  • Are getter and setter functions needed?
  • Should all or most of the variables be private or protected, or leave them public?
  • If a variable is private or protected should it have a getter and / or a setter function?
Reply
#2
To answer your bottom questions:

Setters and getters are not generally used in Python (read: extremely discouraged).
Unless a setter or getter would do actual work you would never write one, and if you were in a situation where you needed to write one, you would use @property decorators and such.

Privacy: again same here. Python is not Java. Python has a much more "we are all adults here" attitude towards data access. We do not use private/public/protected data. You write a class and make it clear how the API operates but if someone wants to touch the mechanics underneath you don't generally try to stop them. Single underscore variables have their place but they are not common; don't get in the habit of trying to mark all your class members "private". It just doesn't work that way.

And absolutely don't mark variables with leading double underscores. This causes name mangling, again doesn't actually enforce privacy, and most importantly annoys the hell out of other Python programmers.
Reply
#3
Thank you for answering my questions Mekire, I just have a question about this:
(Aug-20-2018, 05:56 PM)Mekire Wrote: And absolutely don't mark variables with leading double underscores. This causes name mangling, again doesn't actually enforce privacy, and most importantly annoys the hell out of other Python programmers.

Have I used double underscores? All I know about is '__name__', which if I'm correct, is referencing to basic Python Script variables / functions like 'def __init__(self)', just so Python knows what is going on, which class is doing what, when is a class initialized, etc... Or are you just warning me so I don't make that mistake.
Reply
#4
(Aug-20-2018, 05:56 PM)Mekire Wrote: And absolutely don't mark variables with leading double underscores.
He just advising you. The __init__ and __name__ are fine.
99 percent of computer problems exists between chair and keyboard.
Reply
#5
(Aug-21-2018, 01:06 AM)Windspar Wrote: He just advising you. The __init__ and __name__ are fine.
Thank you for clearing that up Windspar.
Reply
#6
(Aug-20-2018, 11:45 PM)fxJoan Wrote: Have I used double underscores?
No you didn't.

Names like this __something__ are called dunder methods. You shouldn't be creating your own brand new dunder methods but you will need to use them and define their function bodies like __init__ and such.

This isn't what I was talking about though. I was referring to names like this __something. This triggers what is called name mangling. Name mangling does just that; screws up the variable name in a predictable (but extremely annoying) way. Every time I need to deal with a name mangled variable I have to look up how it gets mangled but there is nothing stopping me from accessing it. The main purpose is to avoid potential collisions not enforce privacy.
https://docs.python.org/2/tutorial/class...references


Single leading underscore variables are used to "mark" variables as private but this is purely documentation. A leading underscore tells another python programmer that they really shouldn't access that variable directly and if they do stuff might break. Also for completeness if you were to star import a file (which you should almost never do), names that started with a single underscore would not be imported.
Reply
#7
Thank you very much, that clears up a lot of stuff. I'll focus on coding some of the Challenges, Ideas from the Forum and some of my Ideas and probably post them in this thread, or would it be more appropriate to make a new thread?
Reply
#8
If it is unrelated to the code here a new thread would probably be appropriate.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Simple Text Shop Simulator Feedback Dash 5 3,336 Apr-19-2019, 01:08 PM
Last Post: Dash

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020