Advanced string formatting using conversion operators - python-3.x

I am working with the minimum field width of conversion specifiers for a class, I have tried deleting and rewriting my last section in this the 'TD' and 'INT' but I keep getting an error on line td = float(quaterback_stats[qb]['TD']) the error message reads:
Traceback (most recent call last): File "main.py", line 24, in
td = float(quaterback_stats[qb]['TD']) NameError: name 'quaterback_stats' is not defined
I am struggling to understand how this is wrongly written to produce my outcome, when I have been using quaterback_stats as my defining variable for the rest of the code. The outcome of this code is supposed to create list attaching the quarterback to their stats. Any assistance on clarification would be appreciated, hope I posted this in the proper format:
quarterback_stats = {
'Aaron Rodgers': {'COMP': 371, 'YDS': 4925, 'TD': 39, 'INT': 8},
'Peyton Manning': {'COMP': 400, 'YDS': 4659, 'TD': 37, 'INT': 11},
'Greg McElroy': {'COMP': 19, 'YDS': 214, 'TD': 1, 'INT': 1},
'Matt Leinart': {'COMP': 16, 'YDS': 115, 'TD': 0, 'INT': 1}
}
print('2012 quarterback statistics:')
print(' Passes completed:')
for qb in quarterback_stats:
comp = quarterback_stats[qb]['COMP']
print(' %s : %d' % (qb, comp))
#print(' %?: %?' % (qb, comp)) # Replace conversion specifiers
# Hint: Use the conversion flag '-' to left-justify names
print(' Passing yards:')
for qb in quarterback_stats:
yds = quarterback_stats[qb]['YDS']
print(' %s : %d' % (qb,yds))
print(' Touchdown / interception ratio:')
for qb in quarterback_stats:
td = float(quaterback_stats[qb]['TD'])
int = float(quaterback_stats[qb]['INT'])
print(' %s : %.2f ' % (qb,td/int))

Related

Python, print colored duplicates found in 2 list

I'm 63 and just started with Python (My first steps with Udemy).
I'm Croatian so this is croatian language in program but you will understand when you run a program. I know it can be cleaner, shorter, more elegant etc, but as I mentioned before - I'm beginner.
import random
jedan = random.sample(range(1,99),15)
dva = random.sample(range(1,99),15)
def raspaljot(jedan, dva, i):
for x in jedan:
for y in dva:
if y == x:
index1 = jedan.index(x)
index1_str = str(index1)
index2 = dva.index(y)
index2_str = str(index2)
i += 1
x = str(x)
print(" Broj \033[31m" + x + "\033[0m,je dupli i nalazi se u listi jedan: na poziciji: \033[34m"
+ index1_str + "\033[0m a u listi dva na poziciji: \033[35m"+ index2_str + "\033[0m")
print()
print(jedan)
print(dva)
if i != 0:
print("\n *** Ukupno ima ", i, 'duplih brojeva. ***')
elif i == 0:
print("Nema duplih brojeva. :) ")
i = 0
raspaljot(jedan, dva,i)
What program do is finding duplicates in 2 random lists, them print duplicates in color and detecting position inside list[1] and list[2].
What I trying to do is printing list1 and list2 but showing duplicates in color.
For example:
[14, 78, 85, 31, 5, 54, 13, 46, 83, 4, 35, 41, 52, 51, 32]
[72, 40, 67, 85, 54, 76, 77, 39, 51, 36, 91, 70, 71, 38, 55]
here we have 3 duplicates (85,54,51). This above example on the console End was printed in white color, but I wanna these 3 numbers in red color in those two lines above.
Is this possible? I couldn't find a solution.
PS. Wing Pro version 7 on Fedora 33 Workstation / In WIngIde colors are only displayed in an external console and not the Debug I/O tool. :)
Simple solution would be something like this:
# Change list to string
jedan_str = str(jedan)
# Create set with numbers that need new color
num_set = {"85", "54", "51"}
# Iterate over every number and wrap it with color change
for i in num_set:
# Note that I used f-string to format string
# But you can also do this as "\033[31m" + i + "\033[0m"
jedan_str = jedan_str.replace("85", f"\033[31m{i}\033[0m")
# Print string that represent list
print(jedan_str)
Following the idea of using a set to determine which elements are in both lists (as Cv4niak proposed in his answer), I created a function to print the output as you desire. There are numerous other ways of achieving it, but I think this is a simple yet effective way.
The idea is to use the cprint() function from the termcolor package. You can install it with pip install termcolor, and then print normally all elements, except the ones that are duplicates, which will be printed using cprint(item, "red").
The "{:0>2d}" formatting in each ìtem print serves only to pad the number with zeros (so 2 will be printed as 02, for example), in order for the output of both lists to be aligned.
import random
from termcolor import cprint
def mark_duplicates(first, second):
duplicates = list(set(first).intersection(second))
if duplicates:
for list_ in [first, second]:
print("[", end="")
for item in list_:
if item in duplicates:
cprint("{:0>2d}".format(item), "red", end=",")
else:
print("{:0>2d}".format(item), end=",")
print("\b]")
else:
print("No duplicates.")
jedan = random.sample(range(1, 99), 15)
dva = random.sample(range(1, 99), 15)
mark_duplicates(jedan, dva)
With this, if there are no duplicates, the No duplicates. string will be printed. Also you can change the color with not much effort, and use other nice functionalities from termcolor package.

TypeError: 'str' object cannot be interpreted as an integer when multiplying 2 fields

I am using 2 columns in a file i.e Revenue and Margin to calculate profit for each row and then upload it to SearchAds. I am calculating profit in the function and it is throwing the error below:
Traceback (most recent call last):
File "C:\Python36\lib\site-packages\pandas\core\indexes\base.py", line
4381, in get_value
return libindex.get_value_box(s, key)
File "pandas\_libs\index.pyx", line 52, in pandas._libs.index.get_value_box
File "pandas\_libs\index.pyx", line 48, in
pandas._libs.index.get_value_at
File "pandas\_libs\util.pxd", line 113, in pandas._libs.util.get_value_at
File "pandas\_libs\util.pxd", line 98, in
pandas._libs.util.validate_indexer
TypeError: 'str' object cannot be interpreted as an integer
KeyError: 'MarginData'
I tried calculating the profit right after the If clause it still gives me the same error. Below is the code.
for filename in os.listdir('//AwsSQl/Share/ftpdata/'):
file = '//AwsSQl/Share/ftpdata/' + filename
if filename.startswith('Revenue_'):
print(filename)
file_name = filename
logging.info("Uploading Conversions from " + filename)
columns = ['Timestamp', 'OrderID', 'Revenue', 'MarginPct']
data = pd.read_csv(file, delimiter='\t')
data['Revenue'] = data['Revenue'].map(lambda x: '{:.2f}'.format(x))
data['MarginPct'] = data['MarginPct'].map(lambda x: '{:.2f}'.format(x))
pd.set_option('display.max_columns', 500)
pd.set_option('display.width', 1000)
dir = '//AwsSQl/Share/ftpdata/'
print(data.head(data['Timestamp'].count()))
print(data['Timestamp'].count())
for index, row in data.iterrows():
dt = parse(row['Timestamp'])
millisecond = int(round(dt.timestamp() * 1000))
if row['Orders'] > 0:
profit_upload(service, row['GCLID'], str(row['OrderID']) + "Pro" + str(index), millisecond, row['Revenue'], row['MarginData'])
def profit_upload(service, gclid, orderId, mill, rev, mar):
"""Upload conversion data to Adobe - Revenue.
Args:
service: An authorized Doubleclicksearch service. See Set Up Your Application.
gclid, orderId, millisecond, revenue, row
"""
request = service.conversion().insert(
body=
{
'conversion': [{
'agencyId': agencyId,
'advertiserId': advertiserId,
'attributionModel': 'External Attribution Model',
'clickId': gclid,
'conversionId': orderId,
'conversionTimestamp': mill,
'segmentationType': 'FLOODLIGHT',
'segmentationName': 'Adobe - DSG - Profit',
'type': 'Transaction',
'revenueMicros': (round(float(rev), 2) * round(float(mar), 2) * 1000000), #10 million revenueMicros is equivalent to $10 of revenue
'countMillis': 0 * 1000,
'currencyCode': 'USD',
}]
}
)
it seems that you have an str type where it needs an int type.
... row['MarginData']) # <-- I expect this is where the problem starts
Either it can't find any index for the row['MarginData'] or it expects something else.

'int' object not iterable - Python Lists

For context, I am trying to create a program that calculates the molar mass of a compound given its chemical formula. For each capital letter in the user's input (which is converted into a list), I plan on adding the string "+".
However, when I assign a list to the variable 'position' I run into the following error:
Traceback (most recent call last):
File "/Users/robertg21/PycharmProjects/MolecularMassCalculator/MolecularMassCalculator.py", line 42, in <module>
new_formula.insert(return_index(), "+")
File "/Users/robertg21/PycharmProjects/MolecularMassCalculator/MolecularMassCalculator.py", line 35, in return_index
position = list(formula.index(element))
TypeError: 'int' object is not iterable
Here is my code:
# This program calculates the molar mass of a compound given its chemical formula and number of atoms.
# Dictionary containing relative atomic mass of elements
relative_atomic_mass = {'H': 1.00794, 'He': 4.002602, 'Li': 6.941, 'Be': 9.012182, 'B': 10.811, 'C': 12.0107, 'N': 14.0067,
'O': 15.9994, 'F': 18.9984032, 'Ne': 20.1797, 'Na': 22.98976928, 'Mg': 24.305, 'Al': 26.9815386,
'Si': 28.0855, 'P': 30.973762, 'S': 32.065, 'Cl': 35.453, 'Ar': 39.948, 'K': 39.0983, 'Ca': 40.078,
'Sc': 44.955912, 'Ti': 47.867, 'V': 50.9415, 'Cr': 51.9961, 'Mn': 54.938045,
'Fe': 55.845, 'Co': 58.933195, 'Ni': 58.6934, 'Cu': 63.546, 'Zn': 65.409, 'Ga': 69.723, 'Ge': 72.64,
'As': 74.9216, 'Se': 78.96, 'Br': 79.904, 'Kr': 83.798, 'Rb': 85.4678, 'Sr': 87.62, 'Y': 88.90585,
'Zr': 91.224, 'Nb': 92.90638, 'Mo': 95.94, 'Tc': 98.9063, 'Ru': 101.07, 'Rh': 102.9055, 'Pd': 106.42,
'Ag': 107.8682, 'Cd': 112.411, 'In': 114.818, 'Sn': 118.71, 'Sb': 121.760, 'Te': 127.6,
'I': 126.90447, 'Xe': 131.293, 'Cs': 132.9054519, 'Ba': 137.327, 'La': 138.90547, 'Ce': 140.116,
'Pr': 140.90465, 'Nd': 144.242, 'Pm': 146.9151, 'Sm': 150.36, 'Eu': 151.964, 'Gd': 157.25,
'Tb': 158.92535, 'Dy': 162.5, 'Ho': 164.93032, 'Er': 167.259, 'Tm': 168.93421, 'Yb': 173.04,
'Lu': 174.967, 'Hf': 178.49, 'Ta': 180.9479, 'W': 183.84, 'Re': 186.207, 'Os': 190.23, 'Ir': 192.217,
'Pt': 195.084, 'Au': 196.966569, 'Hg': 200.59, 'Tl': 204.3833, 'Pb': 207.2, 'Bi': 208.9804,
'Po': 208.9824, 'At': 209.9871, 'Rn': 222.0176, 'Fr': 223.0197, 'Ra': 226.0254, 'Ac': 227.0278,
'Th': 232.03806, 'Pa': 231.03588, 'U': 238.02891, 'Np': 237.0482, 'Pu': 244.0642, 'Am': 243.0614,
'Cm': 247.0703, 'Bk': 247.0703, 'Cf': 251.0796, 'Es': 252.0829, 'Fm': 257.0951, 'Md': 258.0951,
'No': 259.1009, 'Lr': 262, 'Rf': 267, 'Db': 268, 'Sg': 271, 'Bh': 270, 'Hs': 269, 'Mt': 278,
'Ds': 281, 'Rg': 281, 'Cn': 285, 'Nh': 284, 'Fl': 289, 'Mc': 289, 'Lv': 292, 'Ts': 294, 'Og': 294,
}
# Asks for user input for chemical formula
chemical_formula = input("Enter chemical formula, or press return to quit: ")
formula = list(chemical_formula)
# Copies list and assigns it to variable new_formula
new_formula = formula.copy()
# Function returns index of letters that are an upper case letter.
def return_index():
for element in formula:
if element.isalpha() and element.isupper():
position = list(formula.index(element))
return position
# Inserts + before for each Capitalized letter in list.
for item in formula:
if item.isalpha() and item.isupper():
new_formula.insert(return_index(), "+")
print(new_formula)
Can anyone help?
Thanks.
def return_index():
for element in formula:
if element.isalpha() and element.isupper():
position = list(formula.index(element))
return position
this is plain wrong. list(formula.index(element)) won't work, index returns an integer, you cannot create a list out of an integer. returning in the middle of a loop makes no sense either.
Fortunately, your comment is clear enough to figure out what you want to do.
You want to use enumerate to get the index & the element, and a list comprehension to filter the indexes you want to return. Also your function should take formula as a parameter, not rely on a global variable:
# Function returns index of letters that are an upper case letter.
def return_index(formula):
return [position for position,element in enumerate(formula) if element.isupper()]
note that isalpha is already covered by isupper, you can remove that test.

Error when converting working code to a more object oriented structure Error: string indices must be integers Python 3

I keep running into the error: string indices must be integers when using placeholders for my script.
My program is supposed to track the growth of veggies purely on calculation. The idea is that each plant has it's own characteristics (eg carrotData) but instead of having code for each 'plantData' I replaced the code with (whichPlant and later whichPlantData) as a temporary placeholder (so that I don't need new code for each plant I have in my garden or that I want to add at a later point).
This is when I get the error in the last line (Plant is a class) marked with the ***. When I use (carrotData) instead of (whichPlantData) my script works. But as soon as I put in the temporary placeholder (whichPlantData) is breaks.
What causes this (so that I can avoid doing this in future projects) and how can I fix this?
thanks for the support!!
carrotData = {'plantID': '','plantingTime': dt(year=now.year, month=3, day=1), "dateOfPlanting": 0, "numberOfPlants": 0, "germinationTime": 7, "growthTime": 227, "flowerTime": 247, "harvestTime": 254, "liveCycles": 1, "status": 0}
potatoData = {'plantID': '','plantingTime': dt(year=now.year, month=3, day=1), "dateOfPlanting": 0, "numberOfPlants": 0, "germinationTime": 7, "growthTime": 227, "flowerTime": 247, "harvestTime": 254, "liveCycles": 1, "status": 0}
print ("imported plant datasheets")
#functions:
#if plant is added
def addPlant():
whichPlant = input("Which plant do you want to add? ")
n = int(input("How many plants do you want to add? "))
i = 0
whichPlantData = whichPlant + "Data"
if whichPlant in inventory:
while i < n:
i += 1
if whichPlant in plants:
plants[whichPlant] += 1
else:
plants[whichPlant] = 1
***Error*** whichPlant = Plant("", whichPlantData['plantingTime'], dt.now(), n, dt.now() + timedelta(days=whichPlantData['germinationTime']), dt.now() + timedelta(days=whichPlantData['growthTime']), dt.now() + timedelta(days=whichPlantData['flowerTime']),whichPlantData['harvestTime'], whichPlantData['liveCycles'], whichPlantData['status'])
Your problem seems to be with whichPlantData = whichPlant + "Data". whichPlant is a string returned by the input function. I think what you're trying to do is get a dictionary of plant information based on input from the user. Furthermore; whichPlant + "Data" seems like an attempt at making whichPlant the same as a variable name pointing towards a dictionary of plant information. Just because the string whichPlant may be equal to the variable name carrotData does not make it the same as the variable. I would suggest making a list of dictionaries full of the information about the plant then iterate over the items in that list to see if the dictionaries name key is the same as the user input.
Similar to this:
plants = [{"Name": "Carrot", 'plantID': '','plantingTime':0, "dateOfPlanting": 0, "numberOfPlants": 0, "germinationTime": 7, "growthTime": 227, "flowerTime": 247, "harvestTime": 254, "liveCycles": 1, "status": 0},
{"Name": "Potato", 'plantID': '','plantingTime': 0, "dateOfPlanting": 0, "numberOfPlants": 0, "germinationTime": 7, "growthTime": 227, "flowerTime": 247, "harvestTime": 254, "liveCycles": 1, "status": 0}]
PlantName = input("Enter a Plant: ")
for plant in plants:
if plant['Name'] == PlantName:
print("{}'s germinationTime is {}".format(PlantName, plant["germinationTime"]))
# DO SOMETHING

Conditional statement between today date and minus 3 months in Python

I am trying to insert 'NULL' values in a table depending on the date.
If the date is between todays date and 3 months backward (which will be february).
Then I want to update the 'NULL' values into each selected columns.
The Traceback is as following:
Traceback (most recent call last):
File "C:\projects\docs\script.py", line 41, in <module>
if dt < date_sql < dr3:
TypeError: '<' not supported between instances of 'datetime.datetime' and 'pyodbc.Row'
Been strugling for a long time, so really appreciate your guidance as I have tried to find a solution.
Python code is:
import pyodbc
from datetime import date, datetime
import dateutil.relativedelta
conn = pyodbc.connect(
r'DRIVER={SQL Server};'
r'SERVER=server;'
r'DATABASE=db;'
)
dt = datetime.today()
dr3 = dt - dateutil.relativedelta.relativedelta(months=3)
print(dr3)
cursor = conn.cursor()
sent_date = cursor.execute("""SELECT TOP 30 sent_date, id
FROM Department.Customer""")
def fetch_date():
for row in sent_date:
r = row
print(r)
return r
date_sql = fetch_date()
if dt < date_sql < dr3:
try:
value = None
cursor.execute("""UPDATE Department.Customer SET name=?, address=?, email=?,
phone=?""", (value, value, value, value))
cursor.commit()
except pyodbc.Error as ex:
print(str(ex))
cursor.rollback()
cursor.close()
Output from print(dr3) is:
2018-02-28 17:19:50.452290
Output from print(r) in fetch_date() function is:
(datetime.datetime(2018, 5, 22, 10, 21, 36), 1)
(datetime.datetime(2018, 5, 22, 10, 21, 36), 2)
(datetime.datetime(2018, 5, 22, 10, 21, 36), 3)
...

Resources