3
\$\begingroup\$

I'm a beginner and self taught and just want to see if there are neater ways of doing what I am doing, or whether there are bits of code that are poorly written. I think Lines 100-204 are the most crudely written. Below I've also determined who is bowling first and therefore assigning a dictionary to that team for there bowling extras. I feel there must be a better way using True and False statements

# Determining who lost the toss and who is batting first
if info['home team'] == info['toss_winner']:
    toss_loser = info['away team']
elif info['home team'] != info['toss_winner']:
    toss_loser = info['home team']
if info['toss_decision'] == 'field':
    first_innings: object = toss_loser
elif info['toss_decision'] != 'field':
    first_innings = info['toss_winner']
# Determining which team the extras belong to for each innings
if first_innings == info['toss_winner']:
    first_innings_extras = {'bowling team': f"{toss_loser}", 'total': 0, 'wides': 0, 'no-balls': 0,
                            'byes': 0, 'leg-byes': 0, 'penalty': 0}
    second_innings_extras = {'bowling team': f"{info['toss_winner']}", 'total': 0, 'wides': 0,
                             'no-balls': 0, 'byes': 0, 'leg-byes': 0, 'penalty': 0}
elif first_innings != info['toss_winner']:
    first_innings_extras = {'bowling team': f"{info['toss_winner']}", 'total': 0, 'wides': 0,
                            'no-balls': 0, 'byes': 0, 'leg-byes': 0, 'penalty': 0}
    second_innings_extras = {'bowling team': f"{toss_loser}", 'total': 0, 'wides': 0, 'no-balls': 0,
                             'byes': 0, 'leg-byes': 0, 'penalty': 0}

Any advice would be hugely appreciated!

Link to code: https://github.com/hanners999/Natwest-T20-Blast/blob/main/cricket_data.py

Link to CSV files (towards bottom of page - look for T20 Blast (CSV new) : https://cricsheet.org/downloads/

\$\endgroup\$

1 Answer 1

10
\$\begingroup\$

Disclaimer: I know nothing whatsoever about the rules of cricket.

Useless check

Because either info['toss_decision'] equals 'field' or it does not, you do not need to check things twice in:

if info['toss_decision'] == 'field':
    first_innings: object = toss_loser
elif info['toss_decision'] != 'field':
    first_innings = info['toss_winner']

which could be written as:

if info['toss_decision'] == 'field':
    first_innings: object = toss_loser
else:
    first_innings = info['toss_winner']

Not that it really changes anything but you could also write this using the ternary operator:

first_innings = toss_loser if info['toss_decision'] == 'field' else info['toss_winner']

Similarly, either info['home team'] and info['toss_winner'] are equal or they are not. We could write:

if info['home team'] == info['toss_winner']:
    toss_loser = info['away team']
else:
    toss_loser = info['home team']

or even:

toss_loser = info['away team'] if info['home team'] == info['toss_winner'] else info['home team']

Going further, one could also imagine writing the retrieval from the structure slightly differently:

toss_loser = info['away team' if (info['home team'] == info['toss_winner']) else 'home team']

Finally, the same argument applies to the last part of the code as well.

Duplicated logic

In the final part of the code, we are creating dictionnaries in a pretty similar way. It could help to try to see which parts are actually the same and which parts are different.

We'd get something like:

if first_innings == info['toss_winner']:
    bowling_first = toss_loser
    bowling_second = info["toss_winner"
else:
    bowling_first = info["toss_winner"]
    bowling_second = toss_loser

first_innings_extras = {'bowling team': f"{bowling_first}", 'total': 0, 'wides': 0,
                            'no-balls': 0, 'byes': 0, 'leg-byes': 0, 'penalty': 0} 
second_innings_extras = {'bowling team': f"{bowling_second}", 'total': 0, 'wides': 0,
                             'no-balls': 0, 'byes': 0, 'leg-byes': 0, 'penalty': 0}

Introducing more variables

The value info["toss_winner"] is heavily used through the code and we have a toss_loser variable. Maybe it'd make things clearer and more consistent to define a variable for it.

Getting rid of the intermediate variables

On the other side, it looks like we check the toss decision to determine the first innings and then check the first inning to determine who is bowling first and who is bowling second. We could probably get rid of the intermediate logic about innings.

At this point, we'd get something like:

toss_winner = info['toss_winner']
toss_loser = info['away team' if (info['home team'] == toss_winner) else 'home team']

# Determining which team the extras belong to for each innings
if info['toss_decision'] != 'field':
    bowling_first = toss_winner
    bowling_second = toss_loser
else:
    bowling_first = toss_loser
    bowling_second = toss_winner

first_innings_extras = {'bowling team': f"{bowling_first}", 'total': 0, 'wides': 0,
                            'no-balls': 0, 'byes': 0, 'leg-byes': 0, 'penalty': 0} 
second_innings_extras = {'bowling team': f"{bowling_second}", 'total': 0, 'wides': 0,
                             'no-balls': 0, 'byes': 0, 'leg-byes': 0, 'penalty': 0}

Additional notes about the different innings

I am not sure this is 100% relevant to what you are trying to achieve but I'd like to show a few other things that could be done.

Python allows to write multiple assignment which in your case could mean something like:

if info['toss_decision'] == 'field':
    bowling_first, bowling_second = toss_loser, toss_winner
else:
    bowling_first, bowling_second = toss_winner, toss_loser

This could again be written with a ternary operator but it probably makes it more complicated than it needs to be.

Another possible improvement is to notice that bowling_first and bowling_second will be handled in much the same way. Instead of having 2 variables for these, we could try to use a relevant data structure: a tuple or a list for instance.

# Determining which team the extras belong to for each innings
if info['toss_decision'] == 'field':
    bowling_order = toss_loser, toss_winner
else:
    bowling_order = toss_winner, toss_loser

first_innings_extras = {'bowling team': f"{bowling_order[0]}", 'total': 0, 'wides': 0,
                            'no-balls': 0, 'byes': 0, 'leg-byes': 0, 'penalty': 0}
second_innings_extras = {'bowling team': f"{bowling_order[1]}", 'total': 0, 'wides': 0,
                             'no-balls': 0, 'byes': 0, 'leg-byes': 0, 'penalty': 0}

But then, the same logic applies to the innings: maybe we do not really need 2 variables for this.

# Determining which team the extras belong to for each innings
bowling_order = (
    (toss_loser, toss_winner)
    if (info["toss_decision"] == "field")
    else (toss_winner, toss_loser)
)

innings = (
    {
        "bowling team": f"{team}",
        "total": 0,
        "wides": 0,
        "no-balls": 0,
        "byes": 0,
        "leg-byes": 0,
        "penalty": 0,
    }
    for team in bowling_order
)
\$\endgroup\$
0

Not the answer you're looking for? Browse other questions tagged or ask your own question.