John Kohan
John Kohan

Reputation: 13

Naming auto generated objects, python

Text in italic can be skipped.

First of all: Forgive me if what I'm asking for is basic knowledge, easy to find answers too, or anything similar that may make my post annoying to anyone. I'm new to programming, and just started it to have an excuse not to read for exams. I'm trying to make a program that can kind of mimic evolution from a tribe of humans to..well, a more advanced tribe of humans. My goal is to some time in the future make a very simple Civilization-like game that focuses on people rather than buildings and units. Starting from scratch, knowing pretty much nothing about programming at the moment, i know this is a task I will probably never complete. Hopefully I'll learn something on the way though. Because my knowledge is so limited, my questions will be clumsy and badly formulated. I'm sorry, thanks for reading.

The current problem: I've made a class that makes objects that are supposed to represent people.

The class looks like this at the moment:

class Settler:
    settlerCount = 0
    iqlistfemale = []
    iqlistmale = []
    maleCount = 0
    femaleCount = 0
    surnameMale = []
    surnameFemale = []

    def __init__(self, sex):
        if sex=="m" or sex=="f" or sex=="M" or sex=="F":
            self.name = choice(surnames)
            Settler.settlerCount += 1
            self.iq=round(random.normalvariate(100,10))
            if sex=="m" or sex=="M":
                self.sex = "Male"
                Settler.iqlistmale=Settler.iqlistmale+[self.iq]
                Settler.surnameMale += [self.name]
                Settler.maleCount += 1
            else:
                self.sex = "Female"
                Settler.iqlistfemale=Settler.iqlistfemale+[self.iq]
                Settler.surnameFemale += [self.name]
                Settler.femaleCount += 1

It will contain way more attributes later, this is just a beginning.

I've also made a loop that will ask you for an amount of males to create, and then an amount of females to create.

The loop-thing looks like this:

x=int(input("Number of male Settlers to generate? (1-20) "))
if x >0 and x <21:
    tellergenerator=0  
    while tellergenerator<x:
        Settler("M")
        tellergenerator=tellergenerator+1

else:
    print("Wrong input!")



x=int(input("Number of female Settlers to generate? (1-20) "))
if x >0 and x <21:
    tellergenerator=0  
    while tellergenerator<x:
        Settler("F")
        tellergenerator=tellergenerator+1

else:
    print("Wrong input!")

Also, I've made a def thing that will allow you to call for information on the attributes of an object:

def displaySettler(self):
        print("Name:", self.name, "Sex:", self.sex, "IQ:", self.iq)

Now, for the questions:

  1. Main question: My loop-thing works fine, meaning it creates the number of objects of the right sex that I want to create. My problem is that it creates objects without names, as far as I know. This means I can't do the displaySettler() call, because it requires me to do nameofobject.displaySettler(). How can I, using some sort of loop function to create a bunch of objects, make those objects with names.

I've found a way to combine a number to a string, which might allow me to put into the loop a system that creates object names like settler1, settler2, settler3, but the way I do that is to do something like

x=settler
y=(some counter)
z=x+str(y)

Is that something I can use? The only way I know to create my objects with name is by writing something like

settler1=Settler("F")

or

w=Settler("F")

is it possible to use the contents of variable z to name something?

  1. I'd also like to ask the following: As you might see from my class, I'm doing a bunch of lists. I'm thinking I have to make a list for every attribute for every sex, containing the particular attributes of all objects. I want those lists to be able to calculate the populations average value of each attribute, and things like that.

Is it possible to get those values directly from the objects, and go through all the objects directly and calculate the average from that?

Or to put it another way: If I have 200 objects, is there some way to get the IQs of all the objects added together?

Thanks for reading (if anyone got this far). All constructive feedback will be much appreciated.

Upvotes: 1

Views: 2728

Answers (4)

georg
georg

Reputation: 214949

Two things:

1) it's better to have two distinct classes, Male and Female, both of them extend the base class Settler. Thus you avoid the most of if sex = M then this else that stuff

Example:

class Settler:
    def __init__(self, name):
        self.name = name
        self.iq = round(random.normalvariate(100,10))

class Male(Settler):
    def __str__(self):
        return '{0.name}, male, iq {0.iq}'.format(self)

class Female(Settler):
    def __str__(self):
        return '{0.name}, female, iq {0.iq}'.format(self)

Note how both classes use __str__ to "represent" themselves in a string form.

2) keep all stuff concerning lists of objects outside of objects definitions. Good objects don't know what's happening outside them. For example, this is how to generate a list of people:

def generate(klass, how_many):
    surnames = ['Doe', 'Smith', 'Mueller', 'Polly-Parrot']
    return [klass(random.choice(surnames)) for _ in range(how_many)]

people = generate(Male, 10) + generate(Female, 20)

[stuff for _ in range(N)] basically means "do stuff N times".

Finally, let's put it all together and print a list of people:

for person in people:
    print(person)

The output will be something like:

Doe, male, iq 114.0
Doe, male, iq 110.0
Polly-Parrot, male, iq 89.0
Smith, male, iq 96.0
Polly-Parrot, male, iq 83.0
Mueller, female, iq 118.0
Mueller, female, iq 90.0
Smith, female, iq 90.0
Smith, female, iq 103.0
Mueller, female, iq 89.0
Smith, female, iq 87.0

Let us know if you have more questions.

Upvotes: 1

metalcharms
metalcharms

Reputation: 63

Edit: Sr2222 beat me to it. I think we are using the same idea.

Not sure if this is the best way, but:

You are able to store objects in a dict, using names generated from a loop.

As an example:

group_of_vars = {}
for name in range(5):
    entry = 'object_'+str(name)
    group_of_vars[name] = entry

print group_of_vars

print group_of_vars
{0: 'object_0', 1: 'object_1', 2: 'object_2', 3: 'object_3', 4: 'object_4

Therefore

>>> print group_of_vars[1]
object_1

So by using this knowledge, you could make a list of variable names (auto-generated or manually) and keep it in a list. Then reference the name of the list as your range in the for-loop, and refer to each variable in that list.

As for getting the sum of all IQ's of the objects added together, you could do (following my earlier example, assume that the entries in the dict are objects with iq property values)

sum = 0
for name in group_of_vars:
    sum += group_of_vars[name].iq

>>> print sum

This should return the sum of the iq property of all objects in the dict group_of_vars.

Upvotes: 0

Cameron Sparr
Cameron Sparr

Reputation: 3981

in response to your second question, and let's say that you had a list of Settlers called people (this is a list comprehension)...

iqs = [person.iq for person in people]
total_iq = sum(iqs)

Upvotes: 0

Silas Ray
Silas Ray

Reputation: 26150

You need to have your person generator record the generated people in a data structure, such as a list or dictionary, then access those people from that created structure. In place of your while loop, try:

people = []
for i in range(x):
    people.append(Settler('M')) # or 'F', for the other loop

Then you can use:

people[n].displaySettler() # where n is any integer from 0 to x-1

Upvotes: 3

Related Questions