why does my program execute an extra line("none") when executed? - python-3.x

I recently wrote a program using oop for an online coffee machine:
from menu import Menu from coffee_maker import CoffeeMaker from
money_machine import MoneyMachine
menu = Menu() coffee_maker = CoffeeMaker() money_machine =
MoneyMachine()
is_on = True
while is_on:
choice = input(f"What would you like? {menu.get_items()}")
if choice == "off":
is_on = False
elif choice == "report":
print(coffee_maker.report())
print(money_machine.report())
files:
class CoffeeMaker:
"""Models the machine that makes the coffee"""
def init(self):
self.resources = {
"water": 300,
"milk": 200,
"coffee": 100,
}
def report(self):
"""Prints a report of all resources."""
print(f"Water: {self.resources['water']}ml")
print(f"Milk: {self.resources['milk']}ml")
print(f"Coffee: {self.resources['coffee']}g")
def is_resource_sufficient(self, drink):
"""Returns True when order can be made, False if ingredients are insufficient."""
can_make = True
for item in drink.ingredients:
if drink.ingredients[item] > self.resources[item]:
print(f"Sorry there is not enough {item}.")
can_make = False
return can_make
def make_coffee(self, order):
"""Deducts the required ingredients from the resources."""
for item in order.ingredients:
self.resources[item] -= order.ingredients[item]
print(f"Here is your {order.name} ☕️. Enjoy!")
class MenuItem:
"""Models each Menu Item."""
def init(self, name, water, milk, coffee, cost):
self.name = name
self.cost = cost
self.ingredients = {
"water": water,
"milk": milk,
"coffee": coffee
}
class Menu:
"""Models the Menu with drinks."""
def init(self):
self.menu = [
MenuItem(name="latte", water=200, milk=150, coffee=24, cost=2.5),
MenuItem(name="espresso", water=50, milk=0, coffee=18, cost=1.5),
MenuItem(name="cappuccino", water=250, milk=50, coffee=24, cost=3),
]
def get_items(self):
"""Returns all the names of the available menu items"""
options = ""
for item in self.menu:
options += f"{item.name}/"
return options
def find_drink(self, order_name):
"""Searches the menu for a particular drink by name. Returns that item if it exists, otherwise returns None"""
for item in self.menu:
if item.name == order_name:
return item
print("Sorry that item is not available.")
class MoneyMachine:
CURRENCY = "$"
COIN_VALUES = {
"quarters": 0.25,
"dimes": 0.10,
"nickles": 0.05,
"pennies": 0.01
}
def __init__(self):
self.profit = 0
self.money_received = 0
def report(self):
"""Prints the current profit"""
print(f"Money: {self.CURRENCY}{self.profit}")
def process_coins(self):
"""Returns the total calculated from coins inserted."""
print("Please insert coins.")
for coin in self.COIN_VALUES:
self.money_received += int(input(f"How many {coin}?: ")) * self.COIN_VALUES[coin]
return self.money_received
def make_payment(self, cost):
"""Returns True when payment is accepted, or False if insufficient."""
self.process_coins()
if self.money_received >= cost:
change = round(self.money_received - cost, 2)
print(f"Here is {self.CURRENCY}{change} in change.")
self.profit += cost
self.money_received = 0
return True
else:
print("Sorry that's not enough money. Money refunded.")
self.money_received = 0
return False
but it printed:
What would you like? latte/espresso/cappuccino/report Water: 300ml
Milk: 200ml Coffee: 100g None Money: $0 None What would you like?
latte/espresso/cappuccino/
can you tell me how to remove this "none"?

Related

Missing 1 required positional argument - 'Self'?

I have the following method of a certain class:
def make_payment(self, cost):
and the following at the main file:
print(money_machine.make_payment(drink.cost))
why is it returning this? (I am following a code-along session and everything seems to be fine with his code)
TypeError: MoneyMachine.make_payment() missing 1 required positional argument: 'cost'
MAIN:
from menu import Menu, MenuItem
from coffee_maker import CoffeeMaker
from money_machine import MoneyMachine
"""1print report
2check resources sufficies
process coins
check transaction successful
make coffee
"""
coffee_maker = CoffeeMaker()
menu = Menu()
money_machine = MoneyMachine
is_on = True
while is_on:
print(menu.get_items())
order = input("your order: ")
if order == 'off':
is_on = False
elif order == "report":
coffee_maker.report()
else:
drink = menu.find_drink(order)
if coffee_maker.is_resource_sufficient(drink):
if money_machine.make_payment(drink.cost):
coffee_maker.make_coffee(drink)
MONEY MACHINE:
class MoneyMachine:
CURRENCY = "$"
COIN_VALUES = {
"quarters": 0.25,
"dimes": 0.10,
"nickles": 0.05,
"pennies": 0.01
}
def __init__(self):
self.profit = 0
self.money_received = 0
def report(self):
"""Prints the current profit"""
print(f"Money: {self.CURRENCY}{self.profit}")
def process_coins(self):
"""Returns the total calculated from coins inserted."""
print("Please insert coins.")
for coin in self.COIN_VALUES:
self.money_received += int(input(f"How many {coin}?: ")) * self.COIN_VALUES[coin]
return self.money_received
def make_payment(self, cost):
"""Returns True when payment is accepted, or False if insufficient."""
print(self.money_received)
self.process_coins()
if self.money_received >= cost:
change = round(self.money_received - cost, 2)
print(f"Here is {self.CURRENCY}{change} in change.")
self.profit += cost
self.money_received = 0
return True
else:
print("Sorry that's not enough money. Money refunded.")
self.money_received = 0
return False
Per your comments, the issue is that you are not instantiating your class correctly.
Overall your instantiation code should be more like this, which is the correct way to instantiate a class:
money_machine = MoneyMachine()
then calling methods would insatiate it correctly and you pass self in, so money_machine.make_payment(drink.cost) would then work as expected.
Instantiating a class is essentially calling the class's __init__() method, this is also where you would define any required arguments if needed when creating a copy of the class. For example:
class MoneyMachine():
def __init__(self, currency_type):
# here you must instantiate with currency_type defined
self.currency_type = currency_type
self.profit = 0
self.money_received = 0
usa_money_machine = MoneyMachine(currency_type='USD')

How to use inheritance to level up a character

# Import Modules
from Dice import dice
d10 = dice(10,1) #I use dice, but you could just as easily use random.randint()
d4 = dice(4,1)
d20 = dice(20,1)
# Assign Classes
class Player_Character:
inventory = []
def __init__(self, HP, MaxHP, AC, ToHitAdjustment, Surprise_Adjustment,
Initiative_Adjustment, Exp, \
MaxExp, Gold, Damage):
self.HP = int(HP)
self.MaxHP = int(MaxHP)
self.AC = int(AC)
self.ToHitAdjustment = int(ToHitAdjustment)
self.Surprise_Adjustment = int(Surprise_Adjustment)
self.Initiative_Adjustment = int(Initiative_Adjustment)
self.Exp = int(Exp)
self.MaxExp = int(MaxExp)
self.Gold = int(Gold)
self.Damage = int(Damage)
this next section may be where the error is, although I doubt it because when I run through the code the character is assigned exp and gold and they seem to grow at the correct rate.
def attack(self, goblin, Player_Character):
Player_attack_roll = d20.die_roll() + Player_Character.ToHitAdjustment
if (Player_attack_roll >= goblin.AC):
print('you did', Player_Character.Damage, 'damage')
goblin.HP -= Player_Character.Damage
if (goblin.HP <= 0):
print("congratulations you killed the goblin")
Player_Character.Exp += goblin.ExpReward
if (Player_Character.Exp >= Player_Character.MaxExp):
print("Congratulations you have leveled up")
Player_Character.LevelUp()
print('you have', Player_Character.Exp, 'exp ')
Player_Character.Gold += goblin.Gold
print("you have", Player_Character.Gold, 'gold ')
del goblin
else:
print("You miss ")
def flee(self):
print("you run away ")
quit()
def heal(self, Player_Character):
Player_Character.HP += d10.die_roll()
if Player_Character.HP >= Player_Character.MaxHP:
Player_Character.HP = Player_Character.MaxHP
print("You have reached max HP ")
this may be where the error is, I expect it to assign the variable name 'MrHezy' which was previously assigned to Player_Character to FighterLvl1, but when I run the code it continuously says that I am leveling up, which I am unsure if that means that the character is remaining as Player_Character, or if there is something else wrong
def LevelUp(self):
MrHezy = FighterLvl1(25, 25, 15, 10, 2, 2, 25, 75, 20, d10.die_roll()+5)
This next section has code is where my question of inheritance comes into play. Even though FighterLvl1 has inherited from (Player_Character) my IDE says things like "unresolved attribute reference 'Exp' for FighterLvl1" Also I am unsure if adding the 'attack' method under FighterLvl1 does anything; I expect it to overwrite the 'attack' method from Player_Character
class FighterLvl1(Player_Character):
def attack(self, goblin, Player_Character):
Player_attack_roll = d20.die_roll() + Player_Character.ToHitAdjustment
if (Player_attack_roll >= goblin.AC):
print('you did', Player_Character.Damage, 'damage')
goblin.HP -= Player_Character.Damage
if (goblin.HP <= 0):
print("congratulations you killed the goblin")
FighterLvl1.Exp += goblin.ExpReward
if (FighterLvl1.Exp >= FighterLvl1.MaxExp):
print("Congratulations you have leveled up")
FighterLvl1.LevelUp()
print('you have', FighterLvl1.Exp, 'exp ')
FighterLvl1.Gold += goblin.Gold
print("you have", FighterLvl1.Gold, 'gold ')
del goblin
def LevelUp(self):
MrHezy = FighterLvl2(Player_Character)
class FighterLvl2(Player_Character):
def LevelUp(self):
MrHezy = FighterLvl3(Player_Character)
class FighterLvl3(Player_Character):
def MaxLevel(self):
print("Congratulations you are level 3, this is the highest programmed level in the game
")
class goblin:
def __init__(self, HP, MaxHP, AC, ToHitAdjustment, Surprise_Adjustment,
Initiative_Adjustment, \
ExpReward, Gold, Damage):
self.HP = int(HP)
self.MaxHP = int(MaxHP)
self.AC = int(AC)
self.ToHitAdjustment = int(ToHitAdjustment)
self.Surprise_Adjustment = int(Surprise_Adjustment)
self.Initiative_Adjustment = int(Initiative_Adjustment)
self.ExpReward = int(ExpReward)
self.Gold = int(Gold)
self.Damage = int(Damage)
def attack(self, Player_Character, goblin):
if (goblin.HP <= 0):
print("the goblin is inert")
else:
goblin_attack_roll = d20.die_roll() + goblin.ToHitAdjustment
if (goblin_attack_roll >= Player_Character.AC):
goblin_damage = d4.die_roll()
print("you take", goblin_damage, 'damage')
Player_Character.HP -= goblin_damage
if (Player_Character.HP <= 0):
print("oh dear you have died")
del Player_Character
quit()
else:
print("the goblin misses ")
MrHezy = Player_Character(20, 20, 10, 5, 0, 0, 0, 25, 0, d10.die_roll())
def spawn_goblin(goblin):
G1 = goblin(5, 10, 8, 2, 0, 0, 25, 5, d4.die_roll())
return G1
goblin1 = spawn_goblin(goblin)
def battle(goblin1):
# user input
player_initiative_adjustment = MrHezy.Initiative_Adjustment
monster_initiative_adjustment = goblin1.Initiative_Adjustment
#define while loop for the battle
while True:
if (goblin1.HP <= 0):
print('oh dear looks like we need a new goblin')
break
#use random.randint(a,b) to generate player and monster base initiative
player_base_initiative = d10.die_roll()
monster_base_initiative = d10.die_roll()
#subtract the adjustment to get player and monster initiative
player_initiative = player_base_initiative - player_initiative_adjustment
monster_initiative = monster_base_initiative - monster_initiative_adjustment
#compare the initiatives and display the results
if (player_initiative < monster_initiative):
attack_flee_heal = input("congratulations you go first. Would you like to attack,
flee, or heal?")
if attack_flee_heal == 'attack':
MrHezy.attack(goblin1, MrHezy)
elif attack_flee_heal == 'heal':
MrHezy.heal(MrHezy)
print("the goblin attacks")
goblin1.attack(MrHezy)
elif attack_flee_heal == 'flee':
MrHezy.flee()
else:
print("uhoh, the monsters go first, they attack!")
goblin1.attack(MrHezy, goblin1)
attack_flee_heal = input("Would you like to attack, flee, or heal? ")
if attack_flee_heal == 'attack':
MrHezy.attack(goblin1, MrHezy)
elif attack_flee_heal == 'heal':
MrHezy.heal(MrHezy)
print("the goblin attacks")
goblin1.attack(MrHezy, goblin1)
elif attack_flee_heal == 'flee':
MrHezy.flee()
#main game loop
while True:
spawn_goblin(goblin)
battle(goblin1)
print("spawn another goblin")
goblin1.HP = 0
goblin1.HP += d10.die_roll()
This code runs perfectly well, please enter it into your IDE.
The problem that I have is a logic error, when a goblin is killed instead of leveling up the character first to level 1 then level 2 then level 3 instead the character levels up to level 1 over and over and over.
I agree with Danny Varod, in that there are very many improvements that need to be made, and I definitely recommend following his advice.
However if you are simply looking to make what you have work you need to specify in your level up methods that you are referencing the global MrHezy variable.
eg:
def LevelUp(self):
global MrHezy
MrHezy = FighterLvl2(Player_Character)
The level up replaces a variable in the object, what you should do, if you want to use a class per level (not necessarily a good idea) is:
Create a Character class.
In Character class define an implementation field.
Initialize implementation field e.g. implementation = SomeSpeciesLevel1().
To "level-up": implementation = implementation.level_up()
This way you have a constant wrapper that doesn't change which wraps the level-changing implementation.
A better design would be to have one class with functionality based on level-dependant formulas.
class CharImpl:
#abstractmethod
def can_level_up() -> bool:
return NotImplemented
#abstractmethod
def next_level() -> CharImpl:
return NotImplemented
pass
class Character:
def __init__(initial_impl: CharImpl=None):
self.impl = initial_impl.copy() if initial_impl else HumanLevel1()
pass
def level_up():
if self.impl.can_level_up():
self.impl = self.impl.next_level()
pass
pass
class Human(CharImpl):
pass
class HumanLevel1(Human):
def __init__(src: Human):
# TODO: copy relevant fields from src
pass
def can_level_up() -> bool:
return True
def next_level() -> CharImpl:
return HumanLevel2(self)
pass
class HumanLevel2(Human):
def __init__(src: Human):
# TODO: copy relevant fields
pass
def can_level_up() -> bool:
return False
def next_level() -> CharImpl:
return self
pass

Splunk Python SDK API job.results limited to 50k results. Trying to set an offset to pull multiple chunks of 50k but don't know how to get it to work

I have a job who's job['resultCount'] is 367k, but no matter what I do, I can't seem to pull more than the first 50,000 chunk.
I read this chunk of code off of an answer here for someone who had a similar end goal and setup: https://answers.splunk.com/answers/114045/python-sdk-results-resultsreader-extremely-slow.html
rs = job.results(count=maxRecords, offset=self._offset)
results.ResultsReader(io.BufferedReader(ResponseReaderWrapper(rs)))
I wrote the below code around that and I've fiddled around a bit with it, but I can't get offset=self._offset to do anything and I have no idea what it's supposed to be doing.
class SplunkConnector(object):
def __init__(self, username, password, customerGuid):
self.username = username
self.password = password
self.customerGuid = customerGuid
flag = True
while flag:
try:
self.service = client.connect(host=*****, port=8089, username=self.username, password=self.password, scheme='https')
flag = False
except binding.HTTPError as e:
json_log.debug(str(e))
def search(self, query_dict):
query = query_dict['search']
label = query_dict['label']
search_headers = query_dict['headers']
customer = query_dict['customer']
customerGuid = query_dict['customerGuid']
try:
earliest_time = query_dict['earliest_time']
latest_time = query_dict['latest_time']
except KeyError:
earliest_time = '-1d#d'
latest_time = '#d'
json_log.debug('Starting %s customerGuid=%s' % (label, self.customerGuid))
kwargs_normalsearch = {'exec_mode': 'normal', 'earliest_time': earliest_time, 'latest_time': latest_time, 'output_mode': 'csv'}
job = self.service.jobs.create(query + ' | fillnull value="---"', **kwargs_normalsearch)
while True:
try:
while not job.is_ready():
pass
stats = {"isDone": job["isDone"],
"label": label,
"customer": customer,
"customerGuid": customerGuid,
"doneProgress": float(job["doneProgress"]) * 100,
"scanCount": int(job["scanCount"]),
"eventCount": int(job["eventCount"]),
"resultCount": int(job["resultCount"])}
json_log.debug(stats)
if stats["isDone"] == "1":
json_log.debug("\n\nDone!\n\n")
break
sleep(2)
stats = {"isDone": job["isDone"],
"label": label,
"customer": customer,
"customerGuid": customerGuid,
"doneProgress": float(job["doneProgress"]) * 100}
json_log.debug(stats)
if stats["isDone"] == "1":
json_log.debug('Search %s finished for customerGuid=%s'
% (label, customerGuid))
break
sleep(2)
except binding.HTTPError as e:
json_log.debug(str(e))
pass
except AttributeError:
stats = {"isDone": job["isDone"],
"label": label,
"customer": customer,
"customerGuid": customerGuid,
"doneProgress": float(job["doneProgress"]) * 100}
json_log.debug(stats)
if stats["isDone"] == "1":
json_log.debug('Search %s finished for customerGuid=%s'
% (label, customerGuid))
break
sleep(2)
# Get the results and display them
result_count = job['resultCount']
rs = job.results(count=0)
rr = results.ResultsReader(io.BufferedReader(rs))
results_list = []
for result in rr:
if isinstance(result, results.Message):
# Diagnostic messages may be returned in the results
json_log.debug('%s: %s label=%s customerGuid=%s'
% (result.type, result.message, label, customerGuid))
elif isinstance(result, dict):
# Normal events are returned as dicts
keys, values = [], []
for header in search_headers:
if header not in result.keys():
print(header)
result[header] = ''
for key, value in result.items():
if key in search_headers:
keys.append(str(key))
values.append(str(value))
if not results_list == []:
results_list.append(values)
else:
results_list.append(keys)
results_list.append(values)
output = io.BytesIO()
writer = csv.writer(output, delimiter=',')
writer.writerows(results_list)
output_string = output.getvalue()
assert rr.is_preview is False
job.cancel()
return [label, output_string.replace('\r\n', '\n').replace('---', '')]
def searches(self, query_list):
print(query_list)
if type(query_list) == dict:
query_list = [value for value in query_list.values()]
with closing(ThreadPool(processes=len(query_list))) as pool:
results = pool.map(self.search, query_list)
pool.terminate()
print(results)
search_results = {item[0]: item[1] for item in results}
print(search_results)
return search_results
I was able to get this working successfully. My code below should demonstrate how this is accomplished.
import io
import csv
from time import sleep
import splunklib.results as results
import splunklib.client as client
import splunklib.binding as binding
from multiprocessing.pool import ThreadPool
from contextlib import closing
class SplunkConnector(object):
def __init__(self, username, password, customerGuid):
self.username = username
self.password = password
self.customerGuid = customerGuid
flag = True
while flag:
try:
self.service = client.connect(host=*****, port=8089, username=self.username, password=self.password, scheme='https')
flag = False
except binding.HTTPError as e:
json_log.debug(str(e))
def search(self, query_dict):
query = query_dict['search']
label = query_dict['label']
search_headers = query_dict['headers']
customer = query_dict['customer']
customerGuid = query_dict['customerGuid']
try:
earliest_time = query_dict['earliest_time']
latest_time = query_dict['latest_time']
except KeyError:
earliest_time = '-1d#d'
latest_time = '#d'
kwargs_normalsearch = {'exec_mode': 'normal', 'earliest_time': earliest_time, 'latest_time': latest_time, 'output_mode': 'csv'}
flag = True
while flag:
try:
job = self.service.jobs.create(query + ' | fillnull value="---"', **kwargs_normalsearch)
flag = False
except binding.HTTPError as e:
pass
pass
while True:
try:
while not job.is_ready():
pass
stats = {"isDone": job["isDone"],
"label": label,
"customer": customer,
"customerGuid": customerGuid,
"doneProgress": float(job["doneProgress"]) * 100,
"scanCount": int(job["scanCount"]),
"eventCount": int(job["eventCount"]),
"resultCount": int(job["resultCount"])}
if stats["isDone"] == "1":
break
sleep(2)
stats = {"isDone": job["isDone"],
"label": label,
"customer": customer,
"customerGuid": customerGuid,
"doneProgress": float(job["doneProgress"]) * 100}
if stats["isDone"] == "1":
break
sleep(2)
except binding.HTTPError as e:
pass
except AttributeError:
stats = {"isDone": job["isDone"],
"label": label,
"customer": customer,
"customerGuid": customerGuid,
"doneProgress": float(job["doneProgress"]) * 100}
if stats["isDone"] == "1":
break
sleep(2)
result_count = job['resultCount']
offset = 0
count = 50000
results_list = self.results_getter(job, label, customerGuid, search_headers, True, count, offset, result_count)
while len(results_list) < int(result_count) + 1:
offset += count
placeholder = self.results_getter(job, label, customerGuid, search_headers, False, count, offset, result_count)
results_list.extend(placeholder)
output = io.BytesIO()
writer = csv.writer(output, delimiter=',')
writer.writerows(results_list)
output_string = output.getvalue()
job.cancel()
return [label, output_string.replace('\r\n', '\n').replace('---', '')]
def results_getter(self, job, label, customerGuid, search_headers, first, count, offset, result_count):
# Get the results and display them
kwargs_paginate = {"count": count,
"offset": offset}
blocksearch_results = job.results(**kwargs_paginate)
results_list = []
reader = results.ResultsReader(blocksearch_results)
for result in reader:
if isinstance(result, results.Message):
# Diagnostic messages may be returned in the results
elif isinstance(result, dict):
# Normal events are returned as dicts
keys, values = [], []
for header in search_headers:
if header not in result.keys():
result[header] = ''
for key, value in result.items():
if key in search_headers:
keys.append(str(key))
values.append(str(value))
if not results_list == []:
results_list.append(values)
elif first:
results_list.append(keys)
results_list.append(values)
else:
results_list.append(values)
assert not reader.is_preview
return results_list
def searches(self, query_list):
if type(query_list) == dict:
query_list = [value for value in query_list.values()]
with closing(ThreadPool(processes=len(query_list))) as pool:
results = pool.map(self.search, query_list)
pool.terminate()
search_results = {item[0]: item[1] for item in results}
return search_results

How to search in an id tree in the python program

I'm a student and working on a small assignment where I need to collect inputs from the student on factors like kind of books they like to issue from the library. I've been provided id_tree class which I need to search using. As you can see I'm getting inputs from the console and I like to use that as the search criteria and get the recommendation from the id tree.
Just for testing purpose, I'm using out.py, but that needs to be replaced with id_tree search logic for which I'm struggling.
# k-Nearest Neighbors and Identification Trees
#api.py
import os
from copy import deepcopy
from functools import reduce
################################################################################
############################# IDENTIFICATION TREES #############################
################################################################################
class Classifier :
def __init__(self, name, classify_fn) :
self.name = str(name)
self._classify_fn = classify_fn
def classify(self, point):
try:
return self._classify_fn(point)
except KeyError as key:
raise ClassifierError("point has no attribute " + str(key) + ": " + str(point))
def copy(self):
return deepcopy(self)
def __eq__(self, other):
try:
return (self.name == other.name
and self._classify_fn.__code__.co_code == other._classify_fn.__code__.co_code)
except:
return False
def __str__(self):
return "Classifier<" + str(self.name) + ">"
__repr__ = __str__
## HELPER FUNCTIONS FOR CREATING CLASSIFIERS
def maybe_number(x) :
try :
return float(x)
except (ValueError, TypeError) :
return x
def feature_test(key) :
return Classifier(key, lambda pt : maybe_number(pt[key]))
def threshold_test(feature, threshold) :
return Classifier(feature + " > " + str(threshold),
lambda pt: "Yes" if (maybe_number(pt.get(feature)) > threshold) else "No")
## CUSTOM ERROR CLASSES
class NoGoodClassifiersError(ValueError):
def __init__(self, value=""):
self.value = value
def __str__(self):
return repr(self.value)
class ClassifierError(RuntimeError):
def __init__(self, value=""):
self.value = value
def __str__(self):
return repr(self.value)
class IdentificationTreeNode:
def __init__(self, target_classifier, parent_branch_name=None):
self.target_classifier = target_classifier
self._parent_branch_name = parent_branch_name
self._classification = None #value, if leaf node
self._classifier = None #Classifier, if tree continues
self._children = {} #dict mapping feature to node, if tree continues
self._data = [] #only used temporarily for printing with data
def get_parent_branch_name(self):
return self._parent_branch_name if self._parent_branch_name else "(Root node: no parent branch)"
def is_leaf(self):
return not self._classifier
def set_node_classification(self, classification):
self._classification = classification
if self._classifier:
print("Warning: Setting the classification", classification, "converts this node from a subtree to a leaf, overwriting its previous classifier:", self._classifier)
self._classifier = None
self._children = {}
return self
def get_node_classification(self):
return self._classification
def set_classifier_and_expand(self, classifier, features):
if classifier is None:
raise TypeError("Cannot set classifier to None")
if not isinstance_Classifier(classifier):
raise TypeError("classifier must be Classifier-type object: " + str(classifier))
self._classifier = classifier
try:
self._children = {feature:IdentificationTreeNode(self.target_classifier, parent_branch_name=str(feature))
for feature in features}
except TypeError:
raise TypeError("Expected list of feature names, got: " + str(features))
if len(self._children) == 1:
print("Warning: The classifier", classifier.name, "has only one relevant feature, which means it's not a useful test!")
if self._classification:
print("Warning: Setting the classifier", classifier.name, "converts this node from a leaf to a subtree, overwriting its previous classification:", self._classification)
self._classification = None
return self
def get_classifier(self):
return self._classifier
def apply_classifier(self, point):
if self._classifier is None:
raise ClassifierError("Cannot apply classifier at leaf node")
return self._children[self._classifier.classify(point)]
def get_branches(self):
return self._children
def copy(self):
return deepcopy(self)
def print_with_data(self, data):
tree = self.copy()
tree._assign_data(data)
print(tree.__str__(with_data=True))
def _assign_data(self, data):
if not self._classifier:
self._data = deepcopy(data)
return self
try:
pairs = list(self._soc(data, self._classifier).items())
except KeyError: #one of the points is missing a feature
raise ClassifierError("One or more points cannot be classified by " + str(self._classifier))
for (feature, branch_data) in pairs:
if feature in self._children:
self._children[feature]._assign_data(branch_data)
else: #feature branch doesn't exist
self._data.extend(branch_data)
return self
_ssc=lambda self,c,d:self.set_classifier_and_expand(c,self._soc(d,c))
_soc=lambda self,d,c:reduce(lambda b,p:b.__setitem__(c.classify(p),b.get(c.classify(p),[])+[p]) or b,d,{})
def __eq__(self, other):
try:
return (self.target_classifier == other.target_classifier
and self._parent_branch_name == other._parent_branch_name
and self._classification == other._classification
and self._classifier == other._classifier
and self._children == other._children
and self._data == other._data)
except:
return False
def __str__(self, indent=0, with_data=False):
newline = os.linesep
ret = ''
if indent == 0:
ret += (newline + "IdentificationTreeNode classifying by "
+ self.target_classifier.name + ":" + newline)
ret += " "*indent + (self._parent_branch_name + ": " if self._parent_branch_name else '')
if self._classifier:
ret += self._classifier.name
if with_data and self._data:
ret += self._render_points()
for (feature, node) in sorted(self._children.items()):
ret += newline + node.__str__(indent+1, with_data)
else: #leaf
ret += str(self._classification)
if with_data and self._data:
ret += self._render_points()
return ret
def _render_points(self):
ret = ' ('
first_point = True
for point in self._data:
if first_point:
first_point = False
else:
ret += ', '
ret += str(point.get("name","datapoint")) + ": "
try:
ret += str(self.target_classifier.classify(point))
except ClassifierError:
ret += '(unknown)'
ret += ')'
return ret
################################################################################
############################# k-NEAREST NEIGHBORS ##############################
################################################################################
class Point(object):
"""A Point has a name and a list or tuple of coordinates, and optionally a
classification, and/or alpha value."""
def __init__(self, coords, classification=None, name=None):
self.name = name
self.coords = coords
self.classification = classification
def copy(self):
return deepcopy(self)
def __getitem__(self, i): # make Point iterable
return self.coords[i]
def __eq__(self, other):
try:
return (self.coords == other.coords
and self.classification == other.classification)
except:
return False
def __str__(self):
ret = "Point(" + str(self.coords)
if self.classification:
ret += ", " + str(self.classification)
if self.name:
ret += ", name=" + str(self.name)
ret += ")"
return ret
__repr__ = __str__
################################################################################
############################### OTHER FUNCTIONS ################################
################################################################################
def is_class_instance(obj, class_name):
return hasattr(obj, '__class__') and obj.__class__.__name__ == class_name
def isinstance_Classifier(obj):
return is_class_instance(obj, 'Classifier')
def isinstance_IdentificationTreeNode(obj):
return is_class_instance(obj, 'IdentificationTreeNode')
def isinstance_Point(obj):
return is_class_instance(obj, 'Point')
#id_tree
from api import *
import math
log2 = lambda x: math.log(x, 2)
INF = float('inf')
import pandas as pd
def id_tree_classify_point(point, id_tree):
if id_tree.is_leaf():
return id_tree.get_node_classification()
else:
new_tree = id_tree.apply_classifier(point)
get_point = id_tree_classify_point(point, new_tree)
return get_point
def split_on_classifier(data, classifier):
"""Given a set of data (as a list of points) and a Classifier object, uses
the classifier to partition the data. Returns a dict mapping each feature
values to a list of points that have that value."""
#Dictionary which will contain the data after classification.
class_dict = {}
#Iterating through all the points in data
for i in range(len(data)):
get_value = classifier.classify(data[i])
if get_value not in class_dict:
class_dict[get_value] = [data[i]]
else:
class_dict[get_value].append(data[i])
return class_dict
def branch_disorder(data, target_classifier):
"""Given a list of points representing a single branch and a Classifier
for determining the true classification of each point, computes and returns
the disorder of the branch."""
#Getting data after classification based on the target_classifier
class_dict = split_on_classifier(data, target_classifier)
if (len(class_dict) == 1):
#Homogenous condition
return 0
else:
disorder = 0
for i in class_dict:
get_len = len(class_dict[i])
p_term = get_len/ float(len(data))
disorder += (-1) * p_term * log2(p_term)
return disorder
def average_test_disorder(data, test_classifier, target_classifier):
"""Given a list of points, a feature-test Classifier, and a Classifier
for determining the true classification of each point, computes and returns
the disorder of the feature-test stump."""
average_disorder = 0.0
#Getting all the branches after applying test_classifer
get_branches = split_on_classifier(data, test_classifier)
#Iterating through the branches
for i in get_branches:
disorder = branch_disorder(get_branches[i], target_classifier)
average_disorder += disorder * (len(get_branches[i])/ float(len(data)))
return average_disorder
#### CONSTRUCTING AN ID TREE
def find_best_classifier(data, possible_classifiers, target_classifier):
"""Given a list of points, a list of possible Classifiers to use as tests,
and a Classifier for determining the true classification of each point,
finds and returns the classifier with the lowest disorder. Breaks ties by
preferring classifiers that appear earlier in the list. If the best
classifier has only one branch, raises NoGoodClassifiersError."""
#Base values to start with
best_classifier = average_test_disorder(data, possible_classifiers[0], target_classifier)
store_classifier = possible_classifiers[0]
#Iterating over the list of possible classifiers
for i in range(len(possible_classifiers)):
avg_disorder = average_test_disorder(data, possible_classifiers[i], target_classifier)
if avg_disorder < best_classifier:
best_classifier = avg_disorder
store_classifier = possible_classifiers[i]
get_branches = split_on_classifier(data, store_classifier)
if len(get_branches)==1:
#Only 1 branch present
raise NoGoodClassifiersError
else:
return store_classifier
def construct_greedy_id_tree(data, possible_classifiers, target_classifier, id_tree_node=None):
"""Given a list of points, a list of possible Classifiers to use as tests,
a Classifier for determining the true classification of each point, and
optionally a partially completed ID tree, returns a completed ID tree by
adding classifiers and classifications until either perfect classification
has been achieved, or there are no good classifiers left."""
#print data
#print "possible", possible_classifiers
#print "target", target_classifier
if id_tree_node == None:
#Creating a new tree
id_tree_node = IdentificationTreeNode(target_classifier)
if branch_disorder(data, target_classifier) == 0:
id_tree_node.set_node_classification(target_classifier.classify(data[0]))
else:
try:
#Getting the best classifier from the options available
best_classifier = find_best_classifier(data, possible_classifiers, target_classifier)
get_branches = split_on_classifier(data, best_classifier)
id_tree_node = id_tree_node.set_classifier_and_expand(best_classifier, get_branches)
#possible_classifiers.remove(best_classifier)
branches = id_tree_node.get_branches()
for i in branches:
construct_greedy_id_tree(get_branches[i], possible_classifiers, target_classifier, branches[i])
except NoGoodClassifiersError:
pass
return id_tree_node
possible_classifiers = [feature_test('age'),
feature_test('gender'),
feature_test('duration'),
feature_test('Mood')
]
df1 = pd.read_csv("data_form.csv")
#df1 = df1.drop("age", axis=1)
print(df1)
a = []
with open("data_form.csv") as myfile:
firstline = True
for line in myfile:
if firstline:
mykeys = "".join(line.split()).split(',')
firstline = False
else:
values = "".join(line.split()).split(',')
a.append({mykeys[n]:values[n] for n in range(0,len(mykeys))})
keys = a[0].keys()
print(keys)
with open('data_clean.csv', 'w') as output_file:
dict_writer = csv.DictWriter(output_file, keys)
dict_writer.writeheader()
dict_writer.writerows(a)
print(a)
tar = feature_test('genre')
print(construct_greedy_id_tree(a, possible_classifiers, tar))
#book_suggestion
import random
#from out import *
def genre(Mood, age, gender, duration):
print("Hi")
res_0= input("What's your name?")
res_1 = input("How are you, "+str(res_0)+"?")
if res_1 in ("good","fine","ok","nice"):
print ("Oh nice")
else:
print("Oh! It's alright")
Mood = input("What is your current mood?")
age = input("What is your age range : 10-12, 12-15,13-14,15-18,18+?")
gender = input("What is your gender?")
duration = input("How long do you want to read : 1week, 2weeks, 3weeks, 3+weeks, 2hours")
def get_book(genre):
suggestions = []
genre_to_book = {"Fantasy":["Just me and my babysitter - Mercer Mayer","Just Grandpa and me - Mercer Mayer","Just me and my babysitter - Mercer Mayer",
"The new Potty - Mercer Mayer","I was so mad - Mercer Mayer","Just me and my puppy" ,"Just a mess" ,"Me too"
,"The new Baby","Just shopping with mom"],
"Encyclopedias":["Brain Power - Paul Mcevoy", "My best books of snakes Gunzi Chrisitian","MY best books of MOON Grahame,Ian",
"The book of Planets Twist,Clint", "Do stars have points? Melvin", "Young discover series:cells Discovery Channel"]
,
"Action" : ["The Kane Chronicle:The Throne of Fire s Book 2 Riordan,Rick",
"Zane : ninja of ice Farshtey, Greg",
"Escape from Sentai Mountain Farshtey, Greg",
"Percy jackson Rick Riordan",
"The Kane Chronicle:The Throne of Fire s Book 2 Rick Riordan"],
"Comic" : ["Double Dork Diaries Russell Rachel Renée",
"Dork Dairies Russell Rachel Renee",
"Dork Dairies Russell Rachel Renée"],
"Mystery" : ["Sparkling Cyanide Christie Agatha",
"Poirot's Early Cases: Agatha Christie",
"The Name of this Book is Secret Bosch,Pseudonyuous"],
"Biographies" :["All by myself Mercer Mayer", "D Days prett bryan",
"Snake Bite Lane Andrew"] }
if (genre == "Fantasy"):
suggestions = [random.sample(genre_to_book["Fantasy"], 3)]
elif (genre == "Action"):
suggestions = [random.sample(genre_to_book["Action"], 3)]
elif (genre == "Comic"):
suggestions = [random.sample(genre_to_book["Comic"], 3)]
elif (genre == "Mystery"):
suggestions = [random.sample(genre_to_book["Mystery"], 3)]
elif (genre == "Encyclopedias"):
suggestions = random.sample(genre_to_book["Encyclopedias"], 3)
elif (genre == "Biographies"):
suggestions = random.sample(genre_to_book["Biographies"], 3)
return suggestions
print(get_book(genre(Mood, age, gender, duration)))
I want the program to not depend on out.py and and run on the information of id tree
The current implementation of the suggestions works by asking the user for a genre, then looking up a list of book titles in a dictionary using that genre as the key, then randomly selecting one of the titles and printing it. The current implementation also (presumably) constructs a IdentificationTreeNode containing recommendations, but then does nothing with it except printing it to the standard output.
The next step would be to not discard the tree, but save it in a variable and use in the recommendation process. Since the class structure is not given, it is not clear how this could be done, but it seems a reasonable assumption that it is possible to provide a keyword (the genre) and receive some collection of objects where each one contains data on a recommendation.
If constructing the IdentificationTreeNode is too costly to run on each recommendation request, it is possible to split the construction into its own script file and using python's pickle package to save the object in a file that can then be unpickled more quickly in the script performing the recommendations.

How to get a certain value from an array of objects in python

ok so this is my program so far to operate as an ordering system of a cafe with multiple items. My goal is to calculate the price of an order, store that order to keep count of which coffee was ordered and how many of that coffee was ordered. Right now I am stuck on calculating the order total for an order. The main problem im stuck on is getting the coffee price of a coffee based on what the user wants, say if i want x coffee, i need to get the price of that coffee. I've stored instances of coffee in an array and right now I am not sure of how to get the price of a coffee to be used in the calculation of the total price
class Coffee(object):
def __init__ (self, coffee_type, price):
self.coffee_type = coffee_type
self.price = price
class Order(object):
def __init__(self, coffee_type, coffee_amount):
self.coffee_type = coffee_type
self.coffee_amount = coffee_amount
if name =="main":
coffee_available=[Coffee("1 : Flat White", 3.50),
Coffee("2 : Long Black", 3.50),
Coffee("3 : Cappuccino", 4.00),
Coffee("4 : Espresso", 3.25),
Coffee("5 : Latte", 3.50)]
ordering = 'Y'
total_cost = 0
while ordering == 'Y':
print("Coffee Type\t\tPrice")
print("-----------\t\t-----")
for coffee in coffee_available:
print("{}\t- - -\t$ {}".format(coffee.coffee_type,coffee.price))
print()
order_coffee = int(input("What is the number of the coffee you want? "))
order_amount = input("How many would you like to order? ")
new_order = None
if order_coffee >= 1 and order_coffee <=5:
coffee_choice = coffee_available[coffee.price]
new_order = Order(coffee_choice, order_amount)
total_cost = new_order.coffee_type * order_amount
else:
print ("Please enter a valid number")
dine_in = input('You like to dine in? (Y/N)')
dine_in = dine_in.upper()
if dine_in == 'Y' or 'YES':
total_cost = total_cost + (total_cost * 0.1)
print (total_cost)
Ordering = 'N'
elif dine_in == 'N' or 'No':
total_cost = total_cost
else:
print("Please enter a valid input")
continue
It's better to split the id of the coffee from the name:
class Coffee(object):
def __init__ (self, coffee_id, coffee_type, price):
self.coffee_id = coffee_id
self.coffee_type = coffee_type
self.price = price
Then when you create object use:
Coffee(1, "Flat White", 3.5)
And when you want the price use:
def get_price(coffee_available, coffee_id):
for coffee in coffee_available:
if coffee.coffee_id == coffee_id:
return coffee.price
return None

Resources