Encapsulation of functions

Asked

Viewed 113 times

1

Below is an example of using a function passed as a parameter to another function:

def gera_nums():
    lista = []
    for c in range(0, randint(1, 15)):
        lista.append(randint(0, 100))
    return lista


def extrai_maior(array):
    print(f'Os números passados foram: {array}')
    print(f'Foram passados {len(array)} números como parâmetro!')
    print(f'O maior número passado foi o {max(array)}.')


extrai_maior(gera_nums())

Basically the first function generates a number x random (up to 14 numbers) of random numbers (between 0 and 99) and returns a list. This function is passed as parameter to the function extrai_maior that analyzes the list and passes some information.

Considering that the first will only be used with the second, it’s pertinent to encapsulate the first within the second, right? What would that code look like? I’m not being able to apply it.

PS: The use of lambda in this case is impractical because it would not be possible to transform the first function into inline function, right?

2 answers

6

No, this is not an example of using a function passed as a parameter to another function.

When does...

extrai_maior(gera_nums())

... it’s actually just passing by the result of function gera_nums() as a parameter for the function extrai_maior() because when you put the () the front of the function name you are running it.

So that function gera_nums() is passed as parameter to function extrai_maior must be modified to receive a function and call within your body:

from random import randint

# Simplificando a função gera_nums utilizando list comprehension
gera_nums = lambda: [randint(0, 100) for c in range(0, randint(1, 15))]

#Função prepara para receber outra função pelo parâmetro f
def extrai_maior(f):
    array = f() # aqui chama o parâmetro como uma função
    print(f'Os números passados foram: {array}')
    print(f'Foram passados {len(array)} números como parâmetro!')
    print(f'O maior número passado foi o {max(array)}.')

#Agora gera_nums é passada como parâmetro
extrai_maior(gera_nums)

Another possibility is to create a developer, see How Python Decorators Work?:

from random import randint


gera_nums = lambda: [randint(0, 100) for c in range(0, randint(1, 15))]

def extrai_maior(f):
    #array = f() #se chamar f() aqui você cria um closure e o decorator sempre retornará o mesmo valor
    #cria um decorator
    def deco():
      array = f() # aqui chama o parâmetro como uma função
      print(f'Os números passados foram: {array}')
      print(f'Foram passados {len(array)} números como parâmetro!')
      print(f'O maior número passado foi o {max(array)}.')
    return deco #retorna o decorator

#aplica o decorator
gera_nums = extrai_maior(gera_nums)

#Poderia ser usado o açúcar sintático @ mas a função gera_nums() teria que ser movida e modificada
#@extrai_maior
#def gera_nums(): 
#return (lambda: [randint(0, 100) for c in range(0, randint(1, 15))])()

#evoca a função decorada
gera_nums()
  • Class! But I do not know if I understood the part of the developer, I am not properly initiated in this concept, although I have read about. Can you explain me in a synthetic way? I will search for content in parallel to exchange better. Thank you!

  • 1

    @dev.Curi About decorators, you can start here: https://answall.com/q/23628/112052

3

When you say "encapsulate function," I believe you’re talking about nested functions. To do this, just put your function gera_nums() inside extrai_maior() and define the so-called function within the second function.

See below how the code would look:

def extrai_maior():

    def gera_nums():
        lista = []

        for c in range(0, randint(1, 15)):
            lista.append(randint(0, 100))
        return lista

    array = gera_nums()

    print(f'Os números passados foram: {array}')
    print(f'Foram passados {len(array)} números como parâmetro!')
    print(f'O maior número passado foi o {max(array)}.')

extrai_maior()

If I may say so, I don’t think it’s right in this case that you leave the function gera_nums inside extrai_maior. First because it wouldn’t make sense to name the function in that code. Imagine... would it be to extract larger than ? It makes no sense, since the array is already generated within the function.

Second, you could not get the list to be used elsewhere, since the function gera_nums exists only in the scope of the function extrai_maior. So if you wanted to use the array in a function extrai_menor for example, you should create another function gera_nums, creating unnecessary lines and polluting your code.

In your case, I think the code you made was the best option.


Now answering your other question, it would really be impossible to create all the code using only lambda, but it is possible to create the function gera_nums in a single line. See how it would look:

gera_nums = lambda: [randint(0, 100) for c in range(0, randint(1, 5))]

In this code above, I needed to use beyond the lambda one list comprehensions.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.