I'm making a very simple to-do list application and I'm trying to create a list for each instance of my class. I was looking to have seven lists, one for each day, which would be used to store tasks however I can't get my head around it. Example of what I am trying to do:
class Day:
def __init__(self, name, todo_list):
self.name = name
self.todo_list = todo_list
day_Mon = Day('Monday', (MonList=[]))
day_Tue = Day('Tuesday', (TueList=[]))
...
I am very new to OOP and I'm just doing this to try try improve my understanding so I'm not sure if this is even possible/sensible (I've only seen questions about creating lists of instances). Is anyone able to help?
How about something like this?
class Day:
def __init__(self, name, todo_list=None):
self.name = name
if todo_list:
self.todo_list = todo_list
else:
self.todo_list = []
day_Mon = Day('Monday', ['errands', 'study'])
day_Tue = Day('Tuesday',['laundry', 'cook'])
day_Wed = Day('Wednesday')
The constructor accepts two arguments name and todo_list. Notice that todo_list has a default value of an empty list. So the only mandatory argument to create this object is a name - day_Wed is an object where the todo_list attribute is initialized an empty list. It is common when writing classes to have mandatory and optional arguments.
Your initializer can require a name parameter and allow an optional todo_list that defaults to an empty list.
For reasons you should learn about but I won't go in to here, you should never use an empty list as a default value of a function parameter, so we'll use None and then set the desired value in __init__.
>>> class Day:
... def __init__(self, name, todo_list=None):
... self.name = name
... self.todo_list = todo_list if todo_list else []
>>> day_Mon = Day('Monday')
>>> day_Mon.todo_list
[]
>>> day_Tue = Day('Tuesday', ['wash clothes', 'pack'])
>>> day_Tue.todo_list
['wash clothes', 'pack']
You could store the 7 days in a list or dictionary, but its common in OOP to define a container class that provides useful accessors. Here is one that lets you address days of the week by case-insensitive name or number (assuming Sunday is 0).
import datetime
class Day:
def __init__(self, name, todo_list):
self.name = name
self.todo_list = todo_list
class Week:
weekday_names = ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
'Friday')
weekday_index = {name.lower():idx
for idx,name in enumerate(weekday_names)}
weekday_index.update({idx:idx for idx in range(7)})
def __init__(self):
self.days = [Day(name, []) for name in self.weekday_names]
def __getitem__(self, name_or_ord):
if isinstance(name_or_ord, str):
name_or_ord = name_or_ord.lower()
return self.days[self.weekday_index[name_or_ord]]
def __setitem__(self, name, day):
raise ValueError("Cannot set days in week")
week = Week()
week['Sunday'].todo_list.append('dinner with parents')
week['Monday'].todo_list.append('laundry')
print("Monday's tasks:",
', '.join(week['monday'].todo_list))
print("Today's tasks:",
', '.join(week[datetime.date.today().weekday()].todo_list))
Related
I have several classes that were built, one that includes a list of items, and I have to access the list from a function call, using one of the other classes. The issue is, that when I try to access it, I keep getting the object, rather than the list of items in the class.
class Owner:
def __init__(self, name):
self.name = name
self.pets = []
def get_pets_string(a_owner):
result = "{0} {1}'s pets are: {2}.".format(a_owner.name.first, a_owner.name.last, a_owner.pets)
return result
I get the owner names just fine, and I know the pet names are in the list, but cannot access them at all. I've tried using a_owner.pets.name in various ways, I've tried to access the main class, but I am not sure what I'm missing.
Something like this?
class Name():
def __init__(self, first: str, last: str) -> None:
self.first = first
self.last = last
class Owner:
def __init__(self, name: Name, pets: list) -> None:
self.name = name
self.pets = pets
def get_pets_names(self) -> list:
pets_names = []
for pet in self.pets:
pets_names.append(pet.first)
return pets_names
def get_pets_string(a_owner: Owner) -> str:
result = "{0} {1}'s pets are: {2}.".format(a_owner.name.first, a_owner.name.last, a_owner.get_pets_names())
return result
a_owner = Owner(Name("John", "Smith"), [Name("Cat", None), Name("Dog", None)])
print(get_pets_string(a_owner))
a_owner.pets will give you the list.
You can pretty-print it in this way:
from pprint import pp
pp(a_owner.pets)
If there's anything in the list, so len(a_owner.pets) > 0, then
a_owner.pets[0] will give you the 1st element.
To conveniently format all list elements into a single string
you can use this .join() expression:
print(', '.join(a_owner.pets))
I'm facing problem with my code. In fact, I need to create a list of instances of my class( Patent). The name of the list is patent_ints. But when I'm trying to verify if any element in that list is a Patent one, I'm always getting a False response. And when iterating the first element is like "<__main__.Patent at 0x7f107820b710>".
Here is my code, I need help !
import json
import datetime
patent_data = json.loads(open('NASA_data.json', "r").read())
unique_center = []
for thing in patent_data["Patent_Information"]["Results"]:
for val in thing:
if(val == 'NASA Center'):
unique_center.append(thing[val])
total_num_centers = len(set(unique_center))
class Patent:
def __init__(self, abbreviated_organization_name, dict_data):
self.org_name = abbreviated_organization_name
self.title = dict_data["Title"]
# initialize instance variable called year. The value can be extracted from dict_data.
# This should be a four digit string.
self.year = str(datetime.datetime.strptime(dict_data['Date'], '%m/%d/%Y').year) #dict_data['Date'].split('/')[2]
# initialize an instance variable called month. The value can be extracted from dict_data.
# This should be a two digit string.
self.month = str(datetime.datetime.strptime(dict_data['Date'], '%m/%d/%Y').month) #dict_data['Date'].split('/')[0]
# initialize an instance variable called day. The value can be extracted from dict_data.
# This should be a two digit string.
self.day = str(datetime.datetime.strptime(dict_data['Date'], '%m/%d/%Y').day) #dict_data['Date'].split('/')[1]
self.id = dict_data['Case Number']
self.access_limit = dict_data['SRA Final']
patent_ints = [Patent(i, data) for i in unique_center for data in patent_data["Patent_Information"]["Results"]]
patent_ints[0]
Thank you in advance!
<__main__.Patent at 0x7f107820b710> is the default representation of the class when you try to print it. Add an __str__ or __repr__ method to the class and define some custom logic to return your desired details as a string:
class Patent:
def __init__(self, abbreviated_organization_name, dict_data):
...
def __repr__(self):
# return a dictionary of items in the class but you can return whatever you want
# you could do f'{self.title} {self.id} {self.year}-{self.month}-{self.day}' but str(self.__dict__) is quick to test
return str(self.__dict__)
class Course:
'''
A class representing a course offering that includes the following
information about the course: subject, course number, section,
enrolment cap, lecture days, lecture start time, lecture duration
in minutes, and unique student numbers of the students enroled.
If lectures occur on multiple days, they will all start at the same time.
'''
def __init__(self, subject, number, section, cap, days, start_time, dur):
'''
returns a new Course object with no students enroled, given
the subject, number, section, cap, days, start_time, and dur
__init__: Str Nat Nat Nat Str Time Nat -> Course
requires: number is a 3-digit number, section > 0, cap > 0,
days is string containing substrings representing the days
of the week 'M', 'T', 'W', 'Th', 'F', where if the course is
offered on more than one day, the days appear in order and
are separated by a single dash. For example, 'M-T-Th'
indicates the course is offered on Monday, Tuesday, and Th.
'''
self.subject = subject
self.number = number
self.section = section
self.cap = cap
self.days = days
self.start_time = start_time
self.dur = dur
def add_student(self, student_id):
'''
adds a student to the course enrolment if there is room in the course
if the number of students enroled already matches the
enrolment cap, then print the message "Course full"
if the student is already enroled in the course, the there is no
change to the Course object, and the message "Previously enroled"
is printed.
add_student: Course Nat -> None
Effects: Mutates self. May print feedback message.
'''
pass
For the method add_student, how would i implement a list if it not in the init method, (CANT ADD IT TO THE INIT METHOD)? The list need to be connected with the object so later on i can remove students from that list.
You can add it in the __new__ method instead:
class Course:
def __new__(cls, *args, **kwargs):
course = super(Course, cls).__new__(cls)
course.students = []
return course
naive method: try if the member exists, catch the attribute error, and create it if doesn't exist.
def add_student(self, student_id):
try:
self.__list
except AttributeError:
self.__list = []
self.__list.append(student_id)
better use a "getter" instead to make sure the list is created when you access it from whatever method:
def get_list(self):
try:
self.__list
except AttributeError:
self.__list = []
return self.__list
then add_student becomes:
def add_student(self, student_id):
self.get_list().append(student_id)
of course adding it to __init__ is better if you don't have some strange constraints...
You can initialize the list with a property getter, so that it would be initialized whenever it is first accessed:
class Course:
#property
def students(self):
try:
return self._students
except AttributeError:
self._students = []
return self._students
#students.setter
def students(self, value):
self._students = value
I am trying to figure out how to create variables from a list of tuple and assign them to a class.
I have data organized like this
Name Age Status
John 30 Employed
That I have created a list of tuple like this
employeelist = [(John, 30, Employed), (Steve, 25, Part-Time)]
And a class set up like this
class Employee():
ecount = 0
elist = []
def __init__(self, name, age, emp_status):
self.name = name
self.age = age
self.emp_status = emp_status
self.lookup = {}
Employee.ecount = Employee.ecount+1
Employee.elist.append(self.name)
Using this code I am able to turn the tuple into an instance of the class
for i in range(0, len(employeelist),1):
sublist = [str(n) for n in employeelist[i]]
Employee(sublist[0], sublist[1], sublist[2])
But I am not able to access them. Is there a way to think about setting up the for loop to create a variable from sublist[0] and then create a class out of it (e.g. sublist[0] = Employee(sublist[0], sublist[1], sublist[2]))?
You just need
employees = [Employee(*v) for v in employee_list]
Note that employees and Employee.elist are essentially the same once
each Employee object has been created.
I'm fairly new to the world of python and programming in general, and its rare that i get up the nerve to ask questions, but I'm stomped so i thought id suck it up and ask for help.
I'm making an Address book.
class Person():
def __init__(self,name,number,email):
self.name = name
self.number = number
self.email = email
contact = Person('Mike','1-800-foo-spam','email#email.com')
My question is how would go about storing all these attributes in a dictionary with contact.name as the key and contact.number and contact.email as the values.
Bonus question.
Should the dictionary be outside the class, perhaps in the main function?
or
Does it need to be a class variable(not completely sure how those work)
or an object variable
something like
self.storage = {}
Any help would be greatly appreciated.
Thank you!
If I put this information in a dictionary, I would do it like that:
class Person():
def __init__(self,name,number,email):
self.name = name
self.number = number
self.email = email
self.storage = {self.name: [self.number, self.email]}
def getStorage(self):
return self.storage
contact = Person('Mike','1-800-foo-spam','email#email.com')
print contact.storage
# or
print contact.getStorage()
But the whole idea of a dictionary is to have a number of keys and corresponding values. In this example, it always will be one only. So, another schema comes to my mind:
class Person():
def __init__(self,name,number,email):
self.name = name
self.number = number
self.email = email
# creating some example contacts
c1 = Person('Mike','1-800-foo-spam','email#email.com')
c2 = Person('Jim','1-700-foo-spam','e111mail#email.com')
c3 = Person('Kim','1-600-foo-spam','e222mail#email.com')
# creating a dictionary to fill it with c1..cn contacts
contacts = {}
# helper function to automate dictionary filling
def contactToDict(list_of_contacts):
for item in list_of_contacts:
contacts[item.name] = (item.number, item.email)
contactToDict([c1, c2, c3])
"""
expected output:
Mike: ('1-800-foo-spam', 'email#email.com')
Jim: ('1-700-foo-spam', 'e111mail#email.com')
Kim: ('1-600-foo-spam', 'e222mail#email.com')
"""
for key, val in contacts.items():
print str(key) + ": " + str(val)
The answer to the title of the question: a value should be a type of object with allows to have a "list" inside (i.e. list, tuple, another dictionary or custom type object having a number of attributes.)
You can pretty easily have a dictionary with tuples as the values.
a = {}
a["bob"] = ("1-800-whatever","bob#gmail.com")
If you wanted to make it a class variable, you'd just need to create an empty dictionary as part of the Person class:
class Person():
storage = {}
Then in __init__ you can store the new person's info in that dictionary:
def __init__(self,name,number,email):
self.name = name
self.number = number
self.email = email
Person.storage[name] = (number, email)
As you can see class attributes are accessed with the classname, but otherwise like any other attribute. You could store them as a tuple or a list if you need to update them. However if you intend to make changes, it might be better to store the actual Person object, to save having to update Person.storage and the actual person at the same time. This is even easier to do:
def __init__(self,name,number,email):
self.name = name
self.number = number
self.email = email
Person.storage[name] = self
self refers to the instance of Person that's being created with __init__. That's Mike in your example. Then you could access their values by attribute:
Person.storage["Mike"].number
Also as Kevin pointed out in a comment you might want to detect if the key already exists to avoid overwriting an old entry (eg. if there's already a Mike in the dictionary):
self.email = email
if name in Person.storage:
# Make unique name
Person.storage[name] = (number, email)