Create and Instantiate objects in python when the program in running - python

I'm making a program for calculate the electrical consumption of a building starting from the characteristics of the building, like the number of apartments and its type, I mean all not need to be of the same size for example, so I create a class called apartment, something like this:
class apartamento:
def __init__(self):
self.area = 0
self.cantidad = 0
self.altura = 0
self.personas = 0
self.area = 0
self.dotacion = 0
self.cto_alum = 0
self.cto_tug = 0
self.cto_e = 0
So I could have let's say thirty apartments fifteen of 100m^2 and others fifteen of 80m^2, the I want:
type1 = apartamento()
type2 = apartamento()
type1.area = 100
type2.area = 80
But since I dont know how many types of apartments are, I need to create them when the program is running in a loop for example
When I say I don't know how many types of apartments are, I refer to the fact that this could be used for someone else, in differents sets of buildings, so in one It could be only one type of apartment and in other could be ten, and this has to be transparent to the user, now I have a spin box to put how many types of apartments are and then I create a table to put all the data of them, their size, number of person, number of circuits that it has, the problem is that them I have to make some calculations on this data so I want to instantiated every type of apartment as a object with the atributes that are put in the table, now I dont known how many types there will be, it depends of the building.

Most complex programs solve this problem using a reload feature that they incorporate into some kind of daemon. For instance nginx
service nginx reload
Will update sites with new configuration parameters without having to actually restart the server.
In your case since this sounds like a more simple program you can always just have a python config file and read from it at a set interval.
import imp
config_module = imp.load_source("config", "/path/to/config.py")
And your configuration could look like
CONFIG = {
"type1": {
"altura": 10,
"personas": 2,
"cantidad": 5,
},
"type2": {
...
}
}
At a certain interval you can just ask your program to look up the source of the configuration module and then you won't have to worry about your configuration being up to date.
Either that or you can just stop your program and then run it again in order to pick up the latest changes without having to wait for your config to reload.
After the configuration is updated you can create new apartment objects as you desire
apartmentos = {}
for type, values in config_module.CONFIG.iteritems():
apartmentos[type] = Aparatmento(values)
Where Apartmento now accepts a new dictionary of configuration
class Apartmento(object):
def __init__(self, config):
personas = config["personas"]
altura = config["altura"]
...

Without knowing what exactly is it that you need, this is my take on it.
It's most likely the dumbest approach to it. It looks to me like all you want to create is a building with some fixed number of apartments, some of which are of type 1 some of which are type 2.
Types of apartments don't sound to me like something that is preset, but more like something that is specific to each building and its plans. I.E. some buildings have apartments split in 2 categories, 100m^2 and 80m^2 and some have 90 and 50?
`class apartment:
def __init__(self, area):
self.area = area
class building:
def __init__(self, ntypesOfapartments):
self.ntypesOfapartments = ntypesOfapartments
self.apartments = list()
for i in range(ntypesOfapartments):
area = input("Area of {0}. type of apartment: ".format(i))
n = input("Number of apartments of area {0}: ".format(area))
for j in range(int(n)):
self.apartments.append(apartment(area))
def __str__(self):
desc = "Building has {0} types of apartments \n".format(self.ntypesOfapartments)
desc += "Total number of rooms is {0}.".format(len(self.apartments))
return desc
So you can instantiate a building with n different apartment types, and then define your apartment types interactively in the interpreter.
>>> test = building(2)
Area of 0. type of apartment: 100
Number of apartments of area 100: 5
Area of 1. type of apartment: 80
Number of apartments of area 80: 10
>>> print(test)
Building has 2 types of apartments
Total number of rooms is 15.
>>>
Of course it would be a lot better to use a more sensical data structure than a list to hold the apartments, like a dictionary. That way you could access apartment type 1 in a dictionary under which you could have a list of all apartments that match your defined type 1.
This also very depends on the type of calculations you want to do with them? What are all the important data that you have to use in those calculations? In this example I only instantiate apartment area, if it turns out that number of people that live in it, is important to your calculations too, then it doesn't make sense to instantiate all of that by hand. Also what do you mean you don't know how many apartment types there are? What do you consider as a "running python program"? Do you mean interpreter, or are you writing something else?

Related

Python: Conditionals for new variable with three classes

I want to create a new variable with include all drugs DS59 - DS71 (values currently coded: 1 = never used, 2 = rarely use, 3 = occasionally use, and 4 = regularly use). I want one of three classes to be assigned to each subject as laid out below:
no user: no use on any of the drugs (all 1's)
experimenter/light user: low overall score on drug use across all classes (total summed score less than 20) and no "regularly use (4)" answers to any drug classes
regular user - high overall score on drug use across all classes (score above 20) and at least one "occasionally use (3)" or "regularly use (4)" answer to any drug class
This is my current code - I am unsure how to most appropriately write the conditionals.
druglist=[(df['DS59']),(df['DS60']),(df['DS61']),(df['DS62']),(df['DS63']),
(df['DS64']),(df['DS65']),(df['DS66']),(df['DS67']),(df['DS68']),
(df['DS69']),(df['DS70']),(df['DS71'])]
conditions=[
(druglist== ),
(druglist==),
(druglist== ),
]
values=['no user','experimenter/light user','regular user']
df['drugs']=np.select(conditions,values)
Thank you so much for any help/advice.
If I understood correctly, this should be what you're looking for. Let me know if not:
drug_sum = sum(druglist)
conditions = [
(drug_sum == len(druglist)), # If it equals the length, that means every item is 1
(drug_sum <= 20 and not 4 in druglist),
(drug_sum > 20 and (3 in druglist or 4 in druglist)),
]
Though I'm not sure, do these conditions not leave some cases not fitting into any of the options? For example if a person is 1 on everything but one drug, on which they are 4.

What would be the most efficient or useful way to store attendance data?

I want to move my schools attendance records away from excel sheets and into python, but I'm not sure what the best way to store that data would be.
Method 1
Create a dictionary with student names as keys, and the dates they attended as items in a list. Or perhaps a list of the days they were absent would be more efficient.
attendance = {}
attendance["student_1"] = [2018-08-10, 2018-08-15, 2018-08-20]
Method 2
Create a dictionary of dates and append a list of students who were present on that day:
attendance = {}
attendance["2018-08-10"] = [student_1, student_2, student_3]
Method 3
Created nested dictionaries. Students names as the outer keys. All dates as inner keys with a boolean as a value.
attendance = {}
attendance["student_1"]= {}
attendance["student_1"]["1018-08-10"] = 'True'
All of these would probably work, but there must be a better way of storing this data. Can anyone help?
I should add that I want to be able to access the student's attendance record from name and retrieve all the student names that were present given a particular date.
It Completely depends on your use case. Each method has got its own advantage.
Method 1
attendance = {}
attendance["student_1"] = [2018-08-10, 2018-08-15, 2018-08-20]
total_days_present_student_1 = len(attendance["student_1"])
You have the advantage of getting easily the no. of days a student was present
Method 2
attendance = {}
attendance["2018-08-10"] = [student_1, student_2, student_3]
total_student_present_on_2018_08_10 = len(attendance["2018-08-10"])
You have the advantage of getting the total no. of students present on a particular day
Method 3
attendance = {}
attendance["student_1"]= {}
attendance["student_1"]["1018-08-10"] = 'True'
Not really any special advantage which the other 2 methods are providing
I'm not sure whether you've delved into OOP (object-oriented programming), but this approach may be useful if you need to store more than just attendance in the future. See my 'basic' example:
Setup objects
students = []
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
self.attendance = {}
def add_attendance(date, students, values):
for student, val in zip(students, values):
student.attendance[date] = val
Setup students
This part could be done by reading from a text file with student data, but I've simplified here for brevity.
students = [
Student('Bob', 15),
Student('Sam', 14)
]
Add a day and record attendance
Again, I've hard-coded the dates here, but this would obviously come from an external source; the datetime module may prove useful here.
current_date = '27-08-2018'
attendance_values = [
True, # for Student(Bob)
False # for Student(Sam)
]
add_attendance(current_date,
students,
attendance_values)
Now, I'll add a 2nd day (Hard-coded for demonstration):
current_date = '28-08-2018'
attendance_values = [True, True]
add_attendance(current_date, students, attendance_values)
Display information
I can easily display all information:
>>> print('\n'.join([str(s.attendance)
... for s in students]))
{'27-08-2018': True, '28-08-2018': True}
{'27-08-2018': False, '28-08-2018': True}
Or, in a more 'friendly' way, and with each student name:
>>> print('data for 27-08-2018:')
>>> for student in students:
... print('{:>10}: {}'.format(student.name,
... student.attendance['27-08-2018']))
data for 27-08-2018:
Bob: True
Sam: False
Storing externally
Currently, all data will be lost on the program's termination, so a possible text file structure could be the following.
Students:
Bob 15
Sam 14 # more data fields in columns here
Attendance:
27-08-2018
Bob True # or anything else to signify they were present
Sam False
28-08-2018
Bob True
Sam True
Now you could read each file line by line, splitting by whitespace for the 'students' file, but for the 'attendance' file, things will most certainly be more difficult. This all depends on what data you include in your attendance file: it could just be a date with True/False values or a fully formatted record.
I want to move my schools attendance records away from excel sheets and into python, but I'm not sure what the best way to store that data would be.
Actually, none of the example you posted are about storing data (persist them between program executions). Updates to your attendance dict during the program's execution will be lost when the process finishes, and I seriously doubt you want your program users to edit the python code to add or change data.
To make a long story short, this kind of programs want a SQL database - which not only takes care of persisting your data but also makes querying much easier.

Create random, unique variable names for objects

I'm playing around with Python and any programming language for the first time, so please bear with me. I started an online class two weeks ago, but try to develop a small game at the side to learn faster (and have fun). It's a text adventure, but is shall have random encounters and fights with enemies that have random equipment that the players can then loot.
This is my problem: If I create random objects/weapons for my random encounter, I need to make sure that the object has a unique name. The way the level is designed there could in theory be an infinite number of objects (it can be open ended, with encounters just popping up).
This is my approach so far
class Item_NPCs: #create objects for NPCs
def__init__(self, item_type, item_number):
# e.g. item_type 1 = weapons, item_type2 = potions, etc.
if item_type == 1 and item number == 1:
self.property1 = 5
self.property2 = 4
if item_type == 1 and item_number ==2:
# etc. :)
def prepare_encounter():
inventory_NPC = [] # empty list for stuff the NPC carries around
XXX = Class_Item(item_type, item_number) # I might randomize the arguments.
What is important is that I want "XXX" to be unique and random, so that no object exists more than once and can later be put into the player's inventory.
How to do that?
Joe
Why do you need it to be random ? You could simply use a list, and append every new object to the list, with its index being its unique identifier :
items = []
items.append( Class_Item(item_type, item_number) )
But if you really need random identifier, maybe you can use a dictionary :
items = dict()
items[random_id] = Class_Item(item_type, item_number)
This requires random_id to be hashable (but it should be if it is a number or a string).
I don't know why others haven't thought of this:
yourvariableName = randint(0,1000)
exec("var_%s = 'value'" % yourVariableName)
I just thought of it myself. I hope it helps you.
A downside is you can't just do this:
print(var_yourVariableName)
you can only do this:
exec("print(var_%s)" % yourVariableName)
But you can probably circumvent this one way or another. Leave a comment if you manage to figure it out.
One more downside — if used in certain ways, it could be very insecure (as we are using exec), so make sure to cover any holes!

What kind of model field to use for a two dimensional array in Django?

I'm new to Django and I'm trying to create a Battleship game. I want to create a model for my battleship board, which is going to be 10 rows and 10 columns, with each spot having a coordinate of [x,y]. I'm not sure which model field to use though. So far, this is the code I have for my Board class:
class Board(models.Model):
ships_left = models.IntegerField()
available_spots = models.??? #This is to contain [x,y] coordinates of open spots
One possibility is to create a Coordinate class, and have every possible coordinate pair represented:
class Coordinate(models.Model):
x = models.IntegerField()
y = models.IntegerField()
board = models.ForeignKey(Board)
hit = models.BooleanField(default=False)
ship = models.ForeignKey(Ship, null=True) # assumes you have Ship objects somewhere
You can hit a location as follows (assuming board is a Board object):
x = 2
y = 3
location = board.coordinate_set.filter(x=x, y=y)
if location.ship != None:
# hit a ship! Do something with location.ship object
# either way, save that it was hit
location.hit = True
location.save()
This would not be efficient for a large grid, but in this case there are only 100 coordinates per board, so it will likely be reasonable and intuitive.
You might want to consider representing the board as one or more NumPy 2-dimensional arrays. For example, you could use a boolean 2d array to track the coordinates upon which a player has already fired, and an integer array to represent the positions of various ships, by giving each ship type a unique integer value (e.g., 0 for open ocean, 1 for destroyer, 2 for carrier, etc.). This will make it very easy to look up whether an attack was a hit and on what type of ship.
Serialization of the array into the database will require a little bit of work; I'd start by having a look at this article; it will show you what model methods to consider overriding. In the comments, there is a recommendation to just use cPickle with django-picklefield, which is the route I'd try first, for simplicity.
If it's a one-to-one relationship, I would simply split the coordinate into 2 fields:
class Board(models.Model):
ships_left = models.IntegerField()
x = models.IntegerField()
y = models.IntegerField()
Problem solved. I don't see the need of building another model and link it with a foreign key. Complicates things and incurs one more join, which is real cost.

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:
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?
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.
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
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.
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)
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.

Categories