Python functions (II): python Functions

Source: Internet
Author: User
Tags closure definition iterable

Python functions (II): python Functions

Continue to explain the function today:

Directory:

1. function object

2. Function nesting

3. namespace and scope

4. Closure

5. decorator

6. iterator

7. Generator

8. built-in functions

 

Part 1: Function objects

In python, everything is an object, such as int, str, list, dict, and tuple. Therefore, functions are no exception and objects have attributes. As an object, it can be assigned to other function names, or passed to other functions as parameters. The following is an example:

1 def foo (): 2 print ('hello, World') 3 4 # foo is just a function name, which points to foo () function Memory Address 5 6 bar = foo # assign the address of the foo () function to bar, then bar also points to the address of the foo () function 7 8 bar () 9 10 result: 11 hello, world

Let's look at another example. In this example, the function is passed as a parameter to other functions.

1 def test (func): 2 func () # Run the func function. 3 4 def hello (): 5 print ('hello, World') 6 7 test (hello) # pass a test function as a parameter. The result of 8 9 is 10 hello, world.
Part 2: function nesting:

Function Nesting is to define one or more functions within a function. When an external function is called, the external function then calls the internal function. Similar to the following:

1 def fun1 (): # define a function 2 a = 'txt '3 def fun2 (): # define another function in the original function, 4 print () 5 fun2 () 6 7 fun1 () 8 9 10 results: 11 txt

First, understand the definition method above. The nested function knowledge is used below.

Part 3: namespace and scope 1. namespace)

A namespace is the binding relationship between a variable name and a value. Python has three types of namespaces: Local namespaces, global namespaces, and built-in namespaces:

Local namespace: each function or class has its own namespace, which is called a local namespace. It is generated with the execution of the function and the call of the class instance, it is deleted after the function ends or the class instance ends. It includes function parameters and defined variables.

Global namespace: Each module has its own namespace. This is called a global namespace. It records the module variables, including function/class/other imported module/Module-level variables and constants

Built-in namespace: The namespace generated by running the python interpreter. All modules can be accessed. It stores built-in functions and some exceptions.

1 x = 5 2 y = 10 3 def change_x (): 4 x = 10 # create the variable x 5 def print_xy (): 6 print (x, y) in the local namespace) # First, find x in the local namespace of print_x. If not, search for x from the upper namespace. find y from the local namespace and cannot find the global namespace. 7 print_xy () 8 9 change_x () 10 print (x, y) # print x of the global namespace, from this we can see that the x of the local namespace does not overwrite the x11 12 # Result 13 10, or 10 in the global namespace.

 

From the above example, we can also find the order of variables in the namespace:

1. Now, you can find the local namespace variable. If it is found, use the variable to stop searching. If it is not found, search for the local namespace at the previous layer.

2. If the local namespace cannot be found, go to the global namespace search. If it is found, use it and stop searching. If it is not found, go to the built-in namespace search.

2. Scope:

There are two scopes:

Global scope: corresponding to the built-in namespace and global namespace

Local scope: corresponding to the local namespace

As mentioned above, the search sequence of variable names is: local namespace> global namespace> built-in namespace

We can use two built-in functions to view the variables in the scope: globals () and locals (). globals () can view the variables in the global scope, and locals () can view the variables in the local scope. The following is an example:

1 x = 1000 2 print (globals () 3 4 Results: 5 {'_ file _': 'd:/PycharmProjects/untitled8/user. py', 6' _ cached _ ': None, 7' _ loader _': <_ frozen_importlib_external.SourceFileLoader object at 0x00000000009D6CC0>, 8' _ doc __': none, 9' _ name _ ':' _ main _ ', 10' _ package _': None, 11' _ spec __': none, 12' _ builtins _ ': <module 'builtins' (built-in)>, # Here is the reference of the variable with built-in namespace 13 'X ': 1000 # The variable x declared in the global namespace can also be seen in 14}

 

The following is an example of locals:

1 x = 10002 def foo (): 3 x = 1004 print (locals () 5 6 foo () 7 8 # result 9 {'X ': 100} # only one variable declared in the local namespace

 

Variables declared in the global scope are globally valid and can be accessed at any location. Unless del is used to delete the variables, they remain alive. Once the file is executed, the python interpreter exits;

Variables declared in the local scope are locally valid and can only be accessed within the local scope. They are only valid after the function is called and expire after the function is called.

Part 4: Closure

Closure definition: an internal function contains an external scope rather than a reference to a global scope. This internal function is a closure:

1 x = 1000 # declare a global variable 2 def f1 (): 3 x = 10 # declare a local variable 4 def f2 (): # define a closure function 5 print (x) 6 return f2 # return the memory address of the f2 function 7 8 f = f1 () # assign the execution result of the f1 function to f. that is, both f and f1 point to the same memory address 9 print (f) 10 f () # Call function f, indirectly call function f2 () 11 12 # Result 13 <function f1. <locals>. f2 at 0x000000000000006ce1e0> # From this point, we can see the memory address of f2, the internal function of f1, which is also the address pointed by f 14 10

 

The object containing the _ closure _ method becomes a closure object. We can see it through the following example:

1 x = 2 2 def f1 (): 3 y = 2 4 def f2 (): 5 print (x, y) 6 return f2 7 f = f1 () 8 f () 9 print (f) # Return the content pointed to by f, that is, the memory address of the f2 () function 10 print (f. _ closure _) 11 print (dir (f. _ closure _ [0]) #__ closure _ returns the closure pointer 12 print (f. _ closure _ [0]. cell_contents) # cell_contents returns the closure Result 13 14 # result 15 2 216 <function f1. <locals>. f2 at 0x000000000000007de1e0> 17 (<cell at 0x000000000000007a5d38: int object at 0x00000000000052f301f0>,) 18 ['_ class _', '_ delattr __', '_ dir _', '_ doc _', '_ eq _', '_ format _', '_ ge __', '_ getattribute _', '_ gt _', '_ hash _', 20' _ init __', '_ le _', '_ lt _', '_ ne _', '_ new _', '_ reduce __', '_ performance_ex _', '_ repr _', '_ setattr _', '_ sizeof _', '_ str __',
22 '_ subclasshook _', 'cell _ contents '] 23 2

 

Part 5: decorator

Decorator concept: decorate other functions and modify the addition function. The decorator itself can be any callable object, and the decorated object is any callable object.

As shown in the following example, we have developed a function. Now we want to add a function to print the function running time when calling the function. The premise is that you cannot modify the previously written functions as follows:

1 import time 2 def timer (fun): # pass a function as a parameter 3 def wrapper (): # closure function wrapper 4 start_time = time. time () 5 res = fun () # Call the function and obtain the returned value 6 end_time = time. time () 7 print ('% s' % (end_time-start_time )) 8 return res # return the return value 9 return wrapper 10 11 @ timer # the function of this sentence is similar to this: index = wrapper (index) 12 def index (): 13 time. sleep (3) 14 print ('Welcome ') 15 return 116 17 res = index () 18 print (res) 19 20 21 result: 22 welcome23 3.01080536842346224 1

 

The above is an application of the decorator without parameters. When the original function "index ()" code is not changed, the time calculation function is implemented without affecting index () is very convenient. After reading the above example, we can figure out why the decorator is used: 1. Open and closed principle: the modification to the program is closed and the extension to the program is open; 2. the decorator adds new functions to the decorator without modifying the source code of the object to be decorated and calling the object at that time.

Let's take a look at the example below with a parameter modifier. This example adds the authentication function for the original function:

1 def check_auth (args, kwargs): # obtain the username/password from the db file. If the password is correct, True is returned, otherwise, False 2 res = [] 3 with open ('db', 'R', encoding = 'utf-8') as f: 4 res = f. read (). split () 5 for I in res: 6 if args [0] = I. split (',') [0] and args [1] = I. split (',') [1]: 7 return True 8 else: 9 return False10 11 12 def check_driver (driver = 'file'): # The decorator is made of three layers, because parameters are transferred when the decorator function is called, you need to add a layer 13 def auth (func) based on the original two-layer decorator ): # closure function 14 def wrapper (* args, ** kwa Rgs): # closure function. If the original function accepts the parameter, it passes the parameter to the closure function. * args, ** kwargs will find it from the global variable. 15 if driver = 'file': 16 result = check_auth (args, kwargs) 17 if result: # if the verification succeeds, allow the user 18 func (* args, ** kwargs) # Call the original function. 19 elif driver = 'mysql': 20 print ('=========== mysql ======= ') 21 elif driver = 'ldap ': # perform different operations based on the parameters obtained by the decorator. 22 print ('=========== ldap ======= ') 23 return wrapper24 return auth25 26 @ check_driver ('file') # parameters are added to the decorator. 27 def index (): 28 print ('Welcome % s your password is % s' % (name, password) 29 30 31 name = input ('input username :'). strip () 32 password = input ('input password :'). strip () 33 index (name, password) # function call is not changed

 

 

Part 6: iterator

The concept of an iterator: a repetitive process is called an iteration, and the result of each iteration is used as the next initial value. The focus is on repetition, and the results of this iteration are used as the initial values of the next iteration.

Let's take a look at an example of a convenient array:

1 a = ['A', 'B', 'C', 'D', 'E'] 2 3 for I in a: 4 print (I) 5 6 results: 7 a 8 B 9 c10 d11 e

 

The above is an iteration example. Read the content of list a repeatedly, and retrieve the number from the next part of the index to be read next time, and print it.

The following two concepts are introduced: iteratable objects and iterators.

Iteratable object: The object implementing the _ iter _ () method becomes an iteratable object, directed to list, tuple, dict

Iterator: the object implementing the _ iter _ () method and implementing the _ next _ () method is the iterator. Such as file

That is to say, the iterator must be an iteratable object, but the iteration object is not necessarily an iterator.

Since there are already iteratable objects used to iterate data, why is there an iterator? The answer is that for data types without indexes, an index-independent iteration method must be provided, that is, the next () method call described below.

The iteration object obtains an iterator by executing the _ iter _ () method:

1 a=list([1,2,3,4,5])2 b=a.__iter__()3 print(b.__next__())   #14 print(b.__next__())   #25 print(b.__next__())   #36 print(b.__next__())   #47 print(b.__next__())   #58 print(b.__next__())   #StopIteration

 

Run the _ iter _ () method on the list to generate an iterator. The iterator uses the _ next _ () method to obtain the next value, when the value in the iterator is obtained, a StopIteration exception is triggered when the value is obtained.

Are there any ready-made functions that indicate whether an object is an iteratable object or an Iterator, And the Iterable and Iterator methods of the collections module:

1 from collections import Iterable, Iterator2 a = list ([1, 2, 3, 4, 5]) # a is a list of 3 print (isinstance (a, Iterable )) # True4 print (isinstance (a, Iterator) # False5 f = open ('db', mode = 'R', encoding = 'utf-8 ') # f is a file object 6 print (isinstance (f, Iterator) # True7 print (isinstance (f, Iterable) # True8 f. close ()

 

In fact, the iterator has the following advantages and disadvantages:

Advantages: 1. Provides an iteration method that does not depend on the lower mark

2. For the iterator itself, it saves more memory because a single iteration value does not occupy a large amount of memory because the original object has a large number of values.

Disadvantages: 1. for objects with a lower mark (such as list and tuple), The iterator can only take the value of the lower mark once, and cannot take the value of the same lower mark multiple times. It is not as flexible as the value of the object of the sequence type.

2. The iterator cannot get the iterator object length.

Part 7: Generator

Concept: as long as the function body contains the yield keyword, this function is the generator function. The following is an example:

1 def foo (): 2 print ('one') 3 yield 1 4 print ('two') 5 yield 2 6 print ('Three ') 7 yield 3 8 print ('for') 9 yield 410 11g = foo () 12 next (g) # output one. After yield 1 is executed, print 'one', return 1, and then stop executing 13 print (next (g) # output two, output return value 2, stop again

 

 

 

The biggest difference between a generator and a common function is that the function is terminated immediately after the normal function executes return. The next time the function is called, it is called from the start part of the function, and the generator returns a value when it is executed to yield, download and call the function again. The function continues from the last stop.

Let's look at a fun example:

1 # output 9x9 multiplication table 2 def get_num (li): 3 for I in li: 4 for j in li: 5 if I! = J: 6 yield I, j 7 def shiqi (): 8 a = ['1', '2', '3', '4', '5 ', '6', '7', '8'] 9 new_num = [] 10 11 for I, j in get_num (a): 12 new_num.append (I + j) 13 print (new_num)
14 shiqi ()

 

 

 

To sum up:

Yield features:

1. encapsulate the _ inter _ and _ next _ methods for functions.

2. return can return only one value, and the function is terminated. The generator (yield) can return multiple values, and the function is paused every time it is returned, the next _ will resume execution from the last paused position

Part 8: built-in functions

Python built-in functions are as follows:

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.