How to create objects for a class automatically? - python

Is there any way to auto create objects in python
class A:
pass
a = A()
I would like to automatically create objects for a class.
I need to parse a bunch of xml and I'd like to create an object for one file (entry parse).
Or I need to create some random names?

You don't have to manually assign variable names to the object instances, simply store them in a list when you create them dynamically, like in this example where a list of objects gets created with information from a file:
class A:
def __init__(self, words):
self.words = words
a_objects = []
file = open("testfile.txt")
for line in file:
words = line.split()
a_objects.append(A(words))
If you need to access the objects directly using a key, you will have to use a dictionary instead of a list:
a_objects = {}
You can add key-value pairs to it like this:
words = line.split()
key = words[0]
a_objects[key] = A(words)

Related

Cleanest way to create instances of class dynamically

In caluclations.py I have one class called PowerPlant() with
def __init__(self, parameter1, parameter2, parameter3, ...)
and some functions belonging to the class e.g. calculate_supply(self, variable1, variable2).
I'd like to apply the calculations from calculations.py to some power plants stored in a csv file. So far i use the following way...
In simulation.py I read the data from the csv with pd.read_csv()
plant_data = pd.read_csv('plants.csv', sep = ';', index_col = False, encoding = 'latin')
Then i create a list of lists with
# Create list of lists from plant_data DataFrame
list_of_plants = [list(row) for row in plant_data.values]
Afterwards I create an instance of the Class PowerPlant with
## Outer loop: Iterate over all plants
for row in range(len(list_of_plants)):
ElectricityOut = []
Gains = []
...
# Initialise an instance of the plant
MyPowerPlant = PowerPlant(parameter1 = list_of_plants[row][0],
parameter2 = list_of_plants[row][1],
parameter3 = list_of_plants[row][2],
...)
# call some methods from calculations.py
...
Any ideas and suggetions how i could do this in a better and more professional way?
Maybe create a object for each plant?
You can iterate over a list like so, no need for range(len())
for row in list_of_plants:
ElectricityOut = []
Gains = []
...
# Initialise an instance of the plant
MyPowerPlant = PowerPlant(parameter1 = row[0],
parameter2 = row[0],
parameter3 = row[0],
...)
I'm not happy with accessing the list items with [item] e.g.
list_of_plants[row][0]
As far as i know there is no possibility to access lists via names (use dictionaries for that), but whats with namedTuples?
Is it possible to create instances of a class from namedTuples? If so i would change the list to a namedTuple...
Any suggestions?

Writing to textfile in a specific way using a list in python

I am trying to write to a textfile in python where the the output in the file.
I have a Class called phonebook which has a list containing objects of the phonebook class.
My constructor looks like this:
def __init__(self,name,number):
self.name = name
self.number = number
When i add a new object to the list looks like this:
def add(self):
name = input()
number = input()
p = Phonebook(name,number)
list.append(p)
When I'm writing my list to the textfile the function looks like this:
def save():
f = open("textfile.txt","w")
for x in list:
f.write(x.number+";"+x.name+";")
f.close()
And its writes out:
12345;david;12345;dave;12345;davey;09876;cathryn;09876;cathy; and so on..
should look like this:
12345;david,dave,davey
09876;cathryn,cathy,
78887;peter,pete,petr,petemon
My question is then.. How do I implement this save function so it will only write out one unique number and all its names connected to that number?
Feels like its impossible to do with only a list containing names and numbers.. Maybe im wrong..
Dictionaries in Python give you fast access to items based on their key. So a good solution to your problem would be to index the Phonebook objects using the Phonebook.number as the key to store a list of Phonebooks as the values. Then at the end just handle the printing based on however you want each line to appear.
This example should work in your case:
phone_dict = dict() # Used to store Phonebook objects intead of list
def add(self):
name = input()
number = input()
p = Phonebook(name,number)
if p.number in phone_dict:
phone_dict[p.number].append(p) # Append p to list of Phonebooks for same number
else:
phone_dict[p.number] = [p] # Create list for new phone number key
def save():
f = open("textfile.txt","w")
# Loop through all keys in dict
for number in phone_dict:
f.write(x.number + ";") # Write out number
phone_books = phone_dict[number]
# Loop through all phone_books associated with number
for i, pb in enumerate(phone_books):
f.write(pb.name)
# Only append comma if not last value
if i < len(phone_books) - 1:
f.write(",")
f.write("\n") # Go to next line for next number
f.close()
so how would the load function look?
I have tried doing one, and it loads everything into the dictionary but the program doesnt function with my other functions like it did before i saved it and reload it to the program again..
def load(self,filename):
self.dictList = {}
f = open(filename,"r")
for readLine in f:
readLine = readLine.split(";")
number = readLine[0]
nameLength = len(readLine[1:])
name = readLine[1:nameLength]
p = phonebook(name)
self.dictList[number] = [p]
print(self.dictList)
f.close()

How to add Objects to Class with a loop in Python?

I have a class which looks like this.
class CharInStageList(object):
def __init__(self, charid, charname) :
self.charid = charid
self.charname = charname
into this class I would like to add lists that I have.
I know how to do it the normal way
charOne = CharInStageList(1,'Tim')
charTwo = CharInStageList(2,'Struppi')
that's not a problem what I actually want to do is to add them by using a loop.
I get my data in this form
((1,'Tim'),(4,'Struppi'))
or
((1,'Tim'),(4,'Struppi'),(5,'Nami'),(6,'Luffy'))
the amount of characters I have in the scene is always different.
what I imagined would be a loop like this
charlist = ((1,'Tim'),(4,'Struppi'))
for char in charlist
objname = CharInStageList(char[0],char[1])
something like this
I want the objname to change by itself for every object I add to the class.
How can I get this effect?
I can only use python 2.6.6 for this since it's the maya 2013 python
Edit:
Thx #silas-ray #chepner #theodox I looked into Dicts a bit more and that's pretty much what I need
I use a modified version of #chepner method on it.
object_dict = dict( (y, CharInStageList(x,y)) for x,y in data )
Works like a charm
My testcode looks like this
import maya.cmds as cmds
dicttest = {}
def getdata ():
global dicttest
data = ((1,'Tim'),(4,'Struppi'),(5,'Nami'),(6,'Luffy'))
dicttest = dict( (y,(x,y)) for x,y in data )
getdata()
def printtest() :
for char in dicttest:
print dicttest[char]
printtest()
dicttest.clear()
I would have liked to comment in your answers with code examples but I can't get that to work there.
Objects are not added to a class. Instead, you can create a list of objects which are all instances of the same class, using a list comprehension and taking advantage of the *args syntax:
data = ((1,'Tim'),(4,'Struppi'),(5,'Nami'),(6,'Luffy'))
object_list = [ CharInStageList(*x) for x in data ]
Perhaps you want a dictionary instead:
object_dict = dict( (y, CharInStageList(x,y)) for x,y in data )
(Note that CharInStageList is a poor name for the class, because it's not a list; it encapsulates a single character.)
If you really want CharInStateList to be a collection of characters, try something like this, which is just a thin wrapper around a dictionary:
# Your former CharInStageList
class Character(object):
def __init__(self, charid, charname) :
self.charid = charid
self.charname = char name
class OnStageCharacters(object):
def __init__(self):
self.characters = dict()
# Index on-stage characters using their charid
def add(self, character):
self.characters[character.charid] = character
on_stage = OnStageCharacters()
for id, name in data:
on_stage.add( Character(id, name) )
You can't (at least not without hacking at locals/globals, which is generally not a good idea) change the name you are assigning to dynamically like that. You can, however, insert them in to a dictionary where the keys are your dynamically generated names.
characters = {}
for char_data in char_list:
characters[char_data[1]] = CharInStageList(*char_data)
Though if all your character objects are storing is name and id, it might make more sense to simplify the whole thing and just create mapping dictionaries rather than objects.
character_names_by_id = dict(char_data)
character_ids_by_name = dict((name, id) for id, name in char_data)
#chepner's answer is a great one if you can use the *args form to fill out your class instances.
If you're just asking the most efficient way to do this from a loop, remember you can have iterate over the parts of a tuple together:
data = ((1,'Tim'),(4,'Struppi'),(5,'Nami'),(6,'Luffy'))
class_data = (CharInStageList(id, name) for id, name in data) # "for id, name" will yield two vals
You can also use map, which is very common for doing bulk data translations. A common way to do it is with a lambda so you can write it clearly:
to_char = lambda k: CharInStageList(k[0], k[1])
class_data = map(to_char, data)
If you're doing something as simple as your example, you might not want to bother with your own class. the namedtuple is a great data structure for creating tuples that are easy to work with. It also means you can use positional or named args interchangeably, just as in #chepner's *args version:
StageListChar = namedtuple('CharInStageList', ['id', 'name'])
class_data = map(StageListChar , data)

Python List of classes

I'm trying to design a "Time Tracker" device. I want to be able to define a class line like:
class line():
def __init__(self, course, weekHours, hoursTotal, comment)
self.course = course
self.weekHours = weekHours
self.hoursTotal = hoursTotal
self.comment = comment
Then be able store an array (I guess it's called a list in Python?), of these class objects. So I can print a table produced by all of these lines and save these lines to an output file and then later be able to read that back into this list to view the table or make changes. do I declare table = [class line()]? If so, how do I access each of these objects in the list? I want to be able to differentiate them so I can edit a particular "line" if necessary.
You can store class instances in a list:
lines = []
lines.append(line('Math', '3', '12', 'Hello World!'))
...
To get the i'th line, you'd just do:
lines[i]
Note that there really isn't a good reason to have a class here. a python dict would be more efficient:
lines = []
lines.append({'course': 'Math', ...})

ListProperty with GoogleAppEngine

How do I assign a ListProperty with Google App Engine?
name = self.request.get("name")
description = self.request.get("description")
list = '''insert code here'''
I want list to work like a dictionary, is this possible with Google App Engine, if so, how:
[wordone : score; wordtwo : score; wordthree : score]
^I want the list property to store some data like this, how is this possible?
You actually won't be able to store a true dictionary as type in a ListProperty (it only supports datastore property types, of which dict is not one), so you won't be able to get the behavior you're looking for. Will all of the data be the same (i.e. each element represents a word score)? Assuming storing each word as its own property on the model doesn't make sense, one 'dirty' solution would be to make a ListProperty of type str, and then append the word and score as separate elements. Then, when you searched for a word in the list, you would return the value at the index position of the word + 1. That would looks something like:
class MyEntity(db.Model):
name = db.StringProperty()
description = db.TextProperty()
word_list = db.ListProperty()
You could then add words like:
new_entity = MyEntity()
new_entity.word_list = ['word1', 1, 'word2', 2, 'word3', 10]
You could then query for a particular entity and then examine its word_list property (a list), looking for your target word and returning the element one position after it.
More convoluted suggestion
However if that isn't an option, you could look into creating another model (let's say WordScore) that looked something like:
class WordScore(db.Model):
word = db.StringProperty()
score = db.IntegerProperty()
Then, whenever you needed to add a new score, you would create a WordScore instance, fill out the properties and then assign it to the proper entity. I haven't tested any of this, but the idea would be something like:
# Pull the 'other' entity (this would be your main class as defined above)
q = OtherEntity.all()
q.filter('name =', 'Someone')
my_entity = q.get()
# Create new score
ws = WordScore(parent=my_entity)
ws.word = 'dog'
ws.score = 2
ws.put()
You could then pull out the score for dog for 'Someone' by doing something like this (again, completely untested for now - be warned :) ):
# Get key of 'Someone'
q = OtherEntity.all()
q.filter('name =', 'Someone')
my_entity = q.get().key()
# Now get the score
ws = WordScore.all()
ws.filter('word = ', 'dog').ancestor(my_entity)
word_score = ws.get().score
Change to NDB and use the Pickle property:
Value is a Python object (such as a list or a dict or a string) that is serializable using Python's pickle protocol; the Datastore stores the pickle serialization as a blob. Unindexed by default.
NDB Properties
Then you can use it directly:
class table(ndb.Model):
data_dict = ndb.PickleProperty(default = {})
then
dd = table()
dd.data_dict['word_one'] = "Some_Score"

Categories

Resources