Python Cookbook Third Edition study note nine: functions

Source: Internet
Author: User
Tags hypot

A function that accepts any number of arguments . When the number of arguments passed in a function is large, you do not need to define a variable for each parameter when the function is defined, and you can use *rest to include extra arguments. 
As the following code,*rest contains the  3 parameters of 2,3,4. And can iterate over the access. In this example,rest is actually a tuple of other positional parameters   
AVG (first,*rest):
Rest
I
average= (first+sum(rest))/(1+len(rest))
Average
AVG (1,2,3,4)
If we need to pass a parameter with a keyword: You can use the following method. When using **attr,attr is actually a dictionary that contains all the keyword arguments that are passed in. 
AVG (first, **attr):
Attr.items ():
item,attr[item[0]]
AVG (1,size=' Large ',quantity=0)    
The results are as follows:
E:\python2.7.11\python.exe e:/py_prj/python_cookbook.py
(' quantity ', 0) 0
(' Size ', ' large ') large
If you want to force certain parameters to be passed with a keyword argument, you can put the Mandatory keyword argument after the * parameter or a single * 
Lambda:
In the C language, for some short implementations. It can be implemented without a function but by writing a macro. 
For example #define m (y) Y*y+3*y then m (5) The end result is 5*5+3*5=40  
there is a similar implementation in Python, which is Lambada. The code below is the Lambda that implements an addition  .
add=x,y:x+y
Add (3,4)
Let's look at the following example:
We want to sort the names in name by last name. specifying The key value in sorted is also the basis for sorting. Here, use Lambda name:name.split () [ -1].lower () to extract the surname of each name, and then assign a value to the key    
name=[' David Beazley ',' Brains Jones ',' Raymond hettinger ',' Ned Batchelder ']
ret=Sorted(name,key=name:name.split () [-1].lower ())
Ret
Take a look at a more interesting example:
X=10
A=y:y+x
x=20
b=y:y+x
A (ten)
B (ten)
What are the values of the above code A (10) and B (10),20 and 30? Intuitively, it's true, but it turns out to be 30 and 30. Let's take a single-step run:     
After first running thea=y:y+x, the corresponding x=10
After running the b=y:y+x, the corresponding x=20 

This is done to print a (10). This time jumps to a=Lambda y:y+x at this time of x=20, so A (10) is equal to 20+10=30

As can be seen from the above example, although we define the value of x before lambda. But the final value is not binding when it is defined, but only when the actual lambda is running. When the lambda is actually running the print a (10), the value of x has been assigned to 20.
If you want the parameter to be fixed when the lambda is defined, you need to set the value of the parameter when you define it.
A=y,x=x:y+x
Set x=x in lambda so that the value of X is bound to 10.
This is particularly error-prone when the list is deduced. As in the following code. What we expect to get is 0,1,2,3,4.
fun=[Range (5)]
Fun
F (0)
But the end result is 4,4,4,4,4. For the same reason as before, N is 4 when called.
Change to the following code, the value of n can be bound each time.
fun=[Range (5)]
Partial use:
If the function has too many parameter values, partial can fix the value of one or more parameters, and can reduce the number of arguments called when called. As in the following code. Fixed d=3, only need to set the value of A,b,c when calling
Spam (A,b,c,d):
A,b,c,d
S1=partial (spam,d=3)
S1 (0,1,2)
To see a practical example, suppose you have a list of points to represent (x, y) coordinate tuples. You can use the following function to implement the
points=[, (3,4), (5,6), (7,6)]
Distance (P1,P2):
X1,y1=p1
X2,y2=p2
Math.hypot (X2-X1,Y2-Y1)
But if we want to calculate the distance to a base point and sort it based on that distance. How to do it. We talked about the use of lambda before. We can do this with lambda, the code is
points=[, (3,4), (5,6), (7,6)]
Pt= (4,3)
ret=sorted (points,key=points:math.hypot (pt[0]-points[0],pt[1]-points[1]))
Ret
Slightly redundant with Lambda implementations. Partial can streamline the code. Here we will pin the second parameter p2 of Distance to Pt. So when it's called, it doesn't actually
Ret=sorted (Points,key=partial (DISTANCE,PT))
Ret
This is actually the following style when calling:
Distance ((), (4,3))
Distance ((3,4), (4,3))
Distance ((5,6), (4,3))
Distance ((7,6), (4,3))
callback function:
The callback function is used frequently in C, simply by passing the pointer address of the callback function as a parameter, and that function takes advantage of the passed address callback function when it needs to be used. You can then take advantage of this opportunity to process or complete the operation in the callback function.
For example, the following C language code. The address of the Printwelcome is passed to (*print) (int). In callback, you can call

void printwelcome (int len)

{

printf ("Welcome-%d/n", Len);

}

void callback (int times, void (* print_info) (int))

{

int i;

for (i = 0; I < times; ++i)

{

Print_info (i);

}

void Main (void)

{

Callback (ten, printwelcome);

}

In the popular point, the callback function is like you go to the store to buy something, but there is no goods, this time you left the phone number to the clerk, wait until the goods when the clerk called you to let you pick up the goods. Your phone number is the equivalent of a callback function.
See how the callback function in Python is used:
Apply_async (Func,args,callback):
Result=func (*args)
Callback (Result)

Print_result (Result):
Result

Add (x, y):
X+y
Apply_async (Add, (2,3), callback=print_result)
Set callback to Print_result in Apply_async. When add addition is finished running, you can call Print_result to print.
Some people will ask, what is the difference between this and the Write intermediate function: code changed to the following is not the same, call Print_result in Appy_async is not the same
Apply_async (Func,args):
Result=func (*args)
Print_result (Result)

Print_result (Result):
Result

Add (x, y):
X+y

__name__==' __main__ ':
Apply_async (Add, (2,3))
It is true that this is the same effect, so what is the benefit of the callback function? If we update our requirements, we also want to print out the results of 2 parameter subtraction in Apply_async. The code can be changed to the following
Apply_async (Func,func1,args):
Result=func (*args)
Print_result (Result)
RESULT1=FUNC1 (*args)
Print_result (RESULT1)

Print_result (Result):
Result

Delete (x, y):
X-y

Add (x, y):
X+y

__name__==' __main__ ':
Apply_async (Add,delete, (2,3))
But if the demand continues to increase, we also want to print multiplication, division, power operations and other results of the operation. At this time, the various function parameters are not passed in the Apply_async. The more The parameter is written, the more difficult it is to see. The advantage of the callback function at this time is reflected.
Apply_async (Func,args,callback):
Result=func (*args)
Callback (Result)

Print_result (Result):
Result

Delete (x, y):
X-y

Add (x, y):
X+y

__name__==' __main__ ':
Apply_async (Add, (2,3), callback=print_result)
Apply_async (delete, (2,3), callback=print_result)
See, I just need to pass a different handler to the first parameter of Apply_async, and I can get different results. And the callback function is fixed. This is equivalent to using a callback function to handle the public part. And the apply_async of the parameters have different results.
In the callback function above, the callback function can handle only the arguments passed in and cannot access the other variables.
In order for the callback function to access external information, there are two methods: 1 use a binding method instead of a simple function
Resulthandler:
__init__ (self):
Self.sequence=0
Handler (Self,result):
Self.sequence+=1
Self.sequence,result
R=resulthandler ()
Apply_async (Add, (2,3), R.handler)
Apply_async (Add, (bis), R.handler)
Here you first create an instance of the class Resulthandler, and then use handler as the callback function, at which point you can synchronously access the sequence variable.
The second approach is to use closures.
Make_handler ():
Sequence=0
Handler (Result):
Nonlocal sequence
Sequence+=1
Sequence,result
Handler
Hanlder=make_handler ()
Apply_async (Add, (2,3), callback=hanlder)
Note that nonlocal is only used in Python3.0. There is no such keyword in 2.x. So in 2.x, you either use global variables or use lists or dictionaries. If you use a variable, you will get an error. Therefore, the system does not know where the variable is referenced.
Make_handler ():
SEQUENCE=[1]
Handler (Result):
sequence[0]=2
Sequence,result
Handler
Inline callback function:
First look at the use of the Wrap modifier in functools. First of all, look.
Decorator_try (func):
Wrapper (*args,**kwargs):
print ' Call Decorator_try '
Func (*args,**kwargs)
Wrapper


@decorator_try
Example ():
print ' Call example '


__name__==' __main__ ':
Example ()
example.__name__
The results are as follows:
E:\python2.7.11\python.exe e:/py_prj/python_cookbook/chapter5.py
Call Decorator_try
Call Example
Wrapper
The result of example.__name__ here is wrapper, not example. That is, the properties of the modified function have changed. Because the adorner can be equivalent to write Example=decorator_try (example). The return value of Decorator_try is wrapper. So the example attribute is then changed to wrapper. To eliminate this effect, we need to use wraps.
After modifying the wrapper with wraps, the results are example
Decorator_try (func):
@wraps (func)
Wrapper (*args,**kwargs):
print ' Call Decorator_try '
Func (*args,**kwargs)
Wrapper
E:\python2.7.11\python.exe e:/py_prj/python_cookbook/chapter5.py
Call Decorator_try
Call Example
Example

Python Cookbook Third Edition study note nine: functions

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.