I have issue with extending date class in python.
Since date is static class, however, I haven't get it working as it supposed to be. I tried to modify code base on datetime, since this class extend from date. However, failed.
Question is:
How to modify code to make it working like:
ed = ExtendDate(2011,1,1,week=3, quarter=3)
print ed.week # 3
How to deal with __new__, and __init__ in python static class (in theory) ?
How to extend date class (in general) ?
Thanks.
class ExtendDate(date):
"""Extend to have week and quarter property"""
#
# def __init__(self, year, month, day, week=None, quarter=None):
# pass
def __init__(self, year, month, day, week=None, quarter=None):
print 0
super(ExtendDate, self).__init__(year,month,day)
print 1
self._week = week
self._quarter = quarter
#staticmethod
def __new__(cls, year, month, day, week=None, quarter=None):
cls._week = 1
super(ExtendDate, cls).__new__(year, month, day)
def __cmp__(self, other):
if self.cmp_year(other) in [-1,0,1]:
return self.cmp_year(other)
if hasattr(self, 'quarter'):
return self.cmp_quarter(other)
if hasattr(self, 'week'):
return self.cmp_week(other)
# TODO: test - what if it's just a normal date object ?
pass
def cmp_quarter(self, other):
if self.quarter < other.quarter:
return -1
elif self.quarter == other.quarter:
return 0
elif self.quarter > other.quarter:
return 1
def cmp_week(self, other):
if self.week < other.week:
return -1
elif self.week == other.week:
return 0
elif self.week > other.week:
return 1
def cmp_year(self, other):
if self.year < other.year:
return -1
elif self.year == other.year:
return 0
elif self.year > other.year:
return 1
def __repr__(self):
return 'year:' + str(self.year) + ' ' + \
'quarter:' + str(self.quarter) + ' ' + \
'month:' + str(self.month) + ' '+ \
'week:' + str(self.week) + ' '+ \
'day:' + str(self.day) + ' '
week = property(lambda self: 0)
quarter = property(lambda self: 0)
#week.setter
def week(self, value):
self._week = value
#quarter.setter
def quarter(self, value):
self._quarter = value
__new__ isn't supposed to be decorated with #staticmethod (it's a class method implicitly, no decorator should be used). And it's supposed to return the instance created, where your code is modifying cls (which it shouldn't) and not returning the result of the super __new__ call (which it should). Also, if you're providing a __new__ (to make the class logically immutable), you shouldn't provide a __init__.
Really, the code you'd want would be something like:
class ExtendDate(date):
"""Extend to have week and quarter property"""
__slots__ = '_week', '_quarter' # Follow date's lead and limit additional attributes
def __new__(cls, year, month, day, week=None, quarter=None):
self = super(ExtendDate, cls).__new__(cls, year, month, day)
self._week = week
self._quarter = quarter
return self
Presumably, you'd also want functional getters, e.g.
#property
def week(self):
return self._week
# ... etc. ...
As #ShadowRanger answsered, I changed some lines to make it working.
The major change is __new__(cls, year, month, day):
from datetime import date
class ExtendDate(date):
"""Extend to have week and quarter property"""
__slots__ = '_week', '_quarter'
def __new__(cls, year, month, day, week=None, quarter=None):
# self = super(ExtendDate, cls).__new__(year, month, day)
self = date.__new__(cls, year, month, day)
self._week = week
self._quarter = quarter
return self
def __cmp__(self, other):
if self.cmp_year(other) in [-1,0,1]:
return self.cmp_year(other)
if hasattr(self, 'quarter'):
return self.cmp_quarter(other)
if hasattr(self, 'week'):
return self.cmp_week(other)
# TODO: test - what if it's just a normal date object ?
pass
def cmp_quarter(self, other):
if self.quarter < other.quarter:
return -1
elif self.quarter == other.quarter:
return 0
elif self.quarter > other.quarter:
return 1
def cmp_week(self, other):
if self.week < other.week:
return -1
elif self.week == other.week:
return 0
elif self.week > other.week:
return 1
def cmp_year(self, other):
if self.year < other.year:
return -1
elif self.year == other.year:
return 0
elif self.year > other.year:
return 1
def __repr__(self):
return 'year:' + str(self.year) + ' ' + \
'quarter:' + str(self.quarter) + ' ' + \
'month:' + str(self.month) + ' '+ \
'week:' + str(self.week) + ' '+ \
'day:' + str(self.day) + ' '
#property
def week(self):
return self._week
#property
def quarter(self):
return self._quarter
ed = ExtendDate(2011,1,2,3,4)
print type(ed)
print ed._week
Related
Sorry for all of the code, but for this assignment I am working on, it is necessary due to different references.
This chapter we are working with Binary Trees and Binary Search Trees.
I tested the BinaryTree() and BinarySearchTree() classes with no issue.
My problem is this: we are adding records to a binary search tree as seen in the Student class and the main() function to test the class. According to the assignment:
The Student class has an id and name, getters and setters, a str() function so that you can print a student record, and the operations ==, !=, <=, <, >=, > defined. The comparison operators compare student id's which are intended to be unique. Since we can compare student records, we can now put them into a Binary Search Tree.
My question is, how do I add the records a binary tree if all of the initialized variables are completely different than ones in the BinaryTree() class and the BinarySearchTree() class?
Everytime I run the code, I get errors such as:
AttributeError: 'Student' object has no attribute 'insert'
or
isEmpty() = True
None
isEmpty() = False
None
101(Betty Smith)
101(Betty Smith)
Traceback (most recent call last):
File "/Users/phillipward/Desktop/Lab 10/StudentRecordsTest.py", line 50, in <module>
main()
File "/Users/phillipward/Desktop/Lab 10/StudentRecordsTest.py", line 22, in main
BST.insert(Student(42, "Amy Winchester"))
File "/Users/phillipward/Desktop/Lab 10/BinarySearchTree.py", line 13, in insert
self.getleftChild().insert(data)
File "/Users/phillipward/Desktop/Lab 10/BinarySearchTree.py", line 7, in insert
if(self.isEmpty()):
File "/Users/phillipward/Desktop/Lab 10/binaryTree.py", line 33, in isEmpty
if(self is None or self.data is None):
AttributeError: 'Student' object has no attribute 'data'
I'm stuck on how to tell the program that I the student class is a type of BinarySearchTree.
class BinaryTree():
def __init__(self, data = None, leftChild = None, rightChild = None):
self.data = data
self.leftChild = leftChild
self.rightChild = rightChild
def getData(self):
return self.data
def setData(self, x):
self.data = x
return self.data
def getleftChild(self):
return self.leftChild
def setleftChild(self, x):
self.leftChild = x
return self.leftChild
def getrightChild(self):
return self.rightChild
def setrightChild(self, x):
self.rightChild = x
return self.rightChild
def isEmpty(self):
if(self is None or self.data is None):
return True
else:
return False
def __str__ (self):
return "{0}".format(self.data)
def inOrderTraversal(self):
if (self is None):
return "Empty"
else:
result = ""
if(self.getleftChild() is not None): # When we put payload in, we need equality
result += BinaryTree.inOrderTraversal(self.getleftChild()) + " "
result += str(self.getData())
if (self.getrightChild() is not None):
result += " " + BinaryTree.inOrderTraversal(self.getrightChild()) + " "
return result
def preOrderTraversal(self):
if (self.isEmpty()):
return "Empty"
else:
result = ""
result += str(self.getData())
if (self.getleftChild() is not None):
result += " " + BinaryTree.preOrderTraversal(self.getleftChild()) + " "
if (self.getrightChild() is not None):
result += BinaryTree.preOrderTraversal(self.getrightChild())
return result
def postOrderTraversal(self):
if (self.isEmpty()):
return "Empty"
else:
result = ""
if (self.getleftChild() is not None):
result += BinaryTree.postOrderTraversal(self.getleftChild()) + " "
if (self.getrightChild() is not None):
result += BinaryTree.postOrderTraversal(self.getrightChild()) + " "
result += str(self.getData())
return result
def insert(self, data):
if (self.isEmpty()):
self.setData(data)
elif (data < self.getData()):
if (self.getleftChild() is None):
self.setleftChild(BinarySearchTree(data))
else:
self.getleftChild().insert(data)
else: # data >= self.getData()
if (self.getrightChild() is None):
self.setrightChild(BinarySearchTree(data))
else:
self.getrightChild().insert(data)
def retrieve(self, data):
if self.isEmpty():
return None
elif data == self.getData():
return self.getData()
elif data <= self.getData():
if self.getleftChild() is None:
return None
else:
return self.getleftChild().retrieve(data)
else:
if self.getrightChild() is None:
return None
else:
return self.getrightChild().retrieve(data)
from binaryTree import BinaryTree
class BinarySearchTree(BinaryTree):
def insert(self, data):
if(self.isEmpty()):
self.setData(data)
elif(data < self.getData()):
if(self.getleftChild() is None):
self.setleftChild(data)
else:
self.getleftChild().insert(data)
else: #data >= self.getData()
if(self.getrightChild() is None):
self.setrightChild(data)
else:
self.getrightChild().insert(data)
def retrieve(self, data):
if self.isEmpty():
return None
elif data == self.getData():
return self.getData()
elif data <= self.getData():
if self.getleftChild() is None:
return None
else:
return self.getleftChild().retrieve(data)
else:
if self.getrightChild() is None:
return None
else:
return self.getrightChild().retrieve(data)
def minValue(self):
current = self
while current.leftChild is not None:
current = current.leftChild
return current.data
def maxValue(self):
current = self
while current.rightChild is not None:
current = current.rightChild
return current.data
def isBST(self):
current = self
if current == None:
return True
if current.leftChild.data <= current.data and
current.rightChild.data >= current.data:
return True
else:
return False
class Student():
def __init__(self, id = None, name = ""):
self.__id = id
self.__name = name
def getId(self):
return self.__id
def setId(self, id):
self.__id = id
def getName(self):
return self.__name
def setName(self, name):
self.__id = name
def __str__(self):
if (self is None):
return ""
else:
return str(self.__id) + "(" + self.__name + ")"
def __cmp__(self, other):
if (self is None or other is None):
return 0
else:
return self.__id - other.__id
def __eq__(self, other):
return self.__cmp__(other) == 0
def __ne__(self, other):
return self.__cmp__(other) != 0
def __lt__(self, other):
return self.__cmp__(other) < 0
def __le__(self, other):
return self.__cmp__(other) <= 0
def __gt__(self, other):
return self.__cmp__(other) > 0
def __ge__(self, other):
return self.__cmp__(other) >= 0
from BinarySearchTree import BinarySearchTree
from Student import Student
def main():
BST = BinarySearchTree()
print("isEmpty() = " + str(BST.isEmpty()))
print(BST)
BST.setData(Student(101, "Betty Smith"))
print("isEmpty() = " + str(BST.isEmpty()))
print(BinarySearchTree())
BST.insert(Student(50, "John Adams"))
print(BST)
BST.insert(Student(250, "Mike Jones"))
print(BST)
BST.insert(Student(42, "Amy Winchester"))
print(BST)
BST.insert(Student(31, "Jill Ranger"))
print(BST)
BST.insert(Student(315, "Bob Crachet"))
print(BST)
BST.insert(Student(200, "Karen Wilkins"))
print(BST)
print("\n")
print()
print("Inorder traversal: " + str(BST))
print()
print("Preorder traversal: \n" + BST.preOrderTraversal())
print()
print("Postorder traversal: " + BST.postOrderTraversal())
print()
print("minValue: " + str(BST.minValue()))
print("maxValue: " + str(BST.maxValue()))
print()
print("isBST = " + str(BST.isBST()))
for id in [101, 200, 31, 50, 315, 250, 42]:
print(BST.retrieve(Student(id)))
main()
I have the below code base:
from datetime import datetime
class Person:
def __init__(self,day,month,year):
self.day = day
self.mon = month
self.year = year
def __repr__(self):
if self.day < 10:
day = "0" + str(self.day)
else:
day = str(self.day)
if self.mon < 10:
mon = "0" + str(self.mon)
else:
mon = str(self.mon)
display = day + "-" + mon + "-" + str(self.year)
return display
def sortdates(l1):
for dates in l1:
date.finalbirthdate = datetime.strptime(str(print(dates)),"%d-%m-%Y")
print (date.finalbirthdate)
if __name__ == '__main__':
p1 = Person(18,9,1984)
print (p1)
p2 = Person(13,1,1988)
print (p2)
sortdates([p1,p2])
Now the main function of sortdates function is to sort the Person objects as per the dates. For that i somehow need to convert the string representation of the Person object into datetime object.
Also since i have to do that i have to somehow capture the string representation into a variable and pass that to datetime.strptime function.
Can someone please guide me out on how to do this?
Thanks in advance.
The correct way to do this is to define __lt__, __gt__, __eq__ methods for your Person object; this way your Person object becomes "sortable" on its own.
class Person:
def __init__(self,day,month,year):
self.day = day
self.mon = month
self.year = year
def _as_date(self):
return datetime.date(self.year, self.mon, self.day)
def __lt__(self, other):
return self._as_date() < other._as_date()
def __gt__(self, other):
return self._as_date() > other._as_date()
def __eq__(self, other):
return self._as_date() == other._as_date()
def __ne__(self, other):
return ! self.__eq__(other)
def __repr__(self):
return '{}-{}-{}'.format(str(self.day).zfill(2),
str(self.mon).zfill(2),
self.year)
Now, you can just sort your objects directly:
if __name__ == '__main__':
p1 = Person(18,9,1984)
print (p1)
p2 = Person(13,1,1988)
print (p2)
sorted_dates = sorted([p1,p2])
I have a question regarding python '>=' behaviour.
I have an old TimeStamp class, which holds (hour, minute) tuple and offers some methods such as __eq__, __gt__, __lt__.
I am refactoring it to also account for day and second, and to store the data as total seconds. Here I implemented __eq__, __gt__, __lt__ as well.
However, further in code I am using >= operator for this class and while the old class version is working properly, with the new one I am getting
TypeError: unorderable types: TimeStamp() >= TimeStamp() error.
Code is below:
class TimeStamp(tuple): # OLD, WORKING VERSION
"""TimeStamp, hh:mm tuple supporting comparison and addition"""
__slots__ = ()
def __new__(cls, *args):
if len(args) == 1: # tuple entrance
hour, minute = args[0]
elif len(args) == 2: # hour, minute entrance
hour, minute = args[0], args[1]
else:
raise TypeError('wrong input to TimeStamp')
div, minute = divmod(minute, 60)
hour += div
_, hour = divmod(hour, 24)
return tuple.__new__(cls, (hour, minute))
#property
def abs_min(self):
return self.hour * 60 + self.minute
def __gt__(self, rhs):
return self.abs_min > rhs.abs_min
def __lt__(self, rhs):
return self.abs_min < rhs.abs_min
def __eq__(self, rhs):
return self.abs_min == rhs.abs_min
New version:
class TimeStamp:
def __init__(self, *args):
for argument in args:
if not isinstance(argument, int):
raise TypeError("Can only build TimeStamp from ints, not: " + str(argument))
if len(args) == 1: # init by abs
self.abs = args[0] # put the ELEMENT, not the tuple itself
elif len(args) == 2: # init by hour:minute
hour, minute = args
self.abs = hour * 60 * 60 + minute * 60
elif len(args) == 4: #init by day:hour:minute:second
day, hour, minute, second = args
self.abs = day * 24 * 60 * 60 + hour * 60 * 60 + minute * 60 + second
else:
raise TypeError("wrong data for TimeStamp: " + str(args))
def __eq__(self, other):
if isinstance(other, TimeStamp):
return self.abs == other.abs
else:
raise TypeError("wrong argument for comparison: " + str(other))
def __gt__(self, other):
if isinstance(other, TimeStamp):
return self.abs > other.abs
else:
raise TypeError("wrong argument for comparison: " + str(other))
def __lt__(self, other):
if isinstance(other, TimeStamp):
return self.abs < other.abs
else:
raise TypeError("wrong argument for comparison: " + str(other))
Now for the comparison part:
if args[1] >= self.start:
>>TypeError: unorderable types: TimeStamp() >= TimeStamp()
I have found two fixes: first, to replace my comparison line with
if args[1] > self.start or args[1] == self.start:
or an alternative, to add
def __ge__(self, other):
if isinstance(other, TimeStamp):
return self.abs >= other.abs
else:
raise TypeError("wrong argument for comparison: " + str(other))
to my new class. However, the old one did work with neither of those fixes. It looks to me as if Python stopped deducting that ((a>b) or (a==b)) implies (a>=b). But why did it work before? Does it have something to do with me subclassing tuple?
PS. don't be scared by my __init__ code, which I included for completeness. It's supposed to be overload-like, but I might be doing it in a non-pythonic way (still learning)
The old one worked because it inherited from tuple, and tuple provides __ge__. Your new version does not inherit from tuple, so it doesn't have a __ge__ method.
Even in your old version, your __gt__ and __lt__ methods were never being called when using >= (as you can verify by putting print inside those methods). The underlying tuple.__ge__ was being called instead. However, for your case, the effect is the same, so you didn't notice. That is, given that the "minutes" number is always less than 60, comparing (hours, minutes) tuples in the usual way is equivalent to comparing 60*hours + minutes. So I don't think you really need to define the comparison methods at all if you inherit from tuple.
class Course(object):
def __init__(self,cnum,name):
self.name = name
self.cnum = cnum
def __str__(self):
return 'Course:' , self.cnum , self.name
class AssigendCourse(Course):
def __init__(self,Course,dept,year,semester):
self.name = Course.name
self.cnum = Course.cnum
if dept == 'SE' or dept == 'CE' or dept == 'CIE' or dept == 'ME':
self.dept = dept
else:
self.dept = None
if year >= 1 and year <= 4:
self.year = year
else:
self.year = None
if semester >= 1 and semester <= 3:
self.semester = semester
else:
self.semester = None
def __str__(self):
return 'Course: ' , self.name , self.cnum
results in this type of error
TypeError: __str__ returned non-string (type tuple)
I can't figure what type of syntax I need to use for the __str__ func in order to get the print for the object when using:
it = iter(db)
for i in it:
print(i)
Your __str__ methods return tuples:
def __str__(self):
return 'Course:' , self.cnum , self.name
The comma makes it it tuple.
You'll need to join those values; I recommend string formatting:
def __str__(self):
return 'Course: {} {}'.format(self.cnum, self.name)
class fase1():
def __init__ (self, num, date, desc)
self.num = num
self.date = date
self.desc = desc
class fase2(fase1):
def __init__(self, ele):
self.ele = [ele,[]]
def __str__(self):
return self.ele
def addfase2(self, num, date, desc):
newfase = fase1()
self.ele[1].append(newfase)
namefase2 = "FASE"
cload = fase2
cload.ele = namefase2
cload.addfase2(10,"date","Desc")
when print ...
['FASE',[<__main__.fase1 instance at 0x01C2BEB8>]]
can anyone help me please?
you have an array containing your fase1 object, which isn't initialized in your addfase2 method (as you'd probably want)
def addfase2(self, num, date, desc):
newfase = fase1(num, date, desc)
also if you add a __str__ method to fase1, you won't see anymore the object repr
def __str__(self):
return self.desc + ' ' + self.num + ' ' + self.date
or something like that