Showing posts with label closure. Show all posts
Showing posts with label closure. Show all posts

Jan 21, 2019

Python Local Vs Global

#########################
#   Global Scope Vs Enclosing Scope Vs Local Scope 
#   LEGB rule
#   Local(L): Defined inside function/class
#   Enclosed(E): Defined inside enclosing functions(Nested function concept)
#   Global(G): Defined at the uppermost level
#   Built-in(B): Reserved names in Python builtin modules
#########################

message = 'global'

def enclosing():
    message = 'enclosing'
    def local():
        message = 'local'
    print('enclosing message: ', message)   # enclosing
    local()
    print('enclosing message: ', message)   # enclosing


def enclosing_nonlocal():
    message = 'enclosing'
    def local():
        nonlocal message    # This refers to the above message in enclosing scope, not in global scope
        message = 'local'
    print('enclosing message: ', message)   # enclosing
    local()
    print('enclosing message: ', message)   local


def enclosing_global():
    message = 'enclosing'
    def local():
        global message
        message = 'local'  # Here you are updating message in global scope, not in enclosing scope
    print('enclosing message: ', message)   enclosing
    local()
    print('enclosing message: ', message)    enclosing 


if __name__ == '__main__':
    print('------------------------------------')
    print('global message: ', message)
    enclosing()
    print('global message: ', message)
    print('----------------NONLOCAL------------------')
    print('global message: ', message)
    enclosing_nonlocal()
    print('global message: ', message)
    print('----------------GLOBAL--------------------')
    print('global message: ', message)
    enclosing_global()
    print('global message: ', message)
    print('------------------------------------')

"""
Output:

------------------------------------
global message:  global
enclosing message:  enclosing
enclosing message:  enclosing
global message:  global
----------------NONLOCAL------------------
global message:  global
enclosing message:  enclosing
enclosing message:  local
global message:  global
----------------GLOBAL--------------------
global message:  global
enclosing message:  enclosing
enclosing message:  enclosing
global message:  local
------------------------------------

"""

Python Closure

#########################
# Closure in Python
# A nested function references a value in its enclosing scope.
# We should have a nested function (function within a function).
# The nested function should refer to a value defined in the enclosing function.
# The enclosing function must return the nested function.
# Closures are used as callback functions, this helps in data hiding. This helps to reduce the use of global variables.
# When we have few functions in our code, closures are helpful. But if we have many functions, then we may go for a class
#########################

# Nested Function
# inner_function() can easily be accessed inside the outer_function body but not outside of it’s body.
# Hence, inner_function() is treated as nested Function which uses text as non-local variable.
def outer_function(text):
    text = text
    def inner_function():
        print(text)
    inner_function()


# A closure — unlike a plain function as above — allows the function to access those enclosed captured variables through
# the closure’s copies of their values or references, even when the function is invoked outside their scope.
def closure_outer_function(text):
    text = text
    def closure_inner_function():
        print(text)
    return closure_inner_function  # without parentheses() / callback function


def enclosed_function(x):
    print('In enclosed_function: ' + str(x))

    def nested_function(y):
        print('###')
        print('In nested_function x : ' + str(x))
        print('In nested_function y : ' + str(y))

    return nested_function    # without parentheses() / callback function


if __name__ == '__main__':
    print('------------------------------------------------------')
    outer_function('Hi Nested Function')
    print('------------------------------------------------------')
    func_obj = closure_outer_function('Hi Closure')
    func_obj()
    print('------------------------------------------------------')
    func_obj = enclosed_function(100)
    print('After calling enclosed_function')
    func_obj(111)
    print('------------------------------------------------------')


"""
------------------------------------------------------
Hi Nested Function
------------------------------------------------------
Hi Closure
------------------------------------------------------
In enclosed_function: 100
After calling enclosed_function
###
In nested_function x : 100
In nested_function y : 111
------------------------------------------------------
"""


Jun 22, 2008

Closure in Perl

What is closure?

- Anonymous subroutines (subroutines without name) act as closures with respect to my() variables ie., lexical variables.

- Closure says if you define an anonymous function in a particular lexical
context, it pretends to run in that context even when it's called outside of
the context.

Example:
########

#!F:\Perl\bin\perl -w
use strict;

sub newprint {
   my $x = shift; # 'x' is a lexical variable
   return sub { my $y = shift; print "$x, $y!\n"; }; #Anonymous subroutine, observe $x
}
my $h = newprint("Howdy");
my $g = newprint("Greetings");

&$h("world"); # Howdy world
&$g("earthlings"); # Greetings earthlings


Note particularly that $x continues to refer to the value passed into
newprint() despite the fact that the my $x has seemingly gone out of
scope by the time the anonymous subroutine runs. That's what closure is all
about.

This applies only to lexical variables, by the way. Dynamic variables
continue to work as they have always worked. Closure is not something that
most Perl programmers need trouble themselves about to begin with.


One More Example on Closure:
##########################

- The important thing about closures is that you can use them to hide different lexicals into seperate
references to the same subroutine.

- I think that the important thing about closures is being able to call the same code but have it use different
variables (without passing them in as arguments).


use strict;
sub make_hello_printer {
  my $message = "Hello, world!";
  return sub { print $message; }
}

my $print_hello = make_hello_printer();
$print_hello->()



As you'd expect, that prints out the Hello, world! message. Nothing special going on here, is there? Well,

actually, there is. This is a closure. Did you notice?

What's special is that the subroutine reference we created refers to a lexical variable called $message. The

lexical is defined in make_hello_printer, so by rights, it shouldn't be visible outside of make_hello_printer,

right? We call make_hello_printer, $message gets created, we return the subroutine reference, and then

$message goes away, out of scope.

Except it doesn't. When we call our subroutine reference, outside of make_hello_printer, it can still see and

receive the correct value of $message. The subroutine reference forms a closure, ``enclosing'' the lexical

variables it refers to.


One More Example on Closure:
##########################

#!F:\Perl\bin\perl -w
use strict;

sub make_counter {
my $start = shift;
return sub { $start++ }
}

my $from_ten = make_counter(10);
my $from_three = make_counter(3);
print $\ = "\n"; # Prints new line each and every print
print $from_ten->(); # 10
print $from_ten->(); # 11
print $from_three->(); # 3
print $from_ten->(); # 12
print $from_three->(); # 4