To use datetime objects as the key value for the dictionary

Just wanted to share something interesting I did as a little bonus.

When I was on the .attendance() challenge I decided that I wanted to use datetime objects as the key value for the dictionary and then just assign a true of false value to it. The true or false is also weighted, so I did rand_int = randint(0, 101) and threw it a if rand_int <= 91: false else: true

I’ve always hated just picking a random number from 0 and 1 and using that as true/false, it’s so counter intuitive for humans to work with and leaves you thinking it wasn’t really random. Using a random number from 0 to 100 and deciding based on that really gives you the impression of random. You can even print it out and you know it’s working properly, rather than printing out a 1 or 0, which can take a couple runs to see it’s changing and random

anyways enough talk here’s my code for you to critique

from datetime import date
#imports the date class from the datetime 'package'
import random
#I initially wanted to do from random import random
#but doing so would cause random.randint(a, b) to not work sooo yeah not sure why

class Student:
  def __init__(self, name, year):
    self.name = name
    self.year = year
    self.grades = []
    self.attendance = self.generate_attendance()

#adds a grade to self.grade 
#grade is a class Grade object
  def add_grade(self, grade):
    if type(grade) == Grade:
      self.grades.append(grade)
    return 

# gets the average, nothing but self is needed for this to run
#  returns -1 if there are no grades to average
#I always use -1 as a placeholder value to return when the function just
#doesn't do what you want it to. IIRC this is common practice
  def get_average(self):
    average = 0
    count = 0
    for grade in self.grades:
      average += grade.score
      count += 1
    if count > 0:
      return average / count
    return -1
  
#only meant to be called by self
#wanted to use a static method here but I don't know how, sorry about that
#this generates an attendance dictionairy for the past 6(?) days
  def generate_attendance(self):
    date_temp = date.today()
    dic = {}
#there's no particularly real reason I started at 1 and ended at 7 for the range.
#I was planning on initially using range(1,8) so I could 
#get an index number I could subtract/add from 
#a datetime object, but that's not how datetime objects 
#work and I ended up using a date object instead(maybe with deltatime object?)
#then using the logic below put the date object out of range because
#it subtracted more days in the month than the month had and the date object
#isn't really smart enough to do anything with that besides raise an error
#and I'm not interested enough to make that exception work... yet
    for i in range(1, 7):
      dic[date_temp] = self.rand_true_false()
      date_temp = date_temp.replace(day=(date_temp.day - 1))
    return dic

#another method that deserves to be static, but I don't know how
#Returns true or false. I used 91 as the weight, meaning If I ran this enough, 
#it should average to being true 91% of the time, or somewhere close to that
#I think that's a good percentage to give people for attending class. They're there
#most of the time, but ■■■■ does happen and you can't always be there.
#a lot of depth for no real reason. But This highlights a perfect reason 
#to generate true/false like this as well as what I mentioned above. 
# Ideally I'd set this weight to be an instance variable of the Student class
#but I don't care enough to do that. 
#but if you want to, go ahead! Tips would be to generate the students attendence
#percentage with another weighted random generator that picks something between
# 35 and 100. If below 50% just remove the pointer linking to the Student instance to
# memory! Yeeee haw, for students who don't attend often, are they even a student????
  def rand_true_false(self):
    rand_int = random.randint(0, 101)
    if rand_int <= 91:
      return True
    return False

class Grade:
  minimum_passing = 65
  def __init__(self, score):
    self.score = score
  #Determines whether the grade is passing or not
  #returns either true or false.
  #if score is >= 65 returns true
  #else returns false
  def is_passing(self):
    if self.score >= Grade.minimum_passing:
      return True
    return False


roger = Student("Roger van der Weyden", 10)
sandro = Student("Sandro Botticelli", 12)
pieter = Student("Pieter Bruegel the Elder", 8)






print (pieter.get_average())
pieter.add_grade(Grade(100))
print (pieter.get_average())
pieter.add_grade(Grade(50))
print (pieter.get_average())
print(pieter.attendance)

#prints out
#-1
#100.0
#75.0
#{datetime.date(2020, 5, 7): True, datetime.date(2020, 5, 6): True, datetime.date(2020, 5, 5): True, datetime.date(2020, 5, 4): True, datetime.date(2020, 5, 3): True, datetime.date(2020, 5, 2): True}


The value generated by math.random is 64 bits in a 64 bit system. How can 0 to 100 be more random than 0 to 2 ** 64 - 1?

The multiplier in a random product describes how many intervals, or segments the entire range is divided into.

randint(1, 100) is the same as random() * 100 + 1 (essentially).