How to obtain a value from inside a loop - python

I will be implementing multiprocessing so that the loops are occurring at the same time, but how can I make it so at the end of each iteration, I can obtain the value of westernEurope.cases and easternEurope.cases so that I can add them together
westernEurope = Region("Western Europe", 1000, 0, 0, 8, 4, 4, 0)
while westernEurope.deaths < westernEurope.population:
westernEurope.infection()
if westernEurope.cases > westernEurope.population:
westernEurope.cases = westernEurope.population
print("Infections:", westernEurope.cases)
westernEurope.death()
if westernEurope.deaths > westernEurope.population:
westernEurope.deaths = westernEurope.population
print("Deaths:", westernEurope.deaths)
#where i want to return the value of westernEurope.cases
time.sleep(0.1)
easternEurope = Region("Eastern Europe", 1000, 0, 0, 8, 4, 4, 0)
while easternEurope.deaths < easternEurope.population:
easternEurope.infection()
if easternEurope.cases > easternEurope.population:
easternEurope.cases = easternEurope.population
print("Infections:", easternEurope.cases)
easternEurope.death()
if easternEurope.deaths > easternEurope.population:
easternEurope.deaths = easternEurope.population
print("Deaths:", easternEurope.deaths)
# where i want to return the value of easternEurope.cases
time.sleep(0.1)
print(easternEurope.cases + westernEurope.cases)

IMHO there is no need for multiprocessing. With a generator, your problem can be solved in an even more elgant way.
# where i want to return the value of easternEurope.cases
yield region.cases
Full code:
def desease(region: Region):
while region.deaths < region.population:
region.infection()
if region.cases > region.population:
region.cases = region.population
print("Infections:", region.cases)
region.death()
if region.deaths > region.population:
region.deaths = region.population
print("Deaths:", region.deaths)
# where i want to return the value of easternEurope.cases
yield region.cases
time.sleep(0.1)
easternEurope = Region("Eastern Europe", 1000, 0, 0, 8, 4, 4, 0)
westernEurope = Region("Western Europe", 2000, 0, 0, 8, 4, 4, 0)
eastDesease = desease(easternEurope)
westDesease = desease(westernEurope)
for eastCases, westCases in zip(eastDesease, westDesease):
print(eastCases, westCases)

Related

Retrieve specific fields of a namedtuple instance from a nested list in Python

I am starting a project for school, a basic text-adventure game, where the player navigates through several rooms, each with a set of items, and adds an item to their inventory by spending a turn.
Since each item is unique to a room and each item is also unique in its stat benefits, I have done the following to implement these:
Item = namedtuple('Item', ['name', 'atk', 'defense', 'agi', 'hp'])
#Sport Store Items
bat = Item('Baseball Bat', 3, 1, 0, 0)
shoes = Item('Running Shoes', 0, 1, 3, 0)
dryeggs = Item('Freeze Dried Eggs', 0, 0, 1, 2)
#Clothes Store Items
belt = Item('Studded Belt', 1, 1, 0, 0)
candy = Item('Japanese Candy', 0, 0, 1, 1)
jacket = Item('Leather Jacket', 0, 3, 0, 1)
#Toy Store Items:
cars = Item('Toy Car Pack', 1, 1, 0, 0)
crayons = Item('Crayons', 0, 0, 1, 0)
toygun = Item('Toy Gun', 2, 1, 0, 0)
#Candle Store Items:
jar = Item('Candle Jar', 2, 0, 0, 0)
matches = Item('Matches', 1, 0, 1, 0)
wax = Item('Wax', 0, 2, 1, 0)
#Music Store Items:
disc = Item('Vinyl Disc', 2, 0, 1, 0)
guitar = Item('Electric Guitar', 3, 0, 0, 0)
symbol = Item('Symbol', 1, 2, 0, 0)
all_items = [
[bat, shoes, dryeggs, '1'],
[belt, candy, jacket, '2'],
[cars, crayons, toygun, '3'],
[jar, matches, wax, '4'],
[disc, guitar, symbol, '5']
]
My issue is here, in my get_items function:
def get_items(id):
for i in all_items:
if i[3] == id:
items = i
items = list(items[0:4])
return items
else:
continue
I'm trying to get the list of items based on the matching ID parameter. There is a function in another file that takes the player's current position and sends it to other functions as the map_id. I've successfully made it so the name of the store changes based on this position, but I cannot figure out how to handle these sub-lists to return a specific sub-list based on the id.
For example, in the sport_store code, I'm trying to return the results like so:
def sport_store():
room_id = '1'
item_select = items.get_items(room_id)
#FIXME: import items.py later with this function in it.
if item_select != []:
if entering == True:
print('You enter the Sporting Goods Store.')
print('There aren\'t many supplies left. What will you pick?')
else:
print('There aren\'t many supplies left. What will you pick?')
print(item_select)
However, no matter what things I change in get_items' loop to get it to work, I always return the original empty list of item_selection. I am trying to select the matching sub-list from the all_items global with the get_items function and then use that sub-list to make a new list that gets sent to item_selection showing the items for that store, and then format the namedtuples in it to show just the names value. Is this possible or do I need to convert the data to a dictionary?
you can use a dictionary for all items:
all_items = {
'1':[bat, shoes, dryeggs],
'2':[belt, candy, jacket],
'3':[cars, crayons, toygun],
'4':[jar, matches, wax],
'5':[disc, guitar, symbol]
}
then, instead of calling items.getItems(room_id), you could just do all_items[room_id]. Hope this helps!

How to use if statements to return DataFrame items to Excel

My apologies if this is extremely basic. I've been trying to teach myself to code through quarantine, so I'm quite new. My goal is to create an if statement that returns each ticker and its corresponding position into certain columns in Excel based on the group the ticker belongs to.
The tickers and positions are contained in a DataFrame I've converted to two lists, I also have converted it to a dictionary. Nothing seems to work to solve the whole problem. My dictionary uses Tickers as keys and Positions as values. My lists contain all Tickers and all Positions. Pasting what is returned from print(dict) below:
{'Position': {'AKERBP': 0, 'APA': -189, 'AR': 0, 'ASCRES': 100, 'CENREP': 0, 'CHK': 0, 'CITHOL': 230, 'CLR': 900, 'CNX': 702, 'CPE': 230, 'CRK': -8, 'CRROCK': -497, 'CVECN': 139, 'DOUBEA': 265, 'ENDENR': 504, 'EQT': 482, 'FANG': 0, 'GPOR': 0, 'GRTWST': 0, 'HILCRP': -843, 'INDNAT': 120, 'JAG': 0, 'LPI': 304, 'MEGCN': 500, 'MSSCRK': 0, 'MTDR': 237, 'MUR': 0, 'NOG': 0, 'OAS': 0, 'OVV': 530, 'OXY': 879, 'PARSLY': 421, 'PDCE': -89, 'QEP': 0, 'RRC': -436, 'SM': -198, 'SRCI': 0, 'SWN': 532, 'SXCP': 862, 'TPGE': 0, 'VIICN': 89, 'VNOM': 0, 'VRI': 987, 'WES': 89, 'WLL': 0, 'WPX': 654, 'XOG': 0}}
The two lists I've created are named tickers and positions. The tickers list contains all of the dictionary keys (AKERBP, APA, AR..) the positions list contains all of the values (0, -189, 0...).
Below are my groupings for my if statements:
permian = ['APA', 'CENREP', 'CRROCK', 'DOUBEA', 'ENDENR', 'JAG', 'LPI', 'MSSCRK', 'MTDR', 'OVV', 'OXY', 'PARSLY', 'VNOM', 'WES', 'WPX']
beta = ['CLR', 'CPE', 'CVECN', 'HILCRP', 'MEGCN', 'NOG', 'OAS', 'QEP', 'SM', 'WLL', 'VIICN']
gas = ['AR', 'ASCRES', 'CNX', 'CRK', 'EQT', 'FANG', 'GPOR', 'RRC', 'SWN', 'VRI']
I've done the following thus far:
df = pd.DataFrame(df.groupby('Ticker(s)')['Position'].sum())
tickerlist = df.groupby('Ticker(s)')['Position'].sum().to_frame('Position').reset_index()
tickers = tickerlist['Ticker(s)'].values.tolist()
p=3
b=3
g=3
o=3
for ticker in tickers:
tickers = "%s %s"%(tickers,ticker.strip())
if ticker in permian:
sheet.cell(row=p, column=9).value = ticker
p += 1
elif ticker in beta:
sheet.cell(row=b, column=12).value = ticker
b += 1
elif ticker in gas:
sheet.cell(row=g, column=15).value = ticker
g += 1
else:
sheet.cell(row=o, column=18).value = ticker
o += 1
This method uses one of my lists, and it puts the tickers in the proper columns, I'm just having a hard time getting the positions to follow. I tried to use my dictionary instead, hoping I could use my for loop to populate the cells with both Tickers and Positions using the following:
dict=df.to_dict()
for key, value in dict.items():
if key in permian:
sheet.cell(row=p, column=9).value = str(key)
sheet.cell(row=p, column=10).value = str(value)
p += 1
elif key in beta:
sheet.cell(row=b, column=12).value = str(key)
sheet.cell(row=b, column=13).value = str(value)
b += 1
elif key in gas:
sheet.cell(row=g, column=15).value = str(key)
sheet.cell(row=g, column=16).value = str(value)
g += 1
else:
sheet.cell(row=o, column=18).value = str(key)
sheet.cell(row=o, column=19).value = str(value)
o += 1
This didn't work for me. My entire dictionary ended up in cell R3. If I can modify my code to get it all in one for loop, that would be preferable. However, given I know that my first code works, I could also search for the dictionary's key in Excel (since that populates correctly) and write a code that would populate its value next to it. I just haven't been able to figure out how to get that far. Any help here would be greatly appreciated!
If this is your df:
df = pd.DataFrame.from_dict({'Position': {'AKERBP': 0, 'APA': -189, 'AR': 0, 'ASCRES': 100, 'CENREP': 0, 'CHK': 0, 'CITHOL': 230, 'CLR': 900, 'CNX': 702, 'CPE': 230, 'CRK': -8, 'CRROCK': -497, 'CVECN': 139, 'DOUBEA': 265, 'ENDENR': 504, 'EQT': 482, 'FANG': 0, 'GPOR': 0, 'GRTWST': 0, 'HILCRP': -843, 'INDNAT': 120, 'JAG': 0, 'LPI': 304, 'MEGCN': 500, 'MSSCRK': 0, 'MTDR': 237, 'MUR': 0, 'NOG': 0, 'OAS': 0, 'OVV': 530, 'OXY': 879, 'PARSLY': 421, 'PDCE': -89, 'QEP': 0, 'RRC': -436, 'SM': -198, 'SRCI': 0, 'SWN': 532, 'SXCP': 862, 'TPGE': 0, 'VIICN': 89, 'VNOM': 0, 'VRI': 987, 'WES': 89, 'WLL': 0, 'WPX': 654, 'XOG': 0}})
When you run df.to_dict() the keys are the column names, which is why I expect that it's always writing to your default column:
print(df.to_dict())
Output
'Position': {'AKERBP': 0,
'APA': -189,
'AR': 0,
'ASCRES': 100,
'CENREP': 0,
'CHK': 0,
...
If you want the keys to be the names of the tickers, you can run .to_dict() on just the Position series:
print(df['Position'].to_dict())
Output
{'AKERBP': 0,
'APA': -189,
'AR': 0,
'ASCRES': 100,
'CENREP': 0,
'CHK': 0,
'CITHOL': 230,
...
Thus your code would look something like
d=df["Position"].to_dict()
for key, value in d.items():
if key in permian:
sheet.cell(row=p, column=9).value = str(key)
sheet.cell(row=p, column=10).value = str(value)
p += 1
elif key in beta:
sheet.cell(row=b, column=12).value = str(key)
sheet.cell(row=b, column=13).value = str(value)
b += 1
elif key in gas:
sheet.cell(row=g, column=15).value = str(key)
sheet.cell(row=g, column=16).value = str(value)
g += 1
else:
sheet.cell(row=o, column=18).value = str(key)
sheet.cell(row=o, column=19).value = str(value)
o += 1
Try using df.to_clipboard() at a point in your code when you have the dataframe in a format that you want it in to copy into Excel.
df.to_clipboard() copies your dataframe into the system clipboard, allowing you to paste it nicely into Excel.
Just noting as well that it's hard to know your exact objective. It seems like you only want to use Excel as a backup but it is the key question you ask in the title.

How to fix "AttributeError: type object has no attribute" in python?

I am adding some code to the preset code to check the time availability, which is if the meeting time can fit into the proposed time schedule. However, I keep getting the following error. Can anyone please give me some advices? Thanks so much for your time.
Preset codes:
from datetime import datetime
class Meeting:
def __init__(self, start_time, end_time):
self.start_time = start_time
self.end_time = end_time
My codes:
def check_availability(meetings, proposed_time):
meeting_start = Meeting.datetime.start_time.hour
meeting_end = Meeting.datetime.end_time.hour
ok_time = datetime.proposed_time.hour
if meeting_start < ok_time < meeting_end:
return True
else:
return False
meetings = [Meeting(datetime(2018, 8, 1, 9, 0, 0), datetime(2018, 8, 1, 11,
0, 0)), Meeting(datetime(2018, 8, 1, 15, 0, 0), datetime(2018, 8, 1, 16, 0,
0)), Meeting(datetime(2018, 8, 2, 9, 0, 0), datetime(2018, 8, 2, 10, 0, 0))]
print(check_availability(meetings, datetime(2018, 8, 1, 12, 0, 0)))
print(check_availability(meetings, datetime(2018, 8, 1, 10, 0, 0)))
Your code raises this exception:
AttributeError: type object 'Meeting' has no attribute 'datetime'
At this line:
meeting_start = Meeting.datetime.start_time.hour
Python is telling you that the Meeting class doesn't have an attribute named datetime. This is true: the Meeting class is a factory for making meeting objects (or instances), and these objects have start_time and end_time attributes, which are set by passing datetime instances to Meeting's __init__ method. These attributes can be accessed like this:
>>> meeting = Meeting(datetime(2018, 8, 1, 9, 0, 0), datetime(2018, 8, 1, 11,
0, 0))
>>> print(meeting.start_time)
2018-08-01 09:00:00
>>> print(meeting.end_time)
2018-08-01 11:00:00
Your check_availability function is being passed a list of meetings, so you need to loop over the list to check whether any of the meetings conflict with the proposed meeting time.
def check_availability(meetings, proposed_time):
# Loop over the list of meetings; "meeting"
# is the meeting that you are currently inspecting.
for meeting in meetings:
# if proposed_time is between meeting.start_time
# and meeting.end_time, return False
# If you get through the list without returning False
# then the proposed time must be ok, so return True.

Outlook.OlSaveAsType.olMSG

reportPath = "C:\\Test\\"
oApp = win32com.client.Dispatch("Outlook.Application")
nSpace = oApp.GetNamespace("MAPI")
nSpace.Logon()
oInbox = nSpace.GetDefaultFolder(win32com.client.constants.olFolderInbox)
oItems = oInbox.Items
for i in range(oItems.Count):
oMsg = oItems.Item(i+1)
oMsg.SaveAs(reportPath+str(i)+".msg", Outlook.OlSaveAsType.olMSG)
oMsg.SaveAs fails as "Outlook.OlSaveAsType.olMSG" parameter invalid.
What is its equivalent in win32com?
Please help
Try to pass a numeric value (olMSG = 3) instead. Or just remove the second parameter, it is optional.
Thanks #Eugene Astafiev for driving it. Finally it worked. Steps following.
OlSaveAsType = {
"olTXT": 0,
"olRTF": 1,
"olTemplate": 2,
"olMSG": 3,
"olDoc": 4,
"olHTML": 5,
"olVCard": 6,
"olVCal": 7,
"olICal": 8
}
&
oMsg.SaveAs("C:\\Test\\1.msg", OlSaveAsType['olMSG'])

Python dictionary dynamic update

so I have this dictionary x created from this function
olist = ['a/b/c','a/b/c/d','b/c/d','x/y/z','a/b','d/e/f','i/j/k']
def bulkFeed(objlist):
x = {}
for obj in objlist:
#pdb.set_trace()
dn_len = len(obj)
if dn_len not in x:
x[dn_len] = {}
if obj not in x[dn_len]:
x[dn_len][obj] = {}
x[dn_len][obj].update({"commit":1,"ObjectRef":obj})
return x
obj_dict = bulkFeed(olist)
>>> obj_dict
{3: {'a/b': {'commit': 1, 'ObjectRef': 'a/b'}}, 5: {'a/b/c': {'commit': 1, 'ObjectRef': 'a/b/c'}, 'd/e/f': {'commit': 1, 'ObjectRef': 'd/e/f'}, 'b/c/d': {'commit': 1, 'ObjectRef': 'b/c/d'}, 'x/y/z': {'commit': 1, 'ObjectRef': 'x/y/z'}, 'i/j/k': {'commit': 1, 'ObjectRef': 'i/j/k'}}, 7: {'a/b/c/d': {'commit': 1, 'ObjectRef': 'a/b/c/d'}}}
what I want to do is something like this in obj_dict
if 'a/b/c'.startswith('a/b'):
update commit to 0 in 'a/b/c' level
if 'a/b/c/d'.startswith('a/b/c'):
update commit to 0 in 'a/b/c/d' level
keep doing for every item in dictionary until reaching end of dict
Thanks any answer/headsup will be very helpful.
'a/b/c' stems from inner dictionary level for instance 'a/b/c/d' stems

Categories

Resources