4
\$\begingroup\$

The basic idea of the code is that agents come into the world, they age and then die. I want to keep track of who is dead and who is alive. Eventually, they will do more things but I think there should be a lot of things I am not doing best practice on. I assume I'm doing something wrong with "Global" as well.

# Classes

class Agent(object):
    def __init__(self, identification, productivity, wealth, preferences, age, health, alive, sex):
        self.identification = identification
        self.productivity = productivity
        self.wealth = wealth
        self.preferences = preferences
        self.age = age
        self.health = health
        self.alive = alive
        self.sex = sex
    def description(self):
        print("My id is", self.identification)
        print("My age is", self.age)

def Create_agents():
    global id
    alive.append(Agent(id,100,20,"blue",30,0,True,True ))
    id += 1

# functions
def Initialize():
    for x in range(3):
        Create_agents()

def Death():
    temp = alive.copy()
    for agent in temp:
        if agent.age>30:
            agent.alive = False
            print("Death of", agent.identification)
            dead.append(agent)
            alive.remove(agent)

def Time_skip():
    print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%SKIPPING TIME%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
    global year
    year += 1
    print("The new year is", year)
    for agent in alive:
        agent.age +=1
    Create_agents()
    Death()


# Values
alive = []
dead = []
id = 0
year = 0
Initialize()

# Testing
for agent in alive: 
    agent.description()

Time_skip()

for agent in alive: 
    agent.description()

The output is:

My id is 0
My age is 30
My id is 1
My age is 30
My id is 2
My age is 30
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%SKIPPING TIME%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
The new year is 1
Death of 0
Death of 1
Death of 2
My id is 3
My age is 30
\$\endgroup\$
  • 1
    \$\begingroup\$ Does this code work as expected? \$\endgroup\$ – pacmaninbw May 16 at 17:57
  • \$\begingroup\$ @pacmaninbw Yes, note the temp = alive.copy() change. \$\endgroup\$ – Peilonrayz May 16 at 18:01
3
\$\begingroup\$
  • Python has a standardized style guide called PEP 8. There is also Google's Python style guide which AFAIK is very similar to PEP 8.

    Any code that goes largely against PEP 8 normally doesn't look Pythonic.

    • Python has a naming scheme to allow developers to know the variables type by it's name only.

      • Classes are in CamelCase,
      • Functions, methods and variables are in snake_case, and
      • Constants are in UPPER_SNAKE_CASE.
    • There should be a single space after commas.

    • Lines should be limited to 79 characters.
    • There should be one space between all methods, and two between top level classes and functions.

    Overall your code adheres to these standards pretty well. Good job.

  • class Agent(object) is a relic from Python 2. In Python 2 classes didn't inherit from object by default. These are now called old style classes. However in Python 3 everything inherits from object by default - making all classes in Python 3 new style classes.

  • Your code would benefit from another class.

    I'm reluctant to suggest this as the code has an over-reliance on global variables. In the future you should try to solve the problem without globals and then see if it can be made cleaner by using a class.

    And so we can make a Simulation class. I would include all the global functions you have in it except initialize.

  • I would use an if __name__ == "__main__": guard to prevent your code from running if it's been imported accidentally.

This gets the following. There's some more changes that can be made, but the base of your code is good.

class Agent:
    def __init__(self, identification, productivity, wealth, preferences, age, health, alive, sex):
        self.identification = identification
        self.productivity = productivity
        self.wealth = wealth
        self.preferences = preferences
        self.age = age
        self.health = health
        self.alive = alive
        self.sex = sex

    def description(self):
        print("My id is", self.identification)
        print("My age is", self.age)


class Simulation:
    def __init__(self):
        self.alive = []
        self.dead = []
        self._id = 0
        self.year = 0

    def create_agent(self):
        self.alive.append(Agent(self._id, 100, 20, "blue", 30, 0, True, True))
        self._id += 1

    def deaths(self):
        for agent in self.alive.copy():
            if agent.age > 30:
                agent.alive = False
                print("Death of", agent.identification)
                self.dead.append(agent)
                self.alive.remove(agent)

    def time_skip(self):
        print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%SKIPPING TIME%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
        self.year += 1
        print("The new year is", self.year)
        for agent in self.alive:
            agent.age += 1
        self.create_agent()
        self.deaths()

if __name__ == '__main__':
    simulation = Simulation()
    for _ in range(3):
        simulation.create_agent()

    # Testing
    for agent in simulation.alive: 
        agent.description()

    simulation.time_skip()

    for agent in simulation.alive: 
        agent.description()
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks, looks good. 1)What is the advantage of making the lists inside the class simulation? And what is the function of " name == 'main'"(i'm aware of what you wrote, i'm just hoping for more detail)? \$\endgroup\$ – Dio May 16 at 18:40
  • \$\begingroup\$ Actually, when i run it, there is an error: AttributeError: 'Simulation' object has no attribute 'id' \$\endgroup\$ – Dio May 16 at 18:46
  • \$\begingroup\$ @Dio 1) The benefit is that you're not relying on globals. It's hard to explain with the code that you have here as there isn't really a problem that the class solves. However globals lead to poor design choices. By wrapping it in a class you're preventing these bad choices prematurely. I understand it's not much of an explanation. You'll likely only understand it once you've been bitten by it once. 2) If the file is called foo.py you can run import foo from another file, with the if the code doesn't run. Without the if the code does. \$\endgroup\$ – Peilonrayz May 16 at 18:50
  • \$\begingroup\$ @Dio I made a couple of mistakes when converting to a class. They're now fixed. \$\endgroup\$ – Peilonrayz May 16 at 18:53
  • \$\begingroup\$ Great! thanks a bunch, @Peilonrayz you've been very helpful :) \$\endgroup\$ – Dio May 16 at 18:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.