Access data in blockchain object for wallet balances - python

While trying to execute the code below to access the wallet
balance in the blockchain, I'm getting the error:
TypeError: slice indices must be integers or None or have an index method
This is the code I use:
class Blockchain:
def __init__(self):
self.chain = [] #stores the blockchain
self.transactions = ["Plain as vanilla"]
self.create_block(proof = 1, previous_hash="0") #helps with block creation
self.nodes = set()
def create_block(self, proof, previous_hash):
""" Used to make a block """
block = {
'index': len(self.chain) + 1,
'timestamp': str(datetime.datetime.utcnow()),
'proof': proof,
'previous_hash': previous_hash,
'data': self.transactions
}
self.transactions = []
self.chain.append(block)
return block
self.balance = 0
chain = Blockchain.chain[]
i = 0
for x in range(len(chain)):
if chain[i:"data":"reciver"] or chain[i:"data":"sender"] == publickey:
io = 0
for chain[i:"data":"reciver"] in chain[i:"data"]: #loop for iterating through the dictionary
amount = int(chain[io:"data":"amount"])
self.balance = self.balance + amount
io = io + 1
if chain[i:"data":"sender"] == publickey:
amount = int(chain[i:"data":"amount"])
self.balance = self.balance - amount
i = i + 1
if chain[-1] == 0:
self.balance = 0
return self.balance
the code is supposed to iterate through a dictionary inside a dictionary inside a list to find the balance of a wallet inside a blockchain, edit: I added the method of how a block is structured on the chain

Can you provide the error message?
I see that you instantiate "chain" as an empty list and then loops over it.
But assuming that you're only showing that the variable exists, to access a dictionary, nested inside a second dictionary within this list you should use:
chain[i]["data"]["receiver"]

Related

Python terminal is printing the location of the object in a class not the data stored in the object

I have a class I've imported into a Python file. But my code is printing the location of the object not the data stored in the object. It is giving me this output, '<Chapter_10_Program_Exercise_5.RetailItem object at 0x10e281520>' which I think is the location but how can I change that? Here's the code and a picture of the python terminal output.
class RetailItem:
# __init__ method initializes the attributes.
def __init__(self, description, units, price):
self.__item_description = description
self.__units_in_inventory = units
self.__price = price
# The set_item_description method gets the item type.
def set_item_description(self, description):
self.__item_description = description
# The set_units_in_inventory method gets number of items available.
def set_units_in_inventory(self, units):
self.__units_in_inventory = units
# The set_price method gets the cost of item.
def set_price(self, price):
self.__price = price
# The get_item_description method returns the item type.
def get_item_description(self):
return self.__item_description
# The get_units_in_inventory returns the number of items available.
def get_units_in_inventory(self):
return self.__units_in_inventory
# The get_price method returns the cost of item.
def get_price(self):
return self.__price
from Chapter_10_Program_Exercise_5 import RetailItem
class CashRegister:
# The __init__ method initializes the attributes.
def __init__(self):
self.__items = []
def clear(self):
self.__items = []
def purchase_item(self, retail_item):
self.__items.append(retail_item)
print('The item was added to the cash register.')
def get_total(self):
total_cost = 0.0
# for loop
for item in self.__items:
total_cost = total_cost +item.get_price()
return total_cost
def display_items(self):
print('The items in the cash register are:')
for item in self.__items:
print(item)
PANTS = 1
SHIRT = 2
DRESS = 3
SOCKS = 4
SWEATER = 5
def main():
pants = RetailItem('Pants', 10, 19.99)
shirt = RetailItem('Shirt', 15, 12.50)
dress = RetailItem('Dress', 3, 79.00)
socks = RetailItem('Socks', 50, 1.00)
sweater = RetailItem('Sweater', 5, 49.99)
sale_items = {PANTS:pants, SHIRT:shirt, DRESS:dress, SOCKS:socks, SWEATER:sweater}
register = CashRegister()
checkout = 'N'
while checkout =='N':
# Call the get_user_option and it is assigned to the user_option
user_option = get_user_option()
# Sale_items of argument user_option is assigned to the item
item= sale_items[user_option]
# If condition to check the items in the items_in_inventory
if item.get_units_in_inventory()== 0:
print('The item is out of stock.')
else:
register.purchase_item(item)
# New item is updated and it is assigned to the new_item
new_item = RetailItem(item.get_item_description(),
item.get_units_in_inventory()-1,
item.get_price())
# Item is updated according to the user selected option
sale_items[user_option] = new_item
# The user input is assigned to the attribute checkout
checkout = input('Are you ready to check out (Y/N)? ')
print()
print('Your purchase total is:',\
format(register.get_total(),'.2f'))
print()
register.display_items()
register.clear()
# Define the get_user_option() method to print the menu items
def get_user_option():
print('Menu')
print('-------------------')
print('1. Pants')
print('2. Shirt')
print('3. Dress')
print('4. Socks')
print('5. Sweater')
print()
option = int(input('Enter the menu number of the item you would like to purchase: '))
print()
while option > SWEATER or option < PANTS:
option = int(input('Please enter a valid item number: '))
return option
main()
Python Terminal Output
This is how python manages the printing of objects. If you want to print attributes you need to tell python which representation you want for your object.
You can do that by implementing these methods in the object class:
class RetailItem:
.
.
.
def __repr__(self):
return "RetailItem()"
def __str__(self):
return "" + self.__item_description + str(self.__units_in_inventory) + str(self.__price)
Note that the two methods will be automatically called in different situations:
>>> ri = RetailItem()
>>> ri
RetailItem()
>>> print(ri)
description 2.0 13.99
Since all variables within RetailItem are private, you'd
need to use the getter method (get_*()) to grab the info.
So to apply that to your display_items() method:
def display_items(self):
print('The items in the cash register are:')
for item in self.__items:
print("Description: %s, Units in Inventory: %d, Price: %0.2f" %
(item.get_item_description(),
item.get_units_in_inventory(),
item.get_price())

Create x instances of a class and store the order they were created in

I want to create x amount of instances of a class and store (inside the instance) the order they were created in. Is there a way that I can do that?
MaxAnts = 100
class Ant:
def __init__(self,id):
self.id = id
# then I will use the id to do math
i = 0
if i <= MaxAnts:
i += 1
i = Ant(i)
But for some reason this doesn't work.
The class itself can give ids to its instances.
class Ant:
counter = 0 # counter is a class variable
def __init__(self):
cls = type(self)
self.id = cls.counter # id is an instance variable
cls.counter += 1
# example:
a = Ant()
b = Ant()
c = Ant()
print(a.id, b.id, c.id) # prints: 0 1 2
Using list comprehension as described in the comments is not a bad way to go but I'll put this here just to give you a introduction to lists.
MaxAnts = 100
class Ant:
def __init__(self,id):
self.id = id
#then i will use the id to do math
ants = [] # or ants = list() , same thing
i = 0
if i <= MaxAnts:
i += 1
ants.append(Ant(i))
The only wierd thing here is that because lists are 0 indexed ants[0].id will be 1 and ant[99].id will be 100. If you do ants = [Ant(i) for i in range(MaxAnts)] you will have your index lined up with your ids, ants[7].id = 7. But you could get the same effect by putting i+=1 after ants.append(Ant(i)) instead of the line before.
To create x amount of instances of some class you would need to use some form of iteration and append them to a collection that you would be able to access.
MaxAnts = 100
class Ant:
def __init__(self,id):
self.id = id
#then i will use the id to do math
ants = [] # A list to store your ants
for i in range(MaxAnts): # Iterating i from 0 to MaxAnts - 1
ant = Ant(i) # Creating your new ant with the i as a parameter
ants.append(ant) # Adding your new ant to the ants list
Since by default 'range' gives you a range from 0 to argument - 1, in case you want to start your order from 1, you should start your iteration from 1, and end it on MaxAnts:
for i in range(1, MaxAnts + 1): # Iterating i from 1 to MaxAnts
More on lists: https://docs.python.org/3/tutorial/datastructures.html
More on range: https://docs.python.org/3/library/functions.html#func-range

How to calculate total of defs using django?

I would like to calculate the total balance of clients, i did this class with def but it calculate for one client only, i would like to create one def to calculate the total of client_balance of all clients i have.
class ClientsBalance(models.Model):
client = models.OneToOneField(Client, on_delete=models.CASCADE,related_name='Client')
def sales(self):
invoices = self.client.invoice_set.all()
sales_amount = 0
for invoice in invoices:
sales_amount += invoice.amountDuettc()
return sales_amount
def clientpayment(self):
invoices = self.client.invoice_set.all()
clientpayment = 0
for invoice in invoices:
clientpayment += invoice.amount_paid()
return clientpayment
def client_balance(self):
items = self.client.invoice_set.all()
invoice_balance = 0
for item in items:
invoice_balance = (self.sales()) - (self.clientpayment()) + (item.client.initialBalance)
return invoice_balance
First of all, you have a typo in your function which makes each iteration overwriting invoice_balance.
This will return the sum as desired:
def client_balance(self):
items = self.client.invoice_set.all()
invoice_balance = 0
for item in items:
invoice_balance += (self.sales()) - (self.clientpayment()) + (item.client.initialBalance)
return invoice_balance
Second of all you could merge your logic if required since you always use the same queryset like so e.g.:
def calculations(self):
queryset = self.client.invoice_set.all()
sales_amount = 0
clientpayment = 0
invoice_balance = 0
for client in queryset:
sales_amount += client.amountDuettc()
clientpayment += client.amount_paid()
invoice_balance += client.amountDuettc() - client.clientpayment() + client.client.initialBalance()
context = {
'sales_amount': sales_amount,
'clientpayment': clientpayment,
'invoice_balance': invoice_balance
}
return context
You current logic is returning balance of last client. In every iteration, invoice_balance override the previous value.
Try this.
Initialize an empty dictionary and append dictionary in every iteration:
def client_balance(self):
items = self.client.invoice_set.all()
invoice_dict = {}
for item in items:
invoice_balance = (self.sales()) - (self.clientpayment()) + (item.client.initialBalance)
invoice_dict[client_pk] = invoice_balance # client_pk is something unique for client.
return invoice_dict
This will return an dictionary with invoice balance of every client.

Program does not recognize value as a valid variable value?

The program I am trying to create involves writing a method called monster_fight(monster1,monster2) to have the two monsters "Fight". However I am having one issue retrieving the damage value stored in each of the monster object dictionaries named 'self.attacks'.
I am trying to retrieve a value from dictionary 'monster1.attacks' to reduce the hp of the monster2 object. However with the current code I have in place, the program does not recognize the value of the keys when I call the dictionary. Can anybody show what I am doing wrong?
Thanks!
class Monster():
def __init__(self, name, max_hp = 20, hp=20):
self.name = name
self.type = type
self.current_hp = max_hp
self.attacks = {'wait': 0}
self.possible_attacks = {'sneak_attack': 1,
'slash': 2,
'ice_storm': 3,
'fire_storm': 3,
'whirlwind': 3,
'earthquake': 2,
'double_hit': 4,
'wait': 0}
self.exp = 0
def add_attack(self, attack_name):
if attack_name in self.possible_attacks:
self.attacks[attack_name] = self.possible_attacks.get(attack_name)
return True
else:
return False
if attack_name in self.attacks:
return False
def remove_attack(self, attack_name):
if attack_name in self.attacks:
self.attacks.pop(attack_name)
if len(self.attacks) == 0:
self.attacks['wait'] = 0
return True
else:
return False
def win_fight(self):
self.exp += 5
self.current_hp = self.max_hp
def lose_fight(self):
self.exp += 1
self.current_hp = self.max_hp
def monster_fight(monster1,monster2):
round1 = 0
moves1 = []
moves2 = []
list1 = []
list2 = []
for i in monster1.attacks:
values = ''
values = monster1.attacks.get(i)
list1.append(values)
for i in range(0,len(monster2.attacks)):
values = monster2.attacks.get(i)
list2.append(values)
while monster1.current_hp > 0 or monster2.current_hp > 0:
round1 += 1
monster1_attack = int(monster1.attacks[list1[(round1-1)%len(list1)]])
monster2.current_hp -= monster1_attack
moves1.append(list1[(round1-1)%len(list1)])
monster2_attack= monster2.attacks[list2[(round1-1)%len(list2)]]
monster1.current_hp -= monster2_attack
moves2.append(list2[(round1-1)%len(list2)])
if monster1.current_hp <= 0:
monster1.lose_fight()
monster2.win_fight()
return round1, monster2.name, moves2
elif monster1.current_hp <= 0:
monster2.lose_fight()
monster1.win_fight()
return round1,monster1.name, moves1
else:
return -1,"None","None"
a = Monster("a", 9)
b = Monster("b", 9)
a.add_attack("ice_storm")
b.add_attack("ice_storm")
b.remove_attack("wait")
a.remove_attack("wait")
round1, winner, moves = monster_fight(a, b)
print(round1)
print(winner.name)
print(moves)
monster1_attack = int(monster1.attacks[list1[(round1-1)%len(list1)]])
KeyError: 3
Well, let's see. You're calling:
monster1_attack = int(monster1.attacks[list1[(round1-1)%len(list1)]])
monster1 is a Monster object, created from:
a = Monster("a", 9)
a.add_attack("ice_storm")
a.remove_attack("wait")
So monster1.attacks looks like:
{
'ice_storm': 3,
}
You're trying to access that dictionary using key dervied from list1[(round1-1)%len(list1)].
list1 is set here:
for i in monster1.attacks:
values = ''
values = monster1.attacks.get(i)
list1.append(values)
After the above code runs, list1 is a list that looks like:
[3]
(Because you ask for monster1.attacks.get(i), which will return the value associated with key i.)
So when you ask for list1[(round1-1)%len(list1)], you get the value 3, which means you're asking for monster1.attacks[3].
There is no key named 3 in monster1.attacks. As we saw earlier, the only key is ice_storm which has the value 3. It looks like you're trying to figure out the damage that monster1's attack will do. That is actually what you have in list1, so in theory you could just write:
monster1_attack = list1[(round1-1)%len(list1)]
monster2.current_hp -= monster1_attack
I think your logic here may be a bit convoluted. You should probably think carefully about exactly what you're trying to accomplish and try to simplify your code with that goal in mind. Using the Python debugger to see the value of your variables prior to the error -- or using print statements to accomplish the same thing -- can help diagnose this sort of problem.

Unable to figure out which data structure to use for efficiency

I come from C background currently learning Python. My task is to create a general tree. The input to the program is in two passes. In the first pass I must collect the identity, name, role and dept of a person. In the second pass I get to know the parent of a node, the manager. So I must store the values transiently. In C I would typically use an array of structs or a linked list depending on the availability of the size information. But I am lost here in Python, not even sure if what I am doing is okay let alone efficient.
Thanks in advance,
Preeti.
if __name__ == "__main__":
# Have successfully created the tree and added nodes by hardcoding values as shown below in commented code
# create_tree = Tree()
# Tree.add_node(42, "Stephen", "Time Cone Radiation", "Black Hole")
# But unable to figure out how to store transient info and use it later to create the tree.
num = 8
list = []
backup_num = num
while num:
id, name, role, dept = raw_input().split()
num -= 1
list.append((id, name, role, dept))
while backup_num:
id, parent = raw_input().split()
backup_num -= 1
#For an id in the list above locate it, and call add_node.
# But not sure how and what is an efficient way.
This will give you a fare idea. Hope this helps.
class Tree():
def __init__(self):
self.length = 0
self.data = {}
def add_node(self, nodeid, name, role, dept):
obj = {}
obj["child"] = {"left": None, "right": None}
obj["parent_id"] = None
obj["name"] = name
obj["role"] = role
obj["dept"] = dept
self.data[nodeid] = obj
self.length += 1
return True
# which_one : Left or Right
def update_child_id(self, which_one, nodeid_parent, nodeid_child):
self.data[nodeid_parent]["child"][which_one] = nodeid_child
return True
def update_parent(self, nodeid, parent_id):
self.data[nodeid]["parent_id"] = parent_id
return True
def display_node(self, nodeid):
obj = self.data[nodeid]
print("Node:", nodeid)
print("Parent:", obj["parent_id"], ", Name:", obj["name"], ", Role: ", obj["role"], ", Dept: ", obj["dept"])
def display_child(self, nodeid):
print(self.data[nodeid]["child"].items())
# Main
test = Tree()
# Get the identity and then add here
node_id, name, role, dept = [42, "Stephen", "Time Cone Radiation", "Black Hole"]
test.add_node(node_id, name, role, dept)
# Get the parent id and add here
parent_id, parent = [6, "James"]
test.update_parent(node_id, parent_id)
test.display_node(42)
test.display_child(42)

Categories

Resources