Skip to content

Python treasures from the internet

My collection of interesting posts on python.

Local and global variables in functions

Using global variables to local functions can be dangerous! Example the code below:

beta = 10
alfa = list(np.arange(1, 5))
for j in np.arange(0, 3):
    def xx(j, beta, alfa):
        beta = beta * (1+j*1e-4)
        alfa[1] = 1232342.+j
        print(f'     inside     : {j=} {beta=:<12.3f}, {alfa=}')
    print(f' in the main    : {j=} {beta=:<12.3f}, {alfa=}')
    xx(j, beta, alfa)
    print(f' >> final : {beta=:<12.3f}, {alfa=}')
which produces this output:
    in the main    : j=0 beta=10.000      , alfa=[1, 2, 3, 4]
        inside     : j=0 beta=10.000      , alfa=[1, 1232342.0, 3, 4]
    >> final : beta=10.000      , alfa=[1, 1232342.0, 3, 4]
    in the main    : j=1 beta=10.000      , alfa=[1, 1232342.0, 3, 4]
        inside     : j=1 beta=10.001      , alfa=[1, 1232343.0, 3, 4]
    >> final : beta=10.000      , alfa=[1, 1232343.0, 3, 4]
    in the main    : j=2 beta=10.000      , alfa=[1, 1232343.0, 3, 4]
        inside     : j=2 beta=10.002      , alfa=[1, 1232344.0, 3, 4]
    >> final : beta=10.000      , alfa=[1, 1232344.0, 3, 4]
So, the variable beta is used inside the function but is not modified outside its scope, while the object alfa is modified for the whole program.

A good reading on the issue here

Passing command arguments to functions in a script

In my python scripts I often use command line arguments to change the script's behaviour without changing the code. Python provides the argparse module, which is a powerful tool to define, handle and parse the arguments in the script. Then, the next issue is how to use the defined arguments within the script, in particular how to pass them into the functions within the script.

The option to declare them as global should be avoided. An interesting alternative without being too complicated is shown below:

# 
# example how to pass command line arguments within the functions in a python script
#

import argparse

def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('-d', '--date', help='enter the date of the event')
    parser.add_argument('-n', '--nrec', type=int, default=10, help='number of records to consider', required=False)
    parser.add_argument('-v', '--verbosity, action='store_true', help='turn on prints', required=False)
    return parser.parse_args()

class MyConfig:
    args = None

config = MyConfig()

def fetch_data():
    if config.args.verbose:
        print(f"Fetching data since {config.args.date}...")

    # --- code here

    return something

def process_data(data):
    if config.args.verbose:
        print(f"Processing {len(data)} records (limit={config.args.nrec})...")

    # -- code here

    return [d.upper() for d in data[:config.args.nrec]]

def main():
    config.args = get_args()
    data = fetch_data()
    results = process_data(data)
    print("Done:", results)

if __name__ == "__main__":
    main()