python tutorial - Python Functions lambda - learn python - python programming




Functions lambda

  • Python supports the creation of anonymous functions (i.e. functions that are not bound to a name) at runtime, using a construct called lambda.
  • This is not exactly the same as lambda in functional programming languages such as Lisp, but it is a very powerful concept that's well integrated into Python and is often used in conjunction with typical functional concepts like filter(), map() and reduce().
  • Like def, the lambda creates a function to be called later. But it returns the function instead of assigning it to a name.
  • This is why lambdas are sometimes known as anonymous functions. In practice, they are used as a way to inline a function definition, or to defer execution of a code.
  • The following code shows the difference between a normal function definition, func and a lambda function, lamb:
>>> 
>>> def func(x): return x ** 3

>>> print(func(5))
125
>>> 
>>> lamb = lambda x: x ** 3
>>> print(lamb(5))
125
>>> 
click below button to copy the code. By Python tutorial team
  • As we can see, func() and lamb() do exactly the same and can be used in the same ways.
  • Note that the lambda definition does not include a return statement -- it always contains an expression which is returned.
  • Also note that we can put a lambda definition anywhere a function is expected, and we don't have to assign it to a variable at all.
  • The lambda's general form is :
lambda arg1, arg2, ...argN : expression using arguments
click below button to copy the code. By Python tutorial team
  • Function objects returned by running lambda expressions work exactly the same as those created and assigned by defs. However, there are a few differences that make lambda useful in specialized roles:
    • lambda is an expression, not a statement.
    • lambda's body is a single expression, not a block of statements.
  • lambda is an expression, not a statement.
    • Because of this, a lambda can appear in places a def is not allowed. For example, places like inside a list literal, or a function call's arguments.
    • As an expression, lambda returns a value that can optionally be assigned a name. In contrast, the def statement always assigns the new function to the name in the header, instead of returning is as a result.
  • lambda's body is a single expression, not a block of statements.
    • The lambda's body is similar to what we'd put in a def body's return statement. We simply type the result as an expression instead of explicitly returning it.
    • Because it is limited to an expression, a lambda is less general that a def. We can only squeeze design, to limit program nesting. lambda is designed for coding simple functions, and def handles larger tasks.
>>> 
>>> def f(x, y, z): return x + y + z

>>> f(2, 30, 400)
432
click below button to copy the code. By Python tutorial team
  • We can achieve the same effect with lambda expression by explicitly assigning its result to a name through which we can call the function later:
>>> 
>>> f = lambda x, y, z: x + y + z
>>> f(2, 30, 400)
432
>>> 
click below button to copy the code. By Python tutorial team
  • Here, f is assigned the function object the lambda expression creates. This is how def works, too. But in def, its assignment is an automatic must.
  • Default work on lambda arguments:
>>> mz = (lambda a = 'Wolfgangus', b = ' Theophilus', c = ' Mozart': a + b + c)
>>> mz('Wolfgang', ' Amadeus')
'Wolfgang Amadeus Mozart'
>>> 
click below button to copy the code. By Python tutorial team
  • In the following example, the value for the name title would have been passes in as a default argument value:
>>> def writer():
	title = 'Sir'
	name = (lambda x:title + ' ' + x)
	return name

>>> who = writer()
>>> who('Arthur Ignatius Conan Doyle')
'Sir Arthur Ignatius Conan Doyle'
>>> 
click below button to copy the code. By Python tutorial team

Why lambda ?

  • The lambdas can be used as a function shorthand that allows us to embed a function within the code.
  • For instance, callback handlers are frequently coded as inline lambda expressions embedded directly in a registration call's arguments list.
  • Instead of being define with a def elsewhere in a file and referenced by name, lambdas are also commonly used to code jump tables which are lists or dictionaries of actions to be performed on demand.
>>> 
>>> L = [lambda x: x ** 2,
         lambda x: x ** 3,
         lambda x: x ** 4]
>>> for f in L:
	print(f(3))

	
9
27
81
>>> print(L[0](11))
121
>>> 
click below button to copy the code. By Python tutorial team
  • In the example above, a list of three functions was built up by embedding lambda expressions inside a list.
  • A def won't work inside a list literal like this because it is a statement, not an expression.
  • If we really want to use def for the same result, we need temporary function names and definitions outside:
>>> 
>>> def f1(x): return x ** 2

>>> def f2(x): return x ** 3

>>> def f3(x): return x ** 4

>>> # Reference by name
>>> L = [f1, f2, f3]
>>> for f in L:
	print(f(3))

	
9
27
81
>>> print(L[0](3))
9
>>> 
click below button to copy the code. By Python tutorial team
  • We can use dictionaries doing the same thing:
    • >>> key = 'quadratic' >>> {'square': (lambda x: x ** 2), 'cubic': (lambda x: x ** 3), 'quadratic': (lambda x: x ** 4)}[key](10) 10000 >>>
    • Here, we made the temporary dictionary, each of the nested lambdas generates and leaves behind a function to be called later. We fetched one of those functions by indexing and the parentheses forced the fetched function to be called.
  • Again, let's do the same thing without lambda.
>>> 
>>> def f1(x): return x ** 2

>>> def f2(x): return x ** 3

>>> def f3(x): return x ** 4

>>> key = 'quadratic'
>>> {'square': f1, 'cubic': f2, 'quadratic': f3}[key](10)
10000
>>> 
click below button to copy the code. By Python tutorial team
  • This works but our defs may be far away in our file. The code proximity that lambda provide is useful for functions that will only be used in a single context.
  • Especially, if the three functions are not going to be used anywhere else, it makes sense to embed them within the dictionary as lambdas.
  • Also, the def requires more names for these title functions that may cause name clash with other names in this file.
  • If we know what we're doing, we can code most statements as expressions:
>>> 
>>> min = (lambda x, y: x if x < y else y)
>>> min(101*99, 102*98)
9996
>>> min(102*98, 101*99)
9996
>>> 
click below button to copy the code. By Python tutorial team
  • If we need to perform loops within a lambda, we can also embed things like map calls and list comprehension expressions.
>>> import sys
>>> fullname = lambda x: list(map(sys.stdout.write,x))
>>> f = fullname(['Wassily ', 'Wassilyevich ', 'Kandinsky'])
Wassily Wassilyevich Kandinsky
>>>
>>> 
>>> fullname = lambda x: [sys.stdout.write(a) for a in x]
>>> t = fullname(['Wassily ', 'Wassilyevich ', 'Kandinsky'])
Wassily Wassilyevich Kandinsky
>>> 
click below button to copy the code. By Python tutorial team
  • Here is the description of map built-in function.
  • map(function, iterable, ...)
  • Return an iterator that applies function to every item of iterable, yielding the results.
  • If additional iterable arguments are passed, function must take that many arguments and is applied to the items from all iterables in parallel.
  • With multiple iterables, the iterator stops when the shortest iterable is exhausted.
  • So, in the above example, sys.stdout.write is an argument for function, and the x is an iterable item, list, in the example.

Nested lambda

  • In the following example, the lambda appears inside a def and so can access the value that the name x has in the function's scope at the time that the enclosing function was called:
>>> def action(x):
	# Make and return function, remember x
	return (lambda newx: x + newx)

>>> ans = action(99)
>>> ans
<function <lambda> at 0x0000000003334648>
>>> ans(100)
199
>>> 
click below button to copy the code. By Python tutorial team
  • Though not clear in this example, note that lambda also has access to the names in any enclosing lambda. Let's look at the following example:
>>> 
>>> action = (lambda x: (lambda newx: x + newx))
>>> ans = action(99)
>>> ans
<function <lambda> at 0x0000000003308048>
>>> ans(100)
199
>>> 
>>> (  (lambda x: (lambda newx: x + newx)) (99)) (100)
199
click below button to copy the code. By Python tutorial team
  • In the example, we nested lambda structure to make a function that makes a function when called. It's fairly convoluted and it should be avoided.

lambda and sorted()

  • Here is a simple example of using lambda with built-in function sorted():
sorted(iterable[, key][, reverse])
click below button to copy the code. By Python tutorial team
  • The sorted() have a key parameter to specify a function to be called on each list element prior to making comparisons.
>>> death = [
    ('James', 'Dean', 24),
    ('Jimi', 'Hendrix', 27),
    ('George', 'Gershwin', 38),
]
>>> sorted(death, key=lambda age: age[2])
[('James', 'Dean', 24), ('Jimi', 'Hendrix', 27), ('George', 'Gershwin', 38)]
click below button to copy the code. By Python tutorial team
  • In this example, we want to read a video file and sort the packet in the order of starting time stamp. Also, we want to count the number of chunks.
#!/usr/bin/python
import psutil
import simplejson
import subprocess

procs_id = 0
procs = {}
procs_data = []

def getMetadata(video):
    cmd = ['ffprobe', '-show_streams', '-show_packets', '-print_format', 'json', video]
    print 'cmd=', cmd
    stdout = runCommand(cmd, return_stdout = True, busy_wait = False)
    data = simplejson.loads(stdout)
    metadata = { }

    if data:
        # Obtain duration here
        if 'streams' in data:
            for item in data['streams']:
                if 'codec_type' in item and 'duration' in item and 'video' in item['codec_type']:
                    metadata['duration'] = float(item['duration'])
        else:
            metadata['duration'] = float(0)

        # Obtain iframes here
        iframes = []
        if 'packets' in data:
            # Filter out packet types
            video_packets = sorted(
                [packet for packet in data['packets'] if (packet['codec_type'] == "video" and 'pos' in packet)],
                key = lambda packet: int(packet['pos'])
            )
            video_positions = sorted([int(packet['pos']) for packet in video_packets])
            audio_packets = sorted(
                [packet for packet in data['packets'] if (packet['codec_type'] == "audio" and 'pos' in packet)],
                key = lambda packet: int(packet['pos']))
            audio_positions = sorted([int(packet['pos']) for packet in audio_packets])

            # Search for iframes
            iframe_packets = [packet for packet in video_packets if (packet['flags'] == "K")]
            positions = sorted([int(packet['pos']) for packet in data['packets'] if ('pos' in packet)])

            start_byte = 0
            end_byte = 0
            duration = None

            for iframe in iframe_packets:
                start_byte = int(iframe['pos'])
                end_byte = 0

                for pos in positions:
                    if pos > start_byte:
                        end_byte = pos - 188
                        break

                if duration is None:
                    duration = float(iframe['pts_time'])
                else:
                    new_duration = float(iframe['pts_time'])
                    iframes.append({ 'byte_start': start_byte,
                                     'byte_end': end_byte,
                                     'duration': (new_duration - duration) })
                    duration = new_duration

            last_duration = float(video_packets[-1]['pts_time'])
            iframes.append({ 'byte_start': start_byte,
                             'byte_end': end_byte,
                             'duration': last_duration - duration })
        metadata['iframes'] = iframes
        print 'metadata=',metadata

    return metadata


# Runs command silently
def runCommand(cmd, use_shell = False, return_stdout = False, busy_wait = True, poll_duration = 0.5):
    # Sanitize cmd to string
    cmd = map(lambda x: '%s' % x, cmd)
    if use_shell:
        command = ' '.join(cmd)
    else:
        command = cmd

    if return_stdout:
        proc = psutil.Popen(cmd, shell = use_shell, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    else:
        proc = psutil.Popen(cmd, shell = use_shell, 
                                stdout = open('/dev/null', 'w'),
                                stderr = open('/dev/null', 'w'))


    global procs_id 
    global procs
    global procs_data
    proc_id = procs_id
    procs[proc_id] = proc
    procs_id += 1
    data = { }

    while busy_wait:
        returncode = proc.poll()
        if returncode == None:
            try:
                data = proc.as_dict(attrs = ['get_io_counters', 'get_cpu_times'])
            except Exception, e:
                pass
            time.sleep(poll_duration)
        else:
            break

    (stdout, stderr) = proc.communicate()
    returncode = proc.returncode
    del procs[proc_id]

    if returncode != 0:
        raise Exception(stderr)
    else:
        if data:
            procs_data.append(data)
        return stdout
    
if __name__ == '__main__':

    segMeta = getMetadata('bunny_400.ismv')
    print 'segMeta=',segMeta
    for k in segMeta.keys():
        if(k == 'iframes'):
	    print 'iframe size =',len(segMeta[k])
            break
click below button to copy the code. By Python tutorial team
  • After reading in the video using ffprobe, the data looks like this:
{
    "packets": [
        {
            "codec_type": "video",
            "stream_index": 0,
            "pts": 0,
            "pts_time": "0.000000",
            "dts": 0,
            "dts_time": "0.000000",
            "size": "847",
            "pos": "2927",
            "flags": "K"
        },
        {
            "codec_type": "video",
            "stream_index": 0,
            "pts": 1200000,
            "pts_time": "0.120000",
            "dts": 1200000,
            "dts_time": "0.120000",
            "size": "486",
            "pos": "3804",
            "flags": "_"
        },
        ........
    ],
    "streams": [
        {
            "index": 0,
            "codec_name": "h264",
            "codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
            "profile": "High",
            "codec_type": "video",
            "codec_time_base": "1/50",
            "codec_tag_string": "avc1",
            "codec_tag": "0x31637661",
            "width": 288,
            "height": 160,
            "has_b_frames": 2,
            "sample_aspect_ratio": "80:81",
            "display_aspect_ratio": "16:9",
            "pix_fmt": "yuv420p",
            "level": 13,
            "r_frame_rate": "25/1",
            "avg_frame_rate": "0/0",
            "time_base": "1/10000000",
            "start_pts": 0,
            "start_time": "0.000000",
            "duration_ts": 5964400000,
            "duration": "596.440000",
            "bit_rate": "400074",
            "nb_read_packets": "14911",
            "disposition": {
                "default": 1,
                "dub": 0,
                "original": 0,
                "comment": 0,
                "lyrics": 0,
                "karaoke": 0,
                "forced": 0,
                "hearing_impaired": 0,
                "visual_impaired": 0,
                "clean_effects": 0,
                "attached_pic": 0
            },
            "tags": {
                "language": "und",
                "handler_name": "VideoHandler"
            }
        }
    ]
}
click below button to copy the code. By Python tutorial team

Output

cmd= ['ffprobe', '-show_streams', '-show_packets', '-print_format', 'json', 'video.dat']
metadata= {
'duration': 596.44, 
'iframes': [
{'duration': 10.0, 'byte_end': 399823, 'byte_start': 377082}, 
{'duration': 10.0, 'byte_end': 998254, 'byte_start': 984197}, 
{'duration': 10.0, 'byte_end': 1833216, 'byte_start': 1804498}, 
{'duration': 10.0, 'byte_end': 2591816, 'byte_start': 2569925},
....
{'duration': 10.0, 'byte_end': 29431348, 'byte_start': 29422617}, 
{'duration': 10.0, 'byte_end': 29633871, 'byte_start': 29633940}, 
{'duration': 10.0, 'byte_end': 29801180, 'byte_start': 29793525}, 
{'duration': 6.399999999999977, 'byte_end': 29801180, 'byte_start': 29793525}]}
iframe size = 60

Related Searches to Python Functions lambda