Smooth python, Fluent Python Chapter VII notes

Function decorator to closure.

Decorator in front of me closures already have a simple record, according to the contents of the book I, a function decorator to re-do a brief closure notes.

def deco(func):
    def inner():
        print('running inner()')
    return inner


@deco
def target():
    print('running target')




# target()

'' 'Is equal to the above the following' ''
target = deco(target)
target()

 This is the direct knowledge of the syntactic sugar function decorator, and is decorated function you run, in fact, already is a function of the interior decorator.

 

7.2Python when to perform decorator

registry = []

def register(func):
    print('running register(%s)' % func)
    registry.append(func)
    return FUNC    # Always remember to return to the original function

@register
def f1():
    print('running f1()')

@register
def f2():
    print('running f2()')

def f3():
    print('running f3()')

def main():
    print('running main()')
    print('registry', registry)
    f1 ()
    f2()
    f3 ()

if __name__ == '__main__':
    main()
running register(<function f1 at 0x10501f9e0>)
running register(<function f2 at 0x10501fd40>)
running main()
registry [<function f1 at 0x10501f9e0>, <function f2 at 0x10501fd40>]
running f1()
running f2()
running f3()
from t7_2 import *

 

/usr/local/bin/python3.7 / Users / shijianzhong / study / Fluent_Python / Chapter VII /t.py
running register(<function f1 at 0x10cd570e0>)
running register(<function f2 at 0x10cd57050>)

Process finished with exit code 0

 

 

Two execution above a main function performing A introduced into the module.

Decorator function is executed immediately upon import, it was decorated function runs only when explicitly called.

The main function is the same also when the same principle.

 

Chapter VI talked about the discount program can function through the decorator way, all of the preferential schemes function into a list of them, all of view, this should be a very good choice when

promos = []
def promotion(promo_func):
    promos.append(promo_func)
    return promo_func

 Preferential schemes need to add this decorator decorated with the discount program will function into the promos

It is a very good choice.

 

7.4 Variable scoping rules.

This fact, when I have a deeper impression.

When comparing subvert my thoughts, not what the function of internal variables can not change the external variables (immutable) (internal variable is not really can not change the external variables, the underlying reason is that if you do not change the amount of the assignment inside the function, assuming x, If you execute the x = x + 1, the editor running, this assignment will be the x defined as local variables, but you have failed to x inside the function, all is certainly an error, this is the so-called internal variables can not be changed the reason for external variables. If you assign a function body inside x = 1, and that a more direct and told the editor, this is a local variable and could not change the external global variable x), but the function before execution, editing will first determine the assignment inside the function body, assignments, irrespective of position,

Once assigned, the variable becomes a local variable, the function call parameters inside, using the local variables.

If there are external variables that have been assigned, there is no internal function of the variables, you can reference the variable, but can not modify the contents of the variable (immutable), unless you define global variables within the function body global variables.

import dis
a = 1
c = 2
def fn(arg):
    print(a)
    print(arg)
    print(c)
    c = 3

if __name__ == '__main__':
    print(dis.dis(fn))
    fn(99)

 External function c have been defined above, but also defines the internal function c, so the compiler function body, c is defined as a local variable, since the internal print function (c) prior to c = 3, so that the print function is for , c is an undefined objects.

Traceback (most recent call last):
  File "/Users/shijianzhong/study/Fluent_Python/第七章/t7_4.py", line 12, in <module>
    fn(99)
  File "/ Users / shijianzhong / study / Fluent_Python / Chapter VII /t7_4.py", line 7, in fn
    print(c)
UnboundLocalError: local variable 'c' referenced before assignment

 

 5           0 LOAD_GLOBAL              0 (print)
              2 LOAD_GLOBAL              1 (a)
              4 CALL_FUNCTION            1
              6 POP_TOP

  6           8 LOAD_GLOBAL              0 (print)
             10 LOAD_FAST                0 (arg)
             12 CALL_FUNCTION            1
             14 POP_TOP

  7          16 LOAD_GLOBAL              0 (print)
             18 LOAD_FAST 1 (c) # c is a partial function
             20 CALL_FUNCTION            1
             22 POP_TOP

  8          24 LOAD_CONST               1 (3)
             26 STORE_FAST               1 (c)
             28 LOAD_CONST               0 (None)
             30 RETURN_VALUE
None
1
99

 There are many solutions,

1, may be defined at the top of global c

2, the functions that the delete c = 3, a direct reference to a global variable

3, c = 3 is moved until the Print (c), it can be called a local parameter c

 

7.5 Closures

Translation of the book, the closure means is an extension of the scope of the function, wherein the function comprises a definition body referenced, but not defined by the non-member global variable definitions.

I do not know this does not translate well, or I understand there is a problem, a good mouthful.

Do just behind will be appreciated, is a function, a variable, the function body references, but its value is non global variables, and the function is not defined inside thereof.

Focused emphasis

1, the definition body is not defined

2, non-global variables

3, reference function definition body

The following cases to do with a method of averaging, respectively to the class of higher-order functions (reviewed higher order function definition, function object can receive or return the call as a function of higher order function)

class Averager:

    def __init__(self):
        self.series = []
        
    def __call__(self, new_value):
        self.series.append(new_value)
        total = sum(self.series)
        return total / len(self.series)

avg = Averager()
print(avg(3))
print(avg(4))
print(avg(5))

 By calling the class is very simple.

By using the closure, a little more complex understanding.

def make_averager():
    series = []
    def averager(new_value):
        series.append(new_value)
        total = sum(series)
        return total / len(series)
    return averager


avg = make_averager()

print(avg(3))
print(avg(4))
print(avg(5))
print (avg .__ code __. co_varnames) # local variable names
print (avg .__ code __. co_freevars) # free variables, is the series
print (avg .__ closure __ [0] .cell_contents) # remove the contents in the series.

'' 'Is a closure function, it retains the free variable bindings defined function when present, so call
When the function, although the scope of the definition is not available, but can still use those bindings' ''

 

/usr/local/bin/python3.7 / Users / shijianzhong / study / Fluent_Python / Chapter VII /t7_9.py
3.0
3.5
4.0
('new_value', 'total')
('series',)
[3, 4, 5]

Process finished with exit code 0

 

 

7.6nonlocal statement

nonlocal feeling is used for the closure, the closure functions when the free variable bindings in the parameter type is immutable, the need nonlocal.

def make_averager():
    count = 0
    total = 0
    def averager(new_value):
        nonlocal count, total # in fact, is the variable marked as free variables
        count += 1
        total += new_value
        return total / count
    return averager


avg = make_averager()

print(avg(3))
print(avg(4))
print(avg(5))
print (avg .__ code __. co_varnames) # local variable names
print (avg .__ code __. co_freevars) # free variables, is the series
print ([i.cell_contents for i in avg .__ closure__]) # remove the contents in the series.


'' 'Is a closure function, it retains the free variable bindings defined function when present, so call
When the function, although the scope of the definition is not available, but can still use those bindings' ''

 

/usr/local/bin/python3.7 / Users / shijianzhong / study / Fluent_Python / Chapter VII /t7_13.py
3.0
3.5
4.0
('new_value',)
('count', 'total')
[3, 12]

Process finished with exit code 0

After marked as free variable, you can re-create the associated value function (immutable).

 

7.7 to implement a simple decorator

According to my thinking in the process of knocking the code, function decorators certainly is a kind of closure function, all the conditions of closure function meet.

Interior decorator function, is not running (as transmitted by an external function in, programming a local variable), but also its global variable references non internal function defined (in fact, is to run the function to be decorated.)

# t7_15.py

import time
from functools import wraps

def clock(func):
    @wraps (func) # of attributes to be decorated with the function __doc__ __name__ property into the interior decorator function
    def clocked(*args):
        t0 = time.perf_counter()
        result = func(*args)
        elapsed = time.perf_counter() - t0
        name = func.__name__
        arg_src = ', '.join(repr(arg) for arg in args)
        print('[%0.8fs] %s(%s) -> %r' % (elapsed, name, arg_src, result))
        return result
    return clocked

 

import time

from t7_15 import clock


@clock
def snooze(seconds):
    '''This is snooze'''
    time.sleep(seconds)


'' 'According to the interpretation closure closure it refers extended function scope
, Which includes the function definition body referenced, but not defined by the non-member global variable definitions.
The snooze function which contains <function snooze at 0x10c0feb90>,
Snooze function is the original, this is not in the body of the function definition defined non-global variables.
But have to perform specific, it contains a reference to the definition of body.
'''

@clock
def factorial(n):
    return 1 if n < 2 else n * factorial(n-1)

if __name__ == '__main__':
    print(snooze.__name__)
    print(snooze.__doc__)
    print(snooze.__code__.co_name)
    print(snooze.__closure__[0].cell_contents)
    print(factorial.__closure__[0].cell_contents)
    print('*' * 40)
    snooze(.123)
    print(factorial(6))

 

/usr/local/bin/python3.7 / Users / shijianzhong / study / Fluent_Python / Chapter VII /t7_16.py
T7_l5
snooze
This is snooze
clocked
<function snooze at 0x10ed97b90>
<function factorial at 0x10ed48200>
****************************************
[0.12730196s] snooze(0.123) -> None
[0.00000109s] factorial(1) -> 1
[0.00002362s] factorial(2) -> 2
[0.00003878s] factorial(3) -> 6
[0.00005274s] factorial(4) -> 24
[0.00006689s] factorial(5) -> 120
[0.00008470s] factorial(6) -> 720
720

Process finished with exit code 0

 

7.8 standard library decorator

7k8klfautrrchtॊlklru_che

@ Functools.lru_cache (maxsize = 128, typed = True) # maxsize save up cached values, throw away the old full later
@clock # typed set to true, the parameters of different types can be stored separately, such as columns and a separate 1.0
def deco(x, y):
    print(f'x is {x},y is {y}')
    return x + y


@functools.lru_cache()
@clock
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n - 2) + fibonacci(n - 1)

 

deco(1, 2)
    deco(1, 2)
    deco(2, 3)
    deco(2, 3)
    fibonacci (10) # may function to accelerate

 

x is 1,y is 2
[0.00001129s] deco(1, 2) -> 3
x is 2,y is 3
[0.00000936s] deco(2, 3) -> 5
[0.00000091s] fibonacci(0) -> 0
[0.00000081s] fibonacci(1) -> 1
[0.00003022s] fibonacci(2) -> 1
[0.00000161s] fibonacci(3) -> 2
[0.00005840s] fibonacci(4) -> 3
[0.00000134s] fibonacci(5) -> 5
[0.00008966s] fibonacci(6) -> 8
[0.00000139s] fibonacci(7) -> 13
[0.00011810s] fibonacci(8) -> 21
[0.00000135s] fibonacci(9) -> 34
[0.00014750s] fibonacci(10) -> 55

 The cache and has value calculation results is not performed again, so the calculation is relatively much faster, avoid a lot of repetitive operations.

 

7.8.2 Pan single dispatch function

I understand from the case in the book, you can register a function to different sub-categories, sub-categories were defined functions into different according to the nature of the incoming parameters, if there is no sub-functions, on the implementation of the main decorative function.

 

from functools import singledispatch
from collections import abc
import numbers
import html

@singledispatch
def htmlize(obj):
    content = html.escape(repr(obj))
    return '<pre>{}</pre>'.format(content)

@ Htmlize.register (str) # string in here
def _(text):
    content = html.escape(text).replace('\n', '<br>\n')
    return '<p>{}</p>'.format(content)

@ Htmlize.register (numbers.Integral) # digital in here
def _(n):
    return '<pre>{0} (0x{0:x})</pre>'.format(n)

@ Htmlize.register (tuple) # Ganso in here
@ Htmlize.register (abc.MutableSequence) # variable sequence in here
def _(seq):
    inner = '</li>\n<li>'.join(htmlize(item) for item in seq)
    return '<ul>\n<li>' + inner +'</li>\n</ul>'

 

In [40]: from t7_21 import htmlize                                                                 

In [41]: htmlize({1,2,3})                                                                          
Out[41]: '<pre>{1, 2, 3}</pre>'

In [42]: htmlize(abs)                                                                              
Out[42]: '<pre><built-in function abs></pre>'

In [43]: htmlize('Heimlich & Co.\n -a game')                                                       
Out[43]: '<p>Heimlich & Co.<br>\n -a game</p>'

In [44]: htmlize(42)                                                                               
Out[44]: '<pre>42 (0x2a)</pre>'

In [45]: htmlize(['alpha',66,{3,2,1}])                                                             
Out[45]: '<ul>\n<li><p>alpha</p></li>\n<li><pre>66 (0x42)</pre></li>\n<li><pre>{1, 2, 3}</pre></li>\n</ul>'

 

Make an inappropriate analogy, @ singledispatch a bit like his father, he registered a lot of sub-functions, need to be registered under his father.

The ratio of use if it can reduce the degree of coupling between the functions.

 

 

Function parameters decorator outermost function is a function of decorator manufacturing.

 

7.10.2 parameterized clock decorator

# t7_25.py

import time
from functools import wraps

DEFAULT_LMT = '[{elapsed:0.8f}s] {name}({args}) -> {result}'

def clock(fmt = DEFAULT_LMT):
    def decorate(func):
        @wraps (func) # of attributes to be decorated with the function __doc__ __name__ property into the interior decorator function
        def clocked(*args):
            t0 = time.perf_counter()
            result = func(*args)
            elapsed = time.perf_counter() - t0
            name = func.__name__
            arg_src = ', '.join(repr(arg) for arg in args)
            print (fmt.format (** locals ())) # by ** locals () to pass unpacked format parameters really show operation.
            return result
        return clocked
    return decorate


if __name__ == '__main__':
    # Only () function within the parameters of style formatted output to fill the need, you can output the clock according to their own favorite form
    @clock()
    def snooze(seconds):
        time.sleep(seconds)

    for i in range(3):
        snooze(.123)

 

/usr/local/bin/python3.7 / Users / shijianzhong / study / Fluent_Python / Chapter VII /t7_25.py
[0.12805624s] snooze((0.123,)) -> None
[0.12805513s] snooze((0.123,)) -> None
[0.12333814s] snooze((0.123,)) -> None

Process finished with exit code 0

Guess you like

Origin www.cnblogs.com/sidianok/p/12089279.html