Unit test initializes class without calling parameters, how do I get the parameters into the class? - python-3.x

So I'm working with Linked Lists in python, and the UnitTest our professor gave us calls C = Course(), but asserts the values after. This is what they use to grade, but I can't find a way to call the class then wait for the variables, and apply them to the class without parameters so it doesn't crash. Thoughts? Am I missing something obvious?
Tried to only include the relevant code. If people need full code for clarification or just for kicks/giggles let me know.
import courselist
import course
def load_data(data):
with open(data) as f:
for line in f:
dline = line.strip().split(",")
C = course.Course(dline[0],dline[1],dline[2],dline[3])
course_list = courselist.CourseList()
course_list.insert(C)
return course_list
def main():
data = "data.txt"
full_list = load_data(data)
print(full_list.__str__())
main()
class Course:
def __init__(self, c_num, c_name, c_hour, c_grade):
self.c_num = c_num
self.c_name = c_name
self.c_hour = c_hour
self.c_grade = c_grade
self.next = None
class TestEmptyCourse(unittest.TestCase):
def test_course_creation(self):
# make sure that an empty course is correct
c = Course()
self.assertEqual(c.name(), "")
self.assertEqual(c.number(), 0)
self.assertEqual(c.credit_hr(), 0.0)
self.assertEqual(c.grade(), 0.0)
self.assertEqual(c.next, None)

I was missing something obvious... Hangs head in shame For those interested here's how to fix it. It's always when you ask for help that you get it just in time to look like an idiot haha. Thanks to those to checked it out. If someone has an alternate solution I'll be sure to upvote you
class Course:
def __init__(self, num=0, cname="", c_hr=0.0, cgrade=0.0, next=None):
self.num = num
self.cname = cname
self.c_hr = c_hr
self.cgrade = cgrade
self.next = None
def number(self):
return int(self.num)
def name(self):
return str(self.cname)
def credit_hr(self):
return self.c_hr
def grade(self):
return self.cgrade
def __str__(self):
return f"cs{self.num} {self.cname} Grade:{self.cgrade} Credit Hours: {self.c_hr}"

Related

Nested function in Python class

i have a little "basic understanding" Python problem.
So let me explain my problem.
At first a very simple code snippet.
class Revert:
__sentence = ""
def __init__(self, sentence: str):
self.__sentence = sentence
def get_sentence(self):
return self.__sentence
def revert_sentence(self):
return self.__sentence[::-1]
if __name__ == '__main__':
print(Revert("Stackoverflow").get_sentence())
print(Revert("Stackoverflow").revert_sentence())
So this show normal function calling of python functions.
But how can i transform this code so i can call the revert function like this:
print(Revert("Stackoverflow").get_sentence().revert_sentence())
Maybe I'm miss the forest through the trees. But I didn't get it how to do this.
I already tried to solve the problem with innermethods but this didn't work for me
...
def get_sentence(self):
def revert_sentence():
self.revert_sentence()
return self.__sentence
...
Many thanks in advance
Implement __str__ to return the actual string. Then in the existing methods, return the object. This way you can chain. But when print is applied to it, that __str__ method will kick in:
class Revert:
__sentence = ""
def __init__(self, sentence: str):
self.__sentence = sentence
def get_sentence(self):
return self
def revert_sentence(self):
return Revert(self.__sentence[::-1])
# Some more such methods ...
def upper(self):
return Revert(self.__sentence.upper())
def first(self, count):
return Revert(self.__sentence[:count])
def dotted(self):
return Revert(".".join(self.__sentence))
# For getting a string
def __str__(self):
return self.__sentence
print(Revert("Stackoverflow").get_sentence().revert_sentence())
print(Revert("Stackoverflow")
.revert_sentence()
.first(8)
.upper()
.revert_sentence()
.first(4)
.dotted()) # "O.V.E.R"
Note that now the .get_sentence() method is not really doing much, and you can always strip it from a chain.
Here You go:
class Revert:
__sentence = ""
def __init__(self, sentence: str):
self.__sentence = sentence
def get_sentence(self):
return self.__sentence
def revert_sentence(self):
# It's important to know that you are making changes in the same instance of the object
self.__sentence = self.__sentence[::-1]
return self
def pseudo_revert(self):
# Return a new object with reverted string, but this instance still has original string intact.
return Revert(self.__sentence[::-1])
if __name__ == '__main__':
r1 = Revert("Stackoverflow")
r2 = Revert("Stackoverflow")
print(r1.get_sentence()) # Stackoverflow
print(r1.revert_sentence().get_sentence()) # wolfrevokcatS
print(r1.get_sentence()) # wolfrevokcatS
print(r2.get_sentence()) # Stackoverflow
print(r2.pseudo_revert().get_sentence()) # wolfrevokcatS
print(r2.get_sentence()) # Stackoverflow
Hope this helps you understand the object, instance of an object, and method of object distinctly.

Error when I call a method within a python class

When I run the code below, I get a NameError that bbo is not defined.
from typing import Tuple
import requests
import os
class Level:
__slots__ = ['price', 'amount']
def __init__(self, price: float, amount: float):
self.price = price
self.amount = amount
def initialize(trading_pair: str):
pass
def bbo(trading_pair: str) -> Tuple:
endpt = "https://api.binance.com"
api = "/api/v3/depth"
response = requests.get(endpt + api + trading_pair)
bids_str, asks_str = response.json()["bids"], response.json()["asks"]
bids = [[float(x) for x in row] for row in bids_str]
asks = [[float(x) for x in row] for row in asks_str]
return (Level(max(bids)[0],max(bids)[1]), Level(min(asks)[0],min(asks)[1]))
def main(trading_pair: str):
while True:
time.sleep(5)
bb, ba = bbo(trading_pair)
print(f"Best Bid: {bb.amount}#{bb.price} Best Ask: {ba.amount}#{ba.price}")
if __name__=='__main__':
trading_pair = os.getenv("TRADING_PAIR", "BTCUSDT")
initialize(trading_pair)
main(trading_pair)
When I added self to main()
def main(self, trading_pair: str):
while True:
time.sleep(1)
bb, ba = self.bbo(trading_pair)
print(f"Best Bid: {bb.amount}#{bb.price} Best Ask: {ba.amount}#{ba.price}")
I got a TypeError saying main() missing 1 required positional argument: 'trading_pair'. How do I fix this?
There are a couple of issues that you're having, even if you've included
the self parameter in your methods.
Firstly, your __main__ call:
trading_pair = os.getenv("TRADING_PAIR", "BTCUSDT")
initialize(trading_pair)
main(trading_pair)
This isn't going to work since initialize is supposed to be a method within the Level class. So you will get an undeclared variable in initialize. But since it doesn't do anything right now, I'm only guessing you're going to use it to do some initializing. Will get to this later.
The main method bbo seems to be the (for lack of a better word) actual initializer, so I'll concentrate on that.
Here's my take on your code:
from typing import Tuple
import requests
import os
import time
class Level:
__slots__ = ['price', 'amount']
def __init__(self, price: float, amount: float):
self.price = price
self.amount = amount
def initialize(self, trading_pair: str):
pass
#staticmethod
def bbo(trading_pair: str) -> Tuple:
endpt = "https://api.binance.com"
api = "/api/v3/depth"
response = requests.get(endpt + api + trading_pair)
bids_str, asks_str = response.json()["bids"], response.json()["asks"]
bids = [[float(x) for x in row] for row in bids_str]
asks = [[float(x) for x in row] for row in asks_str]
return (Level(max(bids)[0],max(bids)[1]),
Level(min(asks)[0],min(asks)[1]))
def main(trading_pair: str):
while True:
time.sleep(5)
bb, ba = Level.bbo(trading_pair)
print(f"Best Bid: {bb.amount}#{bb.price} Best Ask: {ba.amount}#{ba.price}")
if __name__=='__main__':
trading_pair = os.getenv("TRADING_PAIR", "BTCUSDT")
main(trading_pair)
Your initialize method does nothing but if it's just a
place holder for future use, I'll just keep it at that. However,
you need to bear in mind that if you do need to use it,
you will need to place it where you've already instantiated
the Level class. Something along the lines of (but
not exactly, since I don't know what the initialize
will do):
#staticmethod
def bbo(self, trading_pair: str) -> Tuple:
endpt = "https://api.binance.com"
api = "/api/v3/depth"
response = requests.get(endpt + api + trading_pair)
bids_str, asks_str = response.json()["bids"], response.json()["asks"]
bids = [[float(x) for x in row] for row in bids_str]
asks = [[float(x) for x in row] for row in asks_str]
bid_level = Level(max(bids)[0],max(bids)[1])
ask_level = Level(min(asks)[0],min(asks)[1])
bid_level.initialize(trading_pair)
ask_level.initialize(trading_pair)
return (bid_level, ask_level)
That said, you'll also need to include error checking
just in case the response.json() ends up being invalid,
or the response being invalid. (again, just a suggestion).
I've tested the code, but I'm getting a 404 error, so I"m
not sure if the url is correct or I'm missing some
credentials.

Calling classmethod multiple times in python

I am trying to create a classmethod which can be called again and again, however it only works once and stops. Here is the code:
class NewBytes(bytes):
def __init__(self, var):
self.var= var
#classmethod
def rip(cls):
return cls(var[2:])
a = b"12asd5789"
x = NewBytes(a)
print(x, x.rip(), x.rip().rip(), x.rip().rip().rip())
Here is what I got from this:
b'12asd5789' b'asd5789' b'asd5789' b'asd5789'
However, what I want to have is:
b'12asd5789' b'asd5789' b'd5789' b'789'
Thanks in advance.
Probably you don't actually want a class method, since you need access to instance state here.
class NewBytes(bytes):
def __init__(self, x):
self.x = x
def rip(self):
return type(self)(self.x[2:])
My previous answer of using self.x doesnt make sense since this is a class method (too quick to answer). I think this is a case of the XY problem, see the below example of how to use a class method.
class Test(object):
x = "hey there whats up this is a long string"
#classmethod
def TestFunction(cls):
cls.x = cls.x[3:]
print(cls.x)
print(Test().x)
Test().TestFunction()
Test().TestFunction()
Test().TestFunction()
Test().TestFunction()
Test().TestFunction()

Why are my class functions executed when importing the class?

it's probably a very basic question but I was unable to find an answer that I could thoroughly understand.
In my main program main_program.py, I'm importing a class that itself imports another class:
in main_program.py:
from createTest import *
in createTest.py:
print("TEST")
from recordRecallQused import *
print("TEST")
now in recordRecallQused:
class recordRecallQused:
def __init__(self, path):
self.path = path
try:
with open(self.path, 'r',newline = '') as question_used:
question_used.closed
except IOError:
#if file doesnt exist
print("the file doesn't exist")
with open(self.path, 'w',newline = '') as question_used:
question_used.closed
def recallQused(self):
list_Qused = []
print("I'm being executed")
with open(self.path, 'r',newline = '') as question_used:
questionused = csv.reader(question_used)
for item in questionused:
if len(item)>0:
list_Qused.append(item[0])
question_used.closed
return list_Qused
What I obtain in the kernel:
>TEST
>I'm being executed
>TEST
so functions inside the class are executed even though they are not called, but I have read that it's "normal", "def" are no statements but "live" things.
Still, I have tried something much more simple:
in main_program_TEST.py
from class1 import *
a = class1()
in class1.py:
print("t")
from class2 import *
print("t")
class class1:
def __init__(self):
pass
def message(self):
print("prout")
in class2.py:
class class2:
def __init__(self):
pass
def message(self):
print("prout2")
When executing main_program_TEST.py the kernel displays
>t
>t
so this time the functions in class2.py have not been executed, otherwise the kernel would show instead:
>t
>prout2
>t
I really wonder why.
Stephen Rauch you are right, part of my code in recordRecallQused.py was calling the function.
"""#load all list
print("loading questions info")
# questions info: answers, category
list_AllQ = []
with open('questionsInfoTo130.csv', newline = '') as csvfile:
questionsInfo = csv.reader(csvfile)
# loop over the questions information rows
for (i,row) in enumerate(questionsInfo):
if(i!=0):
list_AllQ.append(row)
csvfile.close()
path = 'question_used.csv'"""
list_AllQ = [[0,1,2,1,"que"],[0,1,2,2,"que"],[0,1,2,3,"que"],[0,1,2,4,"que"],[0,1,2,55,"que"],[0,1,2,6,"que"],[0,1,2,7,"que"],[0,1,2,8,"que"],[0,1,2,9,"que"]]
a = recordRecallQused('question_used.csv')
list_Qused = a.recallQused()
list_avQ = a.createListavQ(list_Qused, list_AllQ)
list_Qtest = a.createListQtest(list_avQ)
a.recordQused(list_Qtest)

Return a value of class rather than the class itself Python when called

As I am playing around with classes in Python, I thought the following might be useful. Given:
class NewClass:
def __init__self():
self.value = 1
new = NewClass()
Is there a way that by calling new, it would return the new.value of 1, rather than the class itself
<__main__.NewClass object at 0x7faa096d38d0>?
I assume it might not be possible and people are against it, but I figured I'd ask anyway.
class NewClass():
def __init__(self):
pass
def Ret(self):
self.value = 1
return self.value
new = NewClass().Ret()
print(new)

Resources