Functions and Groups



Global vs local variables:

  • Within a function:
    • if a variable is ONLY referenced, the global version is the one used
    • if a variable is ASSIGNED within the function body, it is LOCAL
    • a global variable can be accessed using the global keyword
x = 33
y = 77

def f():
   global y
   y = 17
   x = 24
   print (x, y)

f()
print (x, y)
Output:
24 17
33 17

Using a tuple:

  • NOTE: Note the comma in the += line
  • += wants to add another tuple, so use of parentheses ()

import random

def rolla (n):
  f = ()
  for g in range (n):
    f += (random.randrange(1,7), )
  return f

h = rolla (10)
print (h)
print (sorted(h))

Output:

(6, 6, 2, 1, 1, 3, 6, 6, 1, 2)
[1, 1, 1, 2, 2, 3, 6, 6, 6, 6]

Using a list with +=:

  • Using square brackets to add a list to a list
import random

def rolla (n):
  f = []
  for g in range (n):
    f += [random.randrange(1,7)]
  return f

h = rolla (10)
print (h)
print (sorted(h))
Output:
[2, 2, 3, 6, 1, 5, 4, 1, 4, 6]
[1, 1, 2, 2, 3, 4, 4, 5, 6, 6]

Using a list with append:

  • Here we don't need []'s
import random

def rolla (n):
  f = []
  for g in range (n):
    f.append(random.randrange(1,7))
  return f

h = rolla (10)
print (h)
print (sorted(h))
Output:
[5, 5, 3, 6, 4, 3, 5, 6, 6, 6]
[3, 3, 4, 5, 5, 5, 6, 6, 6, 6]

Using a set with |=:

  • Using curly brackets to add a set to a set {}
  • Note the update operator |=
import random

def rolla (n):
  f = set()
  for g in range (n):
    f |= {random.randrange(1,7)}
  return f

h = rolla (10)
print (h)
print (sorted(h))
Output:
{2, 3, 4, 5, 6}
[2, 3, 4, 5, 6]

Using a set with add:

  • Here we don't need {}'s
import random

def rolla (n):
  f = set ()
  for g in range (n):
    f.add(random.randrange(1,7))
  return f

h = rolla (10)
print (h)
print (sorted(h))
Output:
{2, 3, 4, 5, 6}
[2, 3, 4, 5, 6]

Using a dictionary with =

import random

def rolla (n):
  f = {1:0, 2:0, 3:0, 4:0, 5:0, 6:0}
  for g in range (n):
    k = random.randrange(1,7)
    f[k] = f.get (k)+1
  return f

h = rolla (200)
print (h)
print (str(h).replace (", ", "\n")
             .replace ("{" , "")
             .replace ("}" , ""))

Output:
{1: 30, 2: 23, 3: 26, 4: 48, 5: 34, 6: 39}
1: 30
2: 23
3: 26
4: 48
5: 34
6: 39

Using a dictionary with update

import random

def rolla (n):
  f = {1:0, 2:0, 3:0, 4:0, 5:0, 6:0}
  for g in range (n):
    k = random.randrange(1,7)
    f.update({k:f.get (k)+1})
  return f

h = rolla (200)
print (h)
print (str(h).replace (", ", "\n")
             .replace ("{" , "")
             .replace ("}" , ""))

Output:
{1: 30, 2: 23, 3: 26, 4: 48, 5: 34, 6: 39}
1: 30
2: 23
3: 26
4: 48
5: 34
6: 39

Using a dictionary with =, more parameters

import random

def rolla (a, b, n):
  f = {}
  c = 0 # make SURE this is int type when inserting a value
  for g in range (a, b):
    f[g] = c
  for g in range (n):
    k = random.randrange(a, b)
    f[k] = f.get (k)+1
  return f

h = rolla (5, 10, 200)
print (str(h).replace (", ", "\n")
             .replace ("{" , "")
             .replace ("}" , ""))
print (sorted(h))

Output:
5: 39
6: 29
7: 40
8: 43
9: 49
[5, 6, 7, 8, 9]

Input array

  • Input from numpy is a LOT easier using the following:
  • Thanks to John Levelle:
fig1 = np.fromstring(
         input('input 3x3 on a single line:\n'), sep=' ')
         .reshape(3, 3)


Init a set

f2 = set ()
f3 = set ()

for i in range (1, 101):
   f2 |= {i*i}
   f3 |= {i*i*i}
Another, perhaps even simpler approach:
sq = {i*i   for i in range (1, 100)}
cb = {i*i*i for i in range (1, 100)}

Init a list using range

y = [[x*0.5, math.sqrt(x*0.5), math.log10(x*.5)]\
    for x in range (1, 10)]



List of lists:

    r = sorted(states, key=lambda x: x[2], reverse=True)
    keys = r[:5]
    print (keys)

    plt.bar([x[0] for x in keys], [x[2] for x in keys], color='blue', width=0.3)
    plt.ylabel('Population')
    plt.xlabel('State')
    plt.show()



Max in Dictionary

An interesting example of getting the max value in a dictionary:
Reference:
info ={ 'Nicole':['bachelors',70000,'female'],
'James':['Masters', 125000,'Male'],
'Fred':['High School', 30000,'Male'],
'Rachel': ['Bachelors',60000,'female'],
'Jadon':['High School', 32000,'Male'],
'Micael': ['Bachelors',80000,'Male']}

d = info
v=list(d.values())
k=list(d.keys())
print (k[v.index(max(v, key=lambda x: int(x[1])))])
Output is James 0 which only works if the second field of the dictionary values is treated as an int - thus the int function in the key/lambda expression.    

Sorting and getting the top 5 - keys & values for plotting:

Note: int () is useful in the lambda expression in case the integers are inside quotes, ie, being treated as strings.

    d = info
    r = sorted(d, key=lambda x: int(d[x][1]), reverse=True)
    keys = r[:5]

    values = []
    for x in keys:
      values += [d[x][1]]


Indirect function calling

Calling functions by their string names, using a string list or string dictionary, with for loops:
def fa (pa):
   print ("fa:", pa)

def fb (pb):
   print ("-- fb:", pb)

far = ['fa', 'fb']
fas = {'fa':'dictionary a', 'fb':'dictionary b'}

print (str(globals()).replace(",", "\n"))

fa ('direct a')
fb ('direct b')

globals()['fa']('global a')
globals()['fb']("global b")


fz = globals()['fa']
fz ('indirect a')

fz = globals()['fb']
fz ('indirect b')

for fu in far:
   globals()[fu]('in for loop')


for key in fas:
   globals()[key](fas[key])
OUTPUT:
{'__name__': '__main__'
 '__doc__': None
 '__package__': None
 '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f8e84dd2910>
 '__spec__': None
 '__annotations__': {}
 '__builtins__': <module 'builtins' (built-in)>
 '__file__': 'FunctionString.py'
 '__cached__': None
 'fa': <function fa at 0x7f8e84dba160>
 'fb': <function fb at 0x7f8e86aed670>
 'far': ['fa'
 'fb']
 'fas': {'fa': 'dictionary a'
 'fb': 'dictionary b'}}

fa: direct a
-- fb: direct b
fa: global a
-- fb: global b

fa: indirect a
-- fb: indirect b
fa: in for loop
-- fb: in for loop

fa: dictionary a
-- fb: dictionary b

Menu Example

"""File: dictionary_functions.py
Date: Aub 31, 2021
Author: Nicholas Duchon
Purpose: This program demonstrated using keys in a dictionary to call functions.
"""

ENDER = 'q'

JUMPS = {'a': 'funca', 'b': 'funcb', 'c': 'funcc', 'd': 'funcd'}
SELECTIONS = str(JUMPS.keys())\
             .replace('dict_keys(','')\
             .replace('[','')\
             .replace ("'", "")\
             .replace('])','')

def funca (parama="In fa"):
    """Function funca"""
    print ("   funca:", parama)

def funcb (paramb="In fb"):
    """Function funcb"""
    print ("   funcb:", paramb)

def funcc (paramc="In fc"):
    """Function funcc"""
    print ("   funcc:", paramc)

def funcd (paramd="In fd"):
    """Function funcd"""
    print ("   funcd:", paramd)

def menu ():
    """Function menu"""
    retval = input (f"Selections: {SELECTIONS}, {ENDER} to quit: ")
    if retval.lower() == ENDER:
        return False
    if retval in JUMPS.keys():
        globals()[JUMPS[retval]](f'testing selection: {retval}')
    else:
        print (f"  >>>> Selection {retval} not found")
    return True

while menu ():
    pass
print ("   End of dictionaryFunctions.py program!")



Simpler Menu

ENDER = 'q'

def funca (parama="In fa"):
    """Function funca"""
    print ("   funca:", parama)

def funcb (paramb="In fb"):
    """Function funcb"""
    print ("   funcb:", paramb)

def funcc (paramc="In fc"):
    """Function funcc"""
    print ("   funcc:", paramc)

def funcd (paramd="In fd"):
    """Function funcd"""
    print ("   funcd:", paramd)

def not_found (paramnf):
    print (f"  >>>> Selection {paramnf} not found")

# version 2 - must be AFTER function declarations
JUMPS = {'a': funca, 'b': funcb, 'c': funcc, 'd': funcd}
SELECTIONS = str(JUMPS.keys())\
             .replace('dict_keys(','')\
             .replace('[','')\
             .replace ("'", "")\
             .replace('])','')

def menu ():
    """Function menu"""
    retval = input (f"Selections: {SELECTIONS}, {ENDER} to quit: ")
    if retval.lower() == ENDER:
        return False

    # version 2:
    selection = JUMPS.get (retval, lambda: not_found (retval))
    selection ()

    return True

while menu ():
    pass
print ("   End of dictionaryFunctions.py program!")



(end)