# Copyright 2025, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file """Various kinds of functions with small specialties.""" from __future__ import print_function import inspect import sys # pylint: disable=redefined-outer-name var_on_module_level = 1 def closureTest1(some_arg): # pylint: disable=unused-argument x = 3 def enclosed(_f="default_value"): return x return enclosed print("Call closured function returning function:", closureTest1(some_arg="ignored")()) def closureTest2(some_arg): # pylint: disable=unused-argument def enclosed(_f="default_value"): return x x = 4 return enclosed print("Call closured function returning function:", closureTest2(some_arg="ignored")()) def defaultValueTest1(_no_default, some_default_constant=1): return some_default_constant print( "Call function with 2 parameters, one defaulted, and check that the default value is used:", defaultValueTest1("ignored"), ) def defaultValueTest1a( _no_default, some_default_constant_1=1, some_default_constant_2=2 ): return some_default_constant_2 - some_default_constant_1 print( "Call function with 3 parameters, 2 defaulted, check they are used correctly:", defaultValueTest1a("ignored"), ) def defaultValueTest2(_no_default, some_default_variable=var_on_module_level * 2): return some_default_variable print( "Call function with 2 parameters, 1 defaulted with an expression, check its result", defaultValueTest2("ignored"), ) var_on_module_level = 2 print( "Call function with 2 parameters, 1 defaulted with an expression, values have changed since, check its result", defaultValueTest2("ignored"), ) def contractionTest(): j = 2 return [j + i for i in range(8)] print("Call function that returns a list contraction:", contractionTest()) def defaultValueTest3a( _no_default, funced_defaulted=defaultValueTest2(var_on_module_level) ): return [i + funced_defaulted for i in range(8)] print( "Call function that has a default value coming from a function call:", defaultValueTest3a("ignored"), ) def defaultValueTest3b( _no_default, funced_defaulted=defaultValueTest2(var_on_module_level) ): local_var = [funced_defaulted + i for i in range(8)] return local_var print( "Call function that returns a list contraction result via a local variable:", defaultValueTest3b("ignored"), ) def defaultValueTest3c( _no_default, funced_defaulted=defaultValueTest2(var_on_module_level) ): local_var = [[j + funced_defaulted + 1 for j in range(i)] for i in range(8)] return local_var print( "Call function that returns a nested list contraction with input from default parameter", defaultValueTest3c("ignored"), ) def defaultValueTest4(_no_default, funced_defaulted=lambda x: x**2): return funced_defaulted(4) print( "Call function that returns value calculated by a lambda function as default parameter", defaultValueTest4("ignored"), ) def defaultValueTest4a(_no_default, funced_defaulted=lambda x: x**2): c = 1 d = funced_defaulted(1) r = (i + j + c + d for i, j in zip(range(8), range(9))) l = [] for x in r: l.append(x) return l print( "Call function that has a lambda calculated default parameter and a generator expression", defaultValueTest4a("ignored"), ) def defaultValueTest4b(_no_default, funced_defaulted=lambda x: x**3): d = funced_defaulted(1) # Nested generators l = [] for x in ((d + j for j in range(4)) for i in range(8)): for y in x: l.append(y) return l print( "Call function that has a lambda calculated default parameter and a nested generator expression", defaultValueTest4b("ignored"), ) def defaultValueTest5(_no_default, tuple_defaulted=(1, 2, 3)): return tuple_defaulted print("Call function with default value that is a tuple", defaultValueTest5("ignored")) def defaultValueTest6( _no_default, list_defaulted=[1, 2, 3] ): # pylint: disable=dangerous-default-value return list_defaulted print("Call function with default value that is a list", defaultValueTest6("ignored")) x = len("hey") # TODO: Doesn't belong here. def in_test(a): # if 7 in a: # print "hey" # pylint: disable=pointless-statement 8 in a # @NoEffect 9 not in a # @NoEffect in_test([8]) try: in_test(9) except TypeError: pass def my_deco(function): def new_function(c, d): return function(d, c) return new_function @my_deco def decoriert(a, b): # pylint: disable=unused-argument def subby(a): return 2 + a return 1 + subby(b) print("Function with decoration", decoriert(3, 9)) def functionWithGlobalReturnValue(): global a # pylint: disable=global-statement return a a = "oh common" some_constant_tuple = (2, 5, 7) some_semiconstant_tuple = (2, 5, a) f = a * 2 print(defaultValueTest1("ignored")) # The change of the default variable doesn't influence the default # parameter of defaultValueTest2, that means it's also calculated # at the time the function is defined. module_level = 7 print(defaultValueTest2("also ignored")) def starArgTest(a, b, c): return a, b, c print("Function called with star arg from tuple:") star_list_arg = (11, 44, 77) print(starArgTest(*star_list_arg)) print("Function called with star arg from list:") star_list_arg = [7, 8, 9] print(starArgTest(*star_list_arg)) star_dict_arg = {"a": 9, "b": 3, "c": 8} print("Function called with star arg from dict") print(starArgTest(**star_dict_arg)) lambda_func = lambda a, b: a < b lambda_args = (8, 9) print("Lambda function called with star args from tuple:") print(lambda_func(*lambda_args)) print("Lambda function called with star args from list:") lambda_args = [8, 7] print(lambda_func(*lambda_args)) print("Generator function without context:") def generator_without_context_function(): gen = (x for x in range(9)) return tuple(gen) print(generator_without_context_function()) print("Generator function with 2 iterateds:") def generator_with_2_fors(): return tuple((x, y) for x in range(2) for y in range(3)) print(generator_with_2_fors()) def someYielder(): yield 1 yield 2 def someYieldFunctionUser(): print("someYielder", someYielder()) result = [] for a in someYielder(): result.append(a) return result print("Function that uses some yielding function coroutine:") print(someYieldFunctionUser()) def someLoopYielder(): for i in (0, 1, 2): yield i def someLoopYieldFunctionUser(): result = [] for a in someLoopYielder(): result.append(a) return result print("Function that uses some yielding function coroutine that loops:") print(someLoopYieldFunctionUser()) def someGeneratorClosureUser(): def someGenerator(): def userOfGeneratorLocalVar(): return x + 1 x = 2 yield userOfGeneratorLocalVar() yield 6 gen = someGenerator() return [next(gen), next(gen)] print( "Function generator that uses a local function accessing its local variables to yield:" ) print(someGeneratorClosureUser()) def someClosureUsingGeneratorUser(): offered = 7 def someGenerator(): yield offered return next(someGenerator()) print("Function generator that yield from its closure:") print(someClosureUsingGeneratorUser()) print("Function call with both star args and named args:") def someFunction(a, b, c, d): print(a, b, c, d) someFunction(a=1, b=2, **{"c": 3, "d": 4}) print("Order of evaluation of function and args:") def getFunction(): print("getFunction", end="") def x(y, u, a, k): return y, u, k, a return x def getPlainArg1(): print("getPlainArg1", end="") return 9 def getPlainArg2(): print("getPlainArg2", end="") return 13 def getKeywordArg1(): print("getKeywordArg1", end="") return "a" def getKeywordArg2(): print("getKeywordArg2", end="") return "b" getFunction()(getPlainArg1(), getPlainArg2(), k=getKeywordArg1(), a=getKeywordArg2()) print() def getListStarArg(): print("getListStarArg", end="") return [1] def getDictStarArg(): print("getDictStarArg", end="") return {"k": 9} print("Same with star args:") getFunction()(getPlainArg1(), a=getKeywordArg1(), *getListStarArg(), **getDictStarArg()) print() print("Dictionary creation order:") d = {getKeywordArg1(): getPlainArg1(), getKeywordArg2(): getPlainArg2()} print() print("Throwing an exception to a generator function:") def someGeneratorFunction(): try: yield 1 yield 2 except Exception: # pylint: disable=broad-except yield 3 yield 4 gen1 = someGeneratorFunction() print("Fresh Generator Function throwing gives", end="") try: print(gen1.throw(ValueError)), except ValueError: print("exception indeed") gen2 = someGeneratorFunction() print("Used Generator Function throwing gives", end="") next(gen2) print(gen2.throw(ValueError), "indeed") gen3 = someGeneratorFunction() print("Fresh Generator Function close gives", end="") print(gen3.close()) gen4 = someGeneratorFunction() print("Used Generator Function that mis-catches close gives", end="") next(gen4) try: print(gen4.close(), end="") except RuntimeError: print("runtime exception indeed") gen5 = someGeneratorFunction() print("Used Generator Function close gives", end="") next(gen5) next(gen5) next(gen5) print(gen5.close(), end="") def receivingGenerator(): while True: a = yield 4 yield a print("Generator function that receives", end="") gen6 = receivingGenerator() print(next(gen6), end="") print(gen6.send(5), end="") print(gen6.send(6), end="") print(gen6.send(7), end="") print(gen6.send(8)) print("Generator function whose generator is copied", end="") def generatorFunction(): yield 1 yield 2 gen7 = generatorFunction() next(gen7) gen8 = iter(gen7) print(next(gen8)) def doubleStarArgs(*a, **d): return a, d try: from UserDict import UserDict except ImportError: print("Using Python3, making own non-dict dict:") class UserDict(dict): pass print("Function that has keyword argument matching the list star arg name", end="") print(doubleStarArgs(1, **UserDict(a=2))) def generatorFunctionUnusedArg(_a): yield 1 generatorFunctionUnusedArg(3) def closureHavingGenerator(arg): def gen(_x=1): yield arg return gen() print("Function generator that has a closure and default argument", end="") print(list(closureHavingGenerator(3))) def functionWithDualStarArgsAndKeywordsOnly(a1, a2, a3, a4, b): return a1, a2, a3, a4, b l = [1, 2, 3] d = {"b": 8} print( "Dual star args, but not positional call", functionWithDualStarArgsAndKeywordsOnly(a4=1, *l, **d), ) def posDoubleStarArgsFunction(a, b, c, *l, **d): return a, b, c, l, d l = [2] d = {"other": 7, "c": 3} print("Dual star args consuming function", posDoubleStarArgsFunction(1, *l, **d)) for value in sorted(dir()): main_value = getattr(sys.modules["__main__"], value) if inspect.isfunction(main_value): print( main_value, main_value.__code__.co_varnames[: main_value.__code__.co_argcount], inspect.getargs(main_value.__code__), ) # # TODO: Make this work as well, currently disabled, because of nested arguments not # being compatible yet. # print inspect.getargspec( main_value ) # Python tests originally created or extracted from other peoples work. The # parts were too small to be protected. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.