Anonüümne funktsioon (lambda)

Tavalise funktsiooni deklareerimine algab funktsiooni nime määramisest (Funktsiooni mõiste ja kasutamine).

def name_of_the_func(params):
    # Some code here
    return [expression]

Sama funktsioon võib olla kirja pandud ilma nimeta, kasutades nn anonüümset funktsiooni, mille võtmesõnaks on lambda. Anonüümne funktsioon on funktsioon, millel on alati mingi tagastatav väärtus ja puudub nimi.

lambda params: [expression]

Eeldame, et meil on vaja funktsiooni, mis arvutab ette antud arvu x jaoks antud valemi arvulise väärtuse: x ** 2 + 15 * sqrt(x).

# no pec # You can also edit the code from math import * def solve_some_math(x: int) -> float: return x ** 2 + 15 * sqrt(x) print(solve_some_math(9)) # --> 126.0 # Anonymous function equivalent to the function above would be func = lambda x: x ** 2 + 15 * sqrt(x) print(func(9)) # --> 126.0

Või näiteks tahame koostada funktsiooni, mis võtab ette mingi sõne (Sõne (string)) ja tagastab sama sõne, kuid esimene täht on asendatud viimase tähega, ja viimane esimesega. Sõne peab seetõttu koosnema vähemalt kahest tähest.

Meie lambda näeks sel juhul välja selline:

lambda word: [ perform charswap ] if [ condition ] else [ return something else ]

# If given word length is greater than one --> if len(word) > 1
# Perform char swap --> word[len(word) - 1] (last char) + word[1:len(word) - 1] (word body) + word[0] (first char)
# Else return initial word

func = lambda word: word[len(word) - 1] + word[1:len(word) - 1] + word[0] if len(word) > 1 else word

print(func("word"))  # --> dorw
print(func("Lambda"))  # --> aambdL
print(func(""))  # --> ""
print(func("a"))  # --> a

# The trivial representation of this algorithm would be
def char_swap(word: str) -> str:
    if len(word) > 1:
        return word[len(word) - 1] + word[1:len(word) - 1] + word[0]
    return word

Tip

Aga anonüümse funktsiooni kasutamine sellistes näidetes väga mõttekas ei ole, kuna antud juhtudel ei ole vahet, kas kasutada tavalist või lambda funktsiooni (mõlemad võtavad sama palju ruumi ja mõlemad on sama lihtsad).

Ikkagi mõnedel juhtudel teeb lambda funktsioonide kasutamine koodi kirjutamise lihtsamaks ja kiiremaks. Tavaliselt kasutatakse seda koos sisseehitatud meetoditega map(), filter() ja reduce(). Neid nimetatakse funktsionaalse programmeerimise elementideks.

filter()

Meetod filter() on kõige lihtsam. Antud meetod võtab ette kaks argumenti - filtreerimise kriteerium, mis on funktsioon, ja andmekogum, kust me võtame väärtused filtreerimiseks. Meetod loob uut järjendit elementidest, millele kehtib määratud kriteerium. Ilma lambda-ta näeb see välja nii:

# Data to filter
input_list = [10, 27, 56, 90]

# Defining filtering criteria
def filter_criteria(number: int) -> int:
    # We only need numbers that are divisible by 2
    return number % 2 == 0

# Filtering out the values we need, outcome is <filter> object
filtered = filter(filter_criteria, input_list)

# Converting the <filter> object to list and printing its contents
print(list(filtered))  # --> [10, 56, 90]

Olgu meil antud järjend suvaliste numbritega. Meie tahame sellest järjendist saada ainult need numbrid, mis jaguvad 3-ga või 5-ga. Triviaalseks lahenduseks on for-each tsükkel (Tsükkel (loop)):

def get_specific_nums(nums: list) -> list:
    # Declaring an empty list
    specific_nums = []
    # For each number in given list
    for number in nums:
        # Check if number is divisible by 3 OR by 5
        if number % 3 == 0 or number % 5 == 0:
            # Add to a new list
            specific_nums.append(number)

    return specific_nums

print(get_specific_nums([1, 3, 14, 27, 15, 100, 151, 9, 2]))  # --> [3, 27, 15, 100, 9]

Tundub päris mahukas. Ja nüüd teeme sama asja kasutades lambda-t ja meetodit filter():

# no pec # Initial list nums = [1, 3, 14, 27, 15, 100, 151, 9, 2] # Filtering out the values we need, outcome is object filtered = filter(lambda x: x % 3 == 0 or x % 5 == 0, nums) # Converting the object to list and printing its contents print(list(filtered)) # --> [3, 27, 15, 100, 9]

Ehk seitsmest koodireast saime kolm, mis on juba tunduvalt lühem. Tegelikult saab need kolm rida veel korra kokku panna, ja saaksime vaid kaks rida koodi:

# no pec nums = [1, 3, 14, 27, 15, 100, 151, 9, 2] print(list(filter(lambda x: x % 3 == 0 or x % 5 == 0, nums))) # --> [3, 27, 15, 100, 9]

Juba palju parem, eks? Lühike ja ilus lahendus meie probleemile. Veel üks näide:

# no pec words = ["lambdas", "are", "cool", "but", "such", "code", "may be", "difficult", "to read"] # Filtering words by length filtered = filter(lambda word: 6 > len(word) > 3, words) print(list(filtered)) # --> ['cool', 'such', 'code'] # Or print(list(filter(lambda word: 6 > len(word) > 3, words))) # --> ['cool', 'such', 'code']

map()

Meetod map() teostab mingit kasutaja poolt määratud tehet igale elemendile algsest andmekogumist. Näiteks on meil järjend numbritest ja me tahame saada sellest uut järjendit, kus iga uus number võrdub algse järjendi numbri ruuduga:

# Data to change
input_list = [1, 2, 3, 4]

# Defining changing method
def change_method(number: int) -> int:
    # Return the same number squared
    return number ** 2

# Changing the values in input_list, outcome is <map> object
mapped = map(change_method, input_list)

# Converting the <map> object to list and printing its contents
print(list(mapped))  # --> [1, 4, 9, 16]

Ja kasutades lambda-t:

# no pec input_list = [1, 2, 3, 4] mapped = map(lambda number: number ** 2, input_list) print(list(mapped)) # --> [1, 4, 9, 16]

Veel üks näide:

# no pec # Data to change input_list = ["Clean", "code", "is", "good", "code"] # Changing the values in input_list, outcome is object # Replacing word "is" to "=" mapped = map(lambda word: "=" if word == "is" else word, input_list) # Converting the object to list and joining contents to string print(" ".join(list(mapped))) # --> Clean code = good code # Or ... (isn't quite clean code though) print(" ".join(list(map(lambda word: "=" if word == "is" else word, input_list)))) # --> Clean code = good code
# Trivial solution would be
def change_element(elements_list):
    result = []
    for word in elements_list:
        if word == "is":
            result.append("=")
        else:
            result.append(word)
    return " ".join(result)

print(change_element(["Clean", "code", "is", "good", "code"]))  # --> Clean code = good code
# Or using the built-in replace() method
print(" ".join(input_list).replace("is", "="))  # --> Clean code = good code

Rohkem lugemist