Compute a students grade based on weight of assignments Hoping to get feedback on how this program could be written in the most pythonic way. Also welcome any criticisms of styling as I know this is not in accordance with pep-8

from collections import namedtuple
a = namedtuple('assignment', 'weight scores')
def average(scores:list):
    '''average a list of scores'''
    return sum(scores)/len(scores)
def get_grade(grades:list):
    '''compute final grade based on scores and their weights'''
    result = 0
    for a in grades:
        result += average(a.scores) * a.weight
    return result 
def main():
   grades = [a(.30, [18/45, 11/55]),
             a(.20, [3/10, 7.5/10, 10/10]),
             a(.10, [9/10, 9/10, 10/10, 10/10, 8/10,
                6/10, 10/10, 10/10]),
             a(.40, [29/65]), 
             a(.01, [1/1])]
   print(get_grade(grades))
main()
from collections import namedtuple


You should put blank lines after imports, and between function/class definitions. 



a = namedtuple('assignment', 'weight scores')


Using a namedtuple for a simple data class like this is a good idea, but it should still be named as a class; Assignment.



def average(scores:list):
    '''average a list of scores'''
    return sum(scores)/2


This function has an obvious bug; what about lists of scores with lengths other than two? Also you type the parameter but not the return value, and should again have some more whitespace; I'd write:

def average(scores: list) -&gt; float:
    """Average a list of scores."""
    return sum(scores) / len(scores)


See PEP-257 for docstring conventions. 



def get_grade(grades:list):
    '''compute final grade based on scores and their weights'''
    result = 0
    for a in grades:
        result += average(a.scores) * a.weight
    return result 


I think you could simplify this with a bit more OOP. If we subclass the named tuple we can add a read only calculated attribute to it:

class Assignment(namedtuple('Assignment', 'weight scores')):

    @property
    def result(self) -&gt; float:
        return average(self.scores) * self.weight


Then your function becomes:

def get_grade(assignments: list) -&gt; float:
    """Compute final grade based on scores and their weights."""
    return sum(a.result for a in assignments)


Note the revised parameter name, which better describes the input. 



def main():
   grades = [a(.30, [18/45, 11/55]),
             a(.20, [3/10, 7.5/10, 10/10]),
             a(.10, [9/10, 9/10, 10/10, 10/10, 8/10,
                6/10, 10/10, 10/10]),
             a(.40, [29/65]), 
             a(.01, [1/1])]
   print(get_grade(grades))
main()


To keep things looking consistent without introducing a lot of indentation, I usually split lists with long elements across multiple lines as follows:

assignments = [
    Assignment(.30, [18/45, 11/55]),
    ...
    Assignment(
        .10,
        [9/10, 9/10, 10/10, 10/10, 8/10, 6/10, 10/10, 10/10]
    ),
    ...
]


Note splitting between, rather than within, the two parameters. 

Also you should guard the invocation of the entry point as follows:

if __name__ == '__main__':
     main()


This means you can import this functionality more easily for testing and reuse.