IncognitoBatman IncognitoBatman - 3 days ago 5
Python Question

Finding the average pH through files

My code is supposed to calculate and print the average pH for every fluid given the file variable name.

This is what I have so far, trying to separate the txt file into parts using

split()
.

I don't really know how to separate the function line by line to calculate each pH and print it separately.

Right now it prints nothing, since it most likely doesn't see a number in the first slot

Function

def average_ph(file_variable):

result = 0
line = file_variable.readline()
found = False
while line != "" and not found:
list = line.strip().split(",")
if list.isnum:
result += list
if line != "":
avg = result / 3
if not found:
result = None
print(avg)
return avg


Main

file_name = str(input("Enter a file name: "))
file_variable = open(file_name, "r", encoding="utf-8")


File - named: pH.txt

Lemon juice,2.4,2.0,2.2
Baking soda (1 Tbsp) in Water (1 cup),8.4,8.3,8.7
Orange juice,3.5,4.0,3.4
Battery acid,1.0,0.7,0.5
Apples,3.0,3.2,3.5

jez jez
Answer

Boy, where to start?

list = line.strip().split(",")
if list.isnum:

First, list is the name of a built-in type in Python, and while you can overshadow that by using it as a variable name, for the sake of not confusing yourself and everybody else, you really shouldn't:

lst = line.strip().split(",")
if lst.isnum:

OK, that's better. lst is an instance of the class that can now still be referred to as list. Now, your if lst.isnum: appears to be an attempt to test the output of a method of that instance. But in Python you can't call methods without typing the parentheses. Without parentheses, currently, your if statement is asking whether the pointer to the method itself is non-zero which, for methods that exist, is always going to be true...

lst = line.strip().split(",")
if lst.isnum():

OK, that's better. Except note that I said, "...for methods that exist". isnum is not a method of the list class so the code will just raise an exception here. You presumably mean the string method .isnumeric:

lst = line.strip().split(",")
if lst.isnumeric():

But of course this is still wrong. You want to test whether items in the list are numeric. Therefore, you need to call some function or method of each item, not of the list itself. Although strings have an isnumeric method, the list class (to which our lst variable belongs) does not. One elegant way around this is to use a "list comprehension":

lst = line.strip().split(",")
lst = [item for item in lst if item.isnumeric()]

But of course that doesn't actually convert the items from strings to numbers. Did you really think you could just add up a bunch of strings and divide by 3?

lst = line.strip().split(",")
lst = [float(item) for item in lst if item.isnumeric()]

OK, now we have a list of actual floating-point numbers that can be manipulated numerically. But we've thrown away the information about which substance we're measuring.

lst = line.strip().split(",")
substance = lst.pop(0)   # remove and store the first item in the list
lst = [float(item) for item in lst if item.isnumeric()]

I would then suggest that you somehow associate each pH value-list/average with its respective substance—otherwise that associative info is going to get lost/corrupted. There are neat ways of doing that with a dict, although currently you have a variable called found that is unused—suggesting that you may be intending to do something like:

if substance == the_particular_substance_we_are_currently_interested_in:
    found = True
    avg = ...

(Note: if you do this, do it inside the loop—you want to check each line to see if it's the target, after all.)

Now, as for your result += lst... Well, you initialized result to 0 so it's an integer, and lst as we know is a list. You can't add a list to an integer—it doesn't make sense. What you presumably want to do is sum the values in the list (and you won't even need result):

    avg = sum(lst) / len(lst)

Note that I'm dividing by whatever the length of lst is, rather than hard-coding the number 3 in there. Hardcoding assumptions like that is a really effective way to set hard-to-find traps for your future self, so let's avoid it.

Good luck.

Comments