简体   繁体   中英

Python different functions depending on input

I wrote a program to solve the problems for my physics chapter which takes all the given data and does everything it can with it. I used a long string of if statements to check which functions are safe to call (the functions themselves are not safe), but I feel like there must be a better way to do this.

the full code is here

Here's a snippet of the offender (argparse default is None):

# EVALUATE:
if args.t and args.ld:
    print 'Velocity:', find_velocity(args.t, args.ld)
if args.t and args.l and args.m:
    print 'Velocity:', find_velocity(args.t, args.l, args.m)
if args.l:
    print 'Longest possible standing wave length:', find_longest_possible_standing_wave_length(args.l)
if args.l and args.m and args.t and args.n:
    print 'Frequency of the standing wave with', args.n, 'nodes:', find_nth_frequency_standing_wave(args.t, args.n, args.l, args.m)
if args.s and args.t and args.n and args.l:
    print 'Frequency of', args.n, 'standing wave:', find_nth_frequency_standing_wave(args.t, args.n, args.l, velocity=args.s)
if args.ld and args.t and args.f:
    print 'Angular wave number: ', find_angular_wave_number(args.ld, args.t, args.f)
if args.p:
    print 'Difference in amplitude of twins:', find_amplitude_difference_of_twins(args.p)
if args.f:
    print 'Angular wave frequency:',  find_angular_wave_frequency(args.f)

Thanks!

Put the functions in a list, then filter that list on making sure that for each variable name in that function those arguments are not none.

Example:

def func_filter(item, arguments):
    needed_args = item.func_code.co_varnames
    all(map(lambda x: getattr(arguments, x) , needed_args))

funcs = (find_velocity, find_nth_frequency_standing_wave)
funcs = filter(lambda x: func_filter(x, args), funcs)
#now execute all of the remaining funcs with the necessary arguments,
#similar to code in func filter

Don't hold me over the coals on syntax, just let me know if I messed up anywhere, I only tried parts of it on the interpreter.

Given the design of your program, you have found a not-too-bad way of implementing what you want to do. But I think there's something fishy with the design of your program.

If I understand correctly, you permit the user to pass as many or as few arguments as s/he wishes and then call all the functions which make sense given which arguments are defined. Why not require either all the arguments to be passed or one of the functions to be named on call?


If you are stuck to this design you could try the following:

  • make a dict of function -> required arguments:

     {find_velocity: ("t", "ld"), ...} 
  • loop over the dict and check whether you have each property:

     for func, reqs in funcs.items(): args = [getattr(args, req) for req in reqs] if all(args): func(*args) 

It seems like you want to call a function and then pass it in some arguments. In this case, you may not need argparse at all. Instead try making the function you want to be the first command line argument, then take everything else as arguments to that function.

You can access the first argument with sys.argv[1] , and all other arguments with sys.argv[2:] .

Then you can call the function like this:

locals()[sys.argv[1]](*sys.argv[2:])

Assuming your functions are defined in the local module.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM