Python Forum
setting parameters for functions and nested functions
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
setting parameters for functions and nested functions
#1
I feel I'm shaky on understanding the interplay between passing variables through functions (outside of classes)...Basically IDK when to use foo() vs foo(bar) especially in freestanding (OUTSIDE of a class) nested functions. Wall Wall Wall

PLEASE HELP

I wrote this up. it's a self contained script:
#!usr/bin/env python3
#defexp0.py
import sys
from functools import partial as p
def inquire(a,type,errmsg):
	while True:
		b = input(a)
		if b !='':
			try:
				b == type(b)
			except ValueError:
				print('{}'.format(errmsg))
				continue
			else:
				print('ok')
				return b
		else:
			print(f'{a:^50} must be answered.')
			continue

the_q = p(inquire,type=str,errmsg='sorry')

def foo():
	while True:
		quit_now = the_q('\'y\' to quit anything else to continue')
		quit_now.strip().lower()
		if quit_now =='y' or quit_now =='yes':
			sys.exit()
		else:
			bar()
			continue
		
def bar():
	quest=the_q('please enter a, b, c, d or etc.')
	quest.strip().lower()
	if quest == 'a':
		forA(quest)
	elif quest == 'b':
		forB()#won't work
	elif quest == 'c':
		forC(quest)
	elif quest == 'd':
		forD()
	elif quest == 'e':
		forE(quest)
	else:
		forEtc()

def forA(x):
	print(f'{x:^10}is fine.')

def forB():
	global someVariable
	print('nothing...'.format(someVariable))
'''but this WOULD work:
def forB():
	global someVariable
	print('nothing...')
I don't understand
'''

def forC(y):
	print('{} works too...'.format(y))

def forD():
	print('fine')

def forE(someVariable):
	global quest
	print('should work...'.format(someVariable))
	#forE() global variable names must be different from parameter names???

def forEtc():
	print('works')

if __name__=='__main__':
	foo()
else:
	print('sorry {__name__} not main') 
It works. Except for [input]b[/input]

this triggers
Error:
Traceback (most recent call last): File "defexp0.py", line 77, in <module> foo() File "defexp0.py", line 30, in foo bar() File "defexp0.py", line 39, in bar forB()#won't work File "defexp0.py", line 54, in forB print('nothing...'.format(someVariable)) NameError: name 'someVariable' is not defined
Perhaps someone could clarify foo() vs foo(bar) and their nuances in nested functions? Please?
Reply
#2
Think of a function as a sort of black box. You give it some data to work with, it does *something*, and then gives you a return value. A function shouldn't use any value that isn't passed to it. global should be avoided at all costs.
Reply
#3
(Feb-24-2018, 06:13 PM)nilamo Wrote: Think of a function as a sort of black box. You give it some data to work with, it does *something*, and then gives you a return value.
Yes. And it works wonderfully well when functions are part of a class.

Quote:A function shouldn't use any value that isn't passed to it.

this is where I get frustrated lol. Pls see code in op above. Entire script runs off foo(). Not a single parameter, but quite a few variable gets assigned values in its body....
So this is what keeps getting me and textbooks seems to not care about the discrepency

def foo():
    a = 'moo'
    print(a)
    bar()

def bar():
    print('bar function')

if __name__=='__main__':
    foo()
else:
    print('choosing not to run')
this script runs...this bothers me.

Maybe it's a detail that comes from experience but I never feel certain when I can make do with foo() and when I need foo(param)....
Reply
#4
(Feb-24-2018, 09:14 PM)mepyyeti Wrote: this script runs...this bothers me.

Maybe it's a detail that comes from experience but I never feel certain when I can make do with foo() and when I need foo(param)....
Make it clear that foo takes a augment.
def foo(bar):
    a = 'moo'
    print(a)
    bar()

def bar():
    print('bar function')

if __name__=='__main__':
    foo(bar)
else:
    print('choosing not to run')
Quote:this is where I get frustrated lol. Pls see code in op above. Entire script runs off foo().
That's normal to have a function that run whole script,the design bit can be the hard part to figure out.
Clearer name(like eg menu) and never ever global,make it clear that a function take arguments,not to long functions.
Can be some tips.

Example no variables in global name namespace,calling menu start it.
result function takes 2 argumet,coin_flip and user_choice these function do only one task each.
Always fall back to menu where can play again or Quit out.

import random

def coin_flip():
    return random.choice(('head', 'tail'))

def user_choice():
    command = input("Choose Head or Tail: ").lower()
    return command

def result(coin_flip, user_choice):
    ''' Doc string explain what function do'''
    coin = coin_flip()
    choice = user_choice()
    if coin == choice:
        print(f'\nComputer <{coin}> You gussed <{choice}> which is correct\n')
    else:
         print(f'\nComputer <{coin}> You gussed <{choice}> which is wrong\n')

def menu():
    while True:
        print('(1) Coin flip game')
        print('(Q) Quit\n')
        choice = input('Enter your choice: ').lower()
        if choice == '1':
            result(coin_flip, user_choice)
        elif choice == 'q':
            return False
        else:
            print(f'Not a correct choice: {choice}')

if __name__ == '__main__':
    menu()
If function get to complicated to design use a class Wink
Reply
#5
SO with the 1st snippet:
def foo(bar):
    a = 'moo'
    print(a)
    bar()
 
def bar():
    print('bar function')
 
if __name__=='__main__':
    foo(bar)
else:
    print('choosing not to run')
since both foo() and foo(bar) work to execute the script...is it simply a matter of best practices to just use foo(bar) to run the script? Technically, whether or not I have a parameter doesn't seem too matter...

Regarding the snippet you wrote:
import random
 
def coin_flip():
    return random.choice(('head', 'tail'))
 
def user_choice():
    command = input("Choose Head or Tail: ").lower()
    return command
 
def result(coin_flip, user_choice):
    ''' Doc string explain what function do'''
    coin = coin_flip()
    choice = user_choice()
    if coin == choice:
        print(f'\nComputer <{coin}> You gussed <{choice}> which is correct\n')
    else:
         print(f'\nComputer <{coin}> You gussed <{choice}> which is wrong\n')
 
def menu():
    while True:
        print('(1) Coin flip game')
        print('(Q) Quit\n')
        choice = input('Enter your choice: ').lower()
        if choice == '1':
            result(coin_flip, user_choice)
        elif choice == 'q':
            return False
        else:
            print(f'Not a correct choice: {choice}')
 
if __name__ == '__main__':
    menu()
user_choice() clearly creates a variable, command, and gives it a value but necessitates no parameter. Yet, result(*args) also creates variables,coin and choice, and gives them the returned value of the 2 executed functions, coin_flip and user_choice.

why not just say:
...
def result():
    ''' Doc string explain what function do'''
    coin = coin_flip()
    choice = user_choice()
...
the logic works fine for
...
def user_choice():
#yes I know value of command is set to user's input not  the return result of a previous function
    command = input("Choose Head or Tail: ").lower()
    return command
...
Question boils down to : Why do I need to set up parameters at all. user_choice() shows that I can create variables without parameters (technically just 1 positional)? this is where I get tripped up...
Reply
#6
(Feb-25-2018, 03:48 AM)mepyyeti Wrote: Why do I need to set up parameters at all. user_choice() shows that I can create variables without parameters
To make it clear and more readable that a function take in code in from outside.
The black box model as @nilamo talk abot crash as son as a function,variable,list,ect... magically appear in a function when is not set as parameter.
As soon as this happen you wonder where dos it come from has it a relationship with this function?
It can be easy to see in shorter code as my example,in larger code it can be a pain that stuff just magically appear from somewhere else.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Passing writable arguments to functions. Assembler 11 826 Jan-15-2024, 11:32 PM
Last Post: sgrey
  partial functions before knowing the values mikisDeWitte 4 539 Dec-24-2023, 10:00 AM
Last Post: perfringo
  Calling functions by making part of their name with variable crouzilles 4 749 Nov-02-2023, 12:25 PM
Last Post: noisefloor
  __name__ and __main__ in functions Mark17 3 680 Oct-12-2023, 01:55 AM
Last Post: deanhystad
  How can i combine these two functions so i only open the file once? cubangt 4 805 Aug-14-2023, 05:04 PM
Last Post: snippsat
  It seems you have to define functions at the top 357mag 7 1,242 May-10-2023, 03:01 PM
Last Post: jefsummers
  Merge two functions to one SamLiu 4 1,054 May-05-2023, 01:36 PM
Last Post: SamLiu
  Can I get some clarification on importing functions from external files. wh33t 3 871 Feb-25-2023, 08:07 PM
Last Post: deanhystad
  Whys is asterisk and random variable necessary in these functions? rrowhe4d 5 1,444 Aug-05-2022, 07:53 AM
Last Post: Gribouillis
  Using C++/CLI wrapper functions by Python Ales1000 2 1,732 Jun-21-2022, 04:50 AM
Last Post: Ales1000

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020