I am starting to learn about object-oriented programming and I'm having a rough time with it.
I have some questions about it:
class Record:
"""Represent a record."""
def __init__(self, category, name, value):
self._category = category
self._name = name
self._value = value
# 1. Define the formal parameters so that a Record can be instantiated
# by calling Record('meal', 'breakfast', -50).
# 2. Initialize the attributes from the parameters. The attribute
# names should start with an underscore (e.g. self._amount)
#property
def amount (self):
return self._value
# Define getter methods for each attribute with #property decorator.
# Example usage:
# >>> record = Record('meal', 'breakfast', -50)
# >>> record.amount
# -50
class Records:
"""Maintain a list of all the 'Record's and the initial amount of money."""
def __init__(self):
# 1. Read from 'records.txt' or prompt for initial amount of money.
# 2. Initialize the attributes (self._records and self._initial_money)
# from the file or user input.
self._records =[]
self._money = 0
fh = open(file='records.txt', mode='r')
if ',' not in i:
self._money = int(i.strip())
else:
raw_line = i.strip()
category, activity, value = raw_line.split(',')
x = Record(category, activity, value)
self._records.append(x)
print("Welcome back!")
fh.close()
#property
def view(self):
for i in self._records:
print(Record._category)
#1. Print all the records and report the balance.
x = Records()
Records.view()
I wanted to print out value from my newly acquired list but I don't know how to pass my data from class Records to class Record for processing. How should I approach this?
Related
I am currently working on an inventory system and trying to implement a class that serves as a "fast fact finer" for my database, which is managed by my Database Management class.
The csv file looks like this:
I have the following code:
class DataBase_Management(object):
def __init__(self):
self.result = []
def make_dict_items(self):
with open("Items2.csv") as fp:
reader = csv.reader(fp)
labels = next(reader, None)
result = []
for row in reader:
if row:
row[0] = int(row[0])
row[1] = float(row[1])
row[2] = int(row[2])
pairs = zip(labels, row)
self.result.append(dict(pairs))
def get_listofdicts(self):
return self.result
The above class manages the list of dicts, through several methods that add items, delete items, etc (not included for simplicity to question).
I also have this class I am working on:
class DB_Fact_Finder():
def __init__(self, management):
self.management = management
def return_item_num(self, item):
items = self.management.get_listodicts()
return items[item]["Item #"]
def return_price(self, item):
items = self.management.get_listodicts()
return items[item]["Price "]
def return_name(self, item):
items = self.management.get_listodicts()
return self.result[item]["Name"]
def return_qnty(self, item):
items = self.management.get_listodicts()
return self.result[item]["Quantity"]
Basically, I want the DB_Fact_Finder class to be able to look at the self.result list of dictionaries defined in the management class, and be able to find specific items such as price, quantity, etc. I tried to implement this in the above code, but feel like I am missing something key to be able to reference the self.result from another class?. How would I do this?
Usage: create instance of DataBase_Management, populate results list, pass to DB_Fact_Finder
db_management = DataBase_Management()
db_management.make_dict_items()
db_fact_finder = DB_Fact_Finder(db_management)
# example usage:
price_1 = db_fact_finder.return_price(0)
print(item_num)
# 5.99
Note there are some problems with the methods of DB_Fact_Finder.
This does not work:
def return_name(self, item):
items = self.management.get_listodicts()
return self.result[item]["Name"]
There will not be a self.results property of a DB_Fact_Finder object as you have the class defined. Same issue exists in def return_qnty
The first two methods are calling self.management correctly.
I'm currently using Python to parse CAN database files. I ran into a problem with lists during implementation and gave it a quick patch that makes it work, but it's kind of ugly and seems as if there's a more elegant solution.
I have defined an object CAN database and one of it's methods takes the file to be parsed, which contains definitions of messages in the database. I loop through each line in the file and when I come across a line indicating a message description, I create a temporary variable referencing an object I've defined for CAN messages, some of the members of which are lists. I put elements in these lists with a method based on the next handful of lines in the file.
Now when I'm done with this temporary object, I add it to the CAN database object. Since I no longer need the data referenced by this variable, I assign the value None to it and reinstantiate the clean slate variable on the next iteration through that detects a message descriptor. Or that was the plan.
When I go through the next iteration and need to use this variable, I add some values to these lists and find that they're not actually empty. It seems that despite assigning the variable to reference None the values in the lists persisted and were not cleaned up.
Below you can see my solution which was to stack more methods on specifically to get rid of the persisting list elements.
Here's some relevant portions of the file:
Parsing Loop
for line in file:
line = line.rstrip('\n')
line_number += 1 # keep track of the line number for error reporting
if line.startswith("BU_:"):
self._parseTransmittingNodes(line)
elif line.startswith("BO_"):
can_msg = self._parseMessageHeader(line).ResetSignals().ResetAttributes()
building_message = True
elif line.startswith(" SG_") and building_message:
can_msg.AddSignal(self._parseSignalEntry(line))
# can_msg.updateSubscribers()
elif line == "":
if building_message:
building_message = False
self._messages += [can_msg]
can_msg = None
Reset Methods
def ResetSignals(self):
"""
Flushes all the signals from the CANMessage object.
"""
self._signals = []
return self
def ResetAttributes(self):
"""
Flushes all the attributes from the CANMessage object.
"""
self._attributes = []
return self
How can I make this variable a fresh object every time? Should I have a method that clears all of it's internals instead of assigning it None like the IDispose interface in C#?
EDIT: Here's the full source for the CANMessage object:
class CANMessage:
"""
Contains information on a message's ID, length in bytes, transmitting node,
and the signals it contains.
"""
_name = ""
_canID = None
_idType = None
_dlc = 0
_txNode = ""
_comment = ""
_signals = list()
_attributes = list()
_iter_index = 0
_subscribers = list()
def __init__(self, msg_id, msg_name, msg_dlc, msg_tx):
"""
Constructor.
"""
self._canID = msg_id
self._name = msg_name
self._dlc = msg_dlc
self._txNode = msg_tx
def __iter__(self):
"""
Defined to make the object iterable.
"""
self._iter_index = 0
return self
def __next__(self):
"""
Defines the next CANSignal object to be returned in an iteration.
"""
if self._iter_index == len(self._signals):
self._iter_index = 0
raise StopIteration
self._iter_index += 1
return self._signals[self._iter_index-1]
def AddSignal(self, signal):
"""
Takes a CANSignal object and adds it to the list of signals.
"""
self._signals += [signal]
return self
def Signals(self):
"""
Gets the signals in a CANMessage object.
"""
return self._signals
def SetComment(self, comment_str):
"""
Sets the Comment property for the CANMessage.
"""
self._comment = comment_str
return self
def CANID(self):
"""
Gets the message's CAN ID.
"""
return self._canID
def AddValue(self, value_tuple):
"""
Adds a enumerated value mapping to the appropriate signal.
"""
for signal in self:
if signal.Name() == value_tuple[0]:
signal.SetValues(value_tuple[2])
break
return self
def AddAttribute(self, attr_tuple):
"""
Adds an attribute to the message.
"""
self._attributes.append(attr_tuple)
return self
def ResetSignals(self):
"""
Flushes all the signals from the CANMessage object.
"""
self._signals = []
return self
def ResetAttributes(self):
"""
Flushes all the attributes from the CANMessage object.
"""
self._attributes = []
return self
def Name(self):
return self._name
def TransmittingNode(self):
return self._txNode
def DLC(self):
return self._dlc
The problem you're seeing is because you used class attributes instead of instance attributes. If you move the initialization of the attributes you don't pass to __init__ from class scope into __init__, each instance will have its own set of lists.
Here's what that would look like:
class CANMessage:
"""
Contains information on a message's ID, length in bytes, transmitting node,
and the signals it contains.
"""
def __init__(self, msg_id, msg_name, msg_dlc, msg_tx):
"""
Constructor.
"""
self._canID = msg_id
self._name = msg_name
self._dlc = msg_dlc
self._txNode = msg_tx
self._name = ""
self._canID = None
self._idType = None
self._dlc = 0
self._txNode = ""
self._comment = ""
self._signals = list()
self._attributes = list()
self._iter_index = 0
self._subscribers = list()
# the rest of the class is unchanged, and not repeated here...
Merry Christmas!
I was trying to generate some code which would make a sort of database using the information provided by the user.
Can I use input() method to define my instance variables?
class Compound:
def __init__(self, name, state, molecular_mass, concentration, concentration_measure):
self.nome = name
self.state = state
self.mol_mass = molecular_mass
self.conc = concentration
self.measure = concentration_measure
def summary(self):
return ('Your compound is {} it has a state of {} it has a molecular mass of {} g/mol and a concentration of {} and a measure of {}'
.format(self.name, self.state, self.mol_mass, self.conc, self.measure))
def ask_compounds():
self.nome = input("Name?")
self.state = input('Solid or Liquid')
self.mas_mol = input('Absolute number for molecular weight?')
self.conc = input('Concentration?')
self.measure = str(input('In M? In g/ml?'))
ask_compounds()
Thank you for your help!
Of course you can. Either return the inputted values and initialize a Compound class with them:
def ask_compounds():
nome = input("Name?")
state = input('Solid or Liquid')
mas_mol = input('Absolute number for molecular weight?')
conc = input('Concentration?')
measure = input('In M? In g/ml?')
return nome, state, mas_mol, conc, measure
inst = Compound(*ask_compounds())
or, even better, make ask_compounds a classmethod that creates instances for you:
class Compound:
def __init__(self, name, state, molecular_mass, concentration, concentration_measure):
# snipped for brevity
def summary(self):
# snipped for brevity
#classmethod
def ask_compounds(cls):
nome = input("Name?")
state = input('Solid or Liquid')
mas_mol = input('Absolute number for molecular weight?')
conc = input('Concentration?')
measure = input('In M? In g/ml?')
return cls(nome, state, mas_mol, conc, measure)
inst = Compound.ask_compounds()
As an aside, you're using nome in __init__ and ask_components but name in summary, change one of the two to the other.
I have a large set of data which I access via a generator/iterator. While processing the dataset I need to determine if any record in that dataset has an attribute with the same value as an attribute of the current record being processed. One way to do this would be with a nested for loop. For example, if were processing a database of students, I could do something like:
def fillStudentList():
# TODO: Add some code here to filll
# a student list
pass
students = fillStudentList()
sameLastNames = list()
for student1 in students1:
students2 = fillStudentList()
for student2 in students2:
if student1.lastName == student2.lastName:
sameLastNames.append((student1, student2))
Granted the code snippet above could be improved quite a bit. The goal of the snippet is to show the nested for loop pattern.
Now let's say that we have a class Student, a class Students (which) is an iterator, and a class Source which provides access to the data in a memory efficient way (say another iterator) of sorts...
Below, I have sketched out what this code might look like. Does anyone have ideas on how to improve this implementation? The goal is to be able to find records in very large datasets with the same attributes so that that filtered set can then be processed.
#!/usr/bin/python
from itertools import ifilter
class Student(object):
"""
A class that represents the first name, last name, and
grade of a student.
"""
def __init__(self, firstName, lastName, grade='K'):
"""
Initializes a Student object
"""
self.firstName = firstName
self.lastName = lastName
self.grade = grade
class Students(object):
"""
An iterator for a collection of students
"""
def __init__(self, source):
"""
"""
self._source = source
self._source_iter = source.get_iter()
self._reset = False
def __iter__(self):
return self
def next(self):
try:
if self._reset:
self._source_iter = self._source.get_iter()
self._reset = False
return self._source_iter.next()
except StopIteration:
self._reset = True
raise StopIteration
def select(self, attr, val):
"""
Return all of the Students with a given
attribute
"""
#select_iter = self._source.get_iter()
select_iter = self._source.filter(attr, val)
for selection in select_iter:
# if (getattr(selection, attr) == val):
# yield selection
yield(selection)
class Source(object):
"""
A source of data that can provide an iterator to
all of the data or provide an iterator to the
data based on some attribute
"""
def __init__(self, data):
self._data = data
def get_iter(self):
"""
Return an iterator to the data
"""
return iter(self._data)
def filter(self, attr, val):
"""
Return an iterator to the data filtered by some
attribute
"""
return ifilter(lambda rec: getattr(rec, attr) == val, self._data)
def test_it():
"""
"""
studentList = [Student("James","Smith","6"),
Student("Jill","Jones","6"),
Student("Bill","Deep","5"),
Student("Bill","Sun","5")]
source = Source(studentList)
students = Students(source)
for student in students:
print student.firstName
for same_names in students.select('firstName', student.firstName):
if same_names.lastName == student.lastName:
continue
else:
print " %s %s in grade %s has your same first name" % \
(same_names.firstName, same_names.lastName, same_names.grade)
if __name__ == '__main__':
test_it()
Nested loops are O(n**2). You can instead use a sort and itertools.groupby for O(nlogn) performance:
students = fill_student_list()
same_last_names = [list(group) for lastname, group in
groupby(sorted(students, key=operator.attrgetter('lastname'))]
In general, you appear to be trying to do what an ORM backed by a database does. Instead of doing it yourself, use one of the many ORMs already out there. See What are some good Python ORM solutions? for a list. They will be both more optimized and more powerful than something you would code yourself.
Perhaps something like this would work for you (this is O(n))
from collections import defaultdict
students = fillStudentList()
sameLastNames = defaultdict(list)
for student in students:
sameLastNames[student.lastName].append(student)
sameLastNames = {k:v for k,v in sameLastNames.iteritems() if len(v)>1}
I'm trying code nearly identical to the example from the manual to enable a download counter but I get an exception:
File "/media/Lexar/montao/wwwblob/handler.py", line 117, in FileInfo
download_count = db.IntegerProperty(required=True, count=0) TypeError: init() got an unexpected keyword argument 'count'
Here's the code I try to run:
from google.appengine.ext import deferred
from google.appengine.runtime import DeadlineExceededError
class Mapper(object):
# Subclasses should replace this with a model class (eg, model.Person).
KIND = None
# Subclasses can replace this with a list of (property, value) tuples to filter by.
FILTERS = []
def __init__(self):
self.to_put = []
self.to_delete = []
def map(self, entity):
"""Updates a single entity.
Implementers should return a tuple containing two iterables (to_update, to_delete).
"""
return ([], [])
def finish(self):
"""Called when the mapper has finished, to allow for any final work to be done."""
pass
def get_query(self):
"""Returns a query over the specified kind, with any appropriate filters applied."""
q = self.KIND.all()
for (prop, value) in self.FILTERS:
q.filter('%s =' % prop, value)
q.order('__key__')
return q
def run(self, batch_size=100):
"""Starts the mapper running."""
self._continue(None, batch_size)
def _batch_write(self):
"""Writes updates and deletes entities in a batch."""
if self.to_put:
db.put(self.to_put)
self.to_put = []
if self.to_delete:
db.delete(self.to_delete)
self.to_delete = []
def _continue(self, start_key, batch_size):
q = self.get_query()
# If we're resuming, pick up where we left off last time.
if start_key:
q.filter('__key__ >', start_key)
# Keep updating records until we run out of time.
try:
# Steps over the results, returning each entity and its index.
for (i, entity) in enumerate(q):
(map_updates, map_deletes) = self.map(entity)
self.to_put.extend(map_updates)
self.to_delete.extend(map_deletes)
# Do updates and deletes in batches.
if (i + 1) % batch_size == 0:
self._batch_write()
# Record the last entity we processed.
start_key = entity.key()
self._batch_write()
except DeadlineExceededError:
# Write any unfinished updates to the datastore.
self._batch_write()
# Queue a new task to pick up where we left off.
deferred.defer(self._continue, start_key, batch_size)
return
self.finish()
class FileInfo(db.Model):
blob = blobstore.BlobReferenceProperty(required=True)
download_count = db.IntegerProperty(required=True, count=0)
uploaded_by = db.UserProperty(required=True)
uploaded_at = db.DateTimeProperty(required=True, auto_now_add=True)
class DailyTotal(db.Model):
date = db.DateProperty(required=True, auto_now_add=True)
file_count = db.IntegerProperty(required=True)
download_count = db.IntegerProperty(required=True)
class DownloadCountMapper(Mapper):
KIND = FileInfo
def __init__(self):
self.file_count = 0
self.download_count = 0
def map(self, file):
self.file_count += 1
self.download_count += file.download_count
def finish(self):
total = DailyTotal(file_count=self.file_count,
download_count=self.download_count)
total.put()
Can you tell me what I should do?
Thank you
This line is the culprit:
download_count = db.IntegerProperty(required=True, count=0)
The IntegerProperty constructor doesn't know what to do with count. Maybe you meant this:
download_count = db.IntegerProperty(required=True, default=0)