the *args parameter are 'keyword-onlyargumentsmeaning that they can only be used as keywords rather than positional arguments def concat(*argssep="/")return sep join(argsconcat("earth""mars""venus"'earth/mars/venusconcat("earth""mars""venus"sep="'earth mars venusunpacking argument lists the reverse situation occurs when the arguments are already in list or tuple but need to be unpacked for function call requiring separate positional arguments for instancethe built-in range(function expects separate start and stop arguments if they are not available separatelywrite the function call with the *-operator to unpack the arguments out of list or tuplelist(range( )[ args [ list(range(*args)[ normal call with separate arguments call with arguments unpacked from list in the same fashiondictionaries can deliver keyword arguments with the **-operatordef parrot(voltagestate=' stiff'action='voom')print("-this parrot wouldn' "actionend='print("if you put"voltage"volts through it "end='print(" ' "state"!" {"voltage""four million""state""bleedindemised""action""voom"parrot(** -this parrot wouldn' voom if you put four million volts through it ' bleedindemised lambda expressions small anonymous functions can be created with the lambda keyword this function returns the sum of its two argumentslambda aba+ lambda functions can be used wherever function objects are required they are syntactically restricted to single expression semanticallythey are just syntactic sugar for normal function definition like nested function definitionslambda functions can reference variables from the containing scopedef make_incrementor( )return lambda xx make_incrementor( ( ( the above example uses lambda expression to return function another use is to pass small function as an argument more on defining functions