Advanced features of Python

slice

For operations that specify index ranges, Python provides the slice method, similar to the Slicer for pivottables in Excel.

>>> L = ['Michael'.'Sarah'.'Tracy'.'Bob'.>>> L[0:3] [0:3] [0:3] [0:3]]Michael', 'Sarah', 'Tracy] '>>> S=list(range(100))    Declare a list from 0 to 99
>>> S[0:100:9]            Let's take a multiple of 9
[0.9.18.27.36.45.54.63.72.81.90.99]
Copy the code

A tuple is also a list, the only difference being that tuples are immutable. Therefore, a tuple can also be sliced, but the result is still a tuple.

Iterative Iteration

Given a list or tulp, you can iterate through the for loop, which is called iteration. Iteration in Python is similar to Javascript, unlike PHP or Java, which uses subscript iteration. For Python, dict, set, string, and so on are all iterable objects that can use a for loop. The for loop works as long as it’s applied to an iterable, and we don’t really care whether it’s a List or some other data type.

To determine whether an object is Iterable, use the Iterable type of the Collections module.

>>> from collections import可迭代>>> isinstance('abc', Iterable) # whether STR is iterable
True
>>> isinstance([1.2.3], Iterable) # list is iterable
True
>>> isinstance(123, Iterable) Whether integers are iterable
False
Copy the code

Python’s built-in enumerate function turns a list into an index-element pair, which iterates over both the index and the element itself in a for loop.

List generator

List Comprehensions are a simple yet powerful Python generator that can be used to create lists. When you write a list generator, you can create a list by putting the elements you want to generate in front of it, followed by a for loop. It’s very useful.

tiangan = 'a symplectic nonyl YiBingDing e f g j'
dizhi = 'Zi Chou Yin MAO Chen Si Wu Wei Shen you Xu Hai'

jiazi = [tiangan[x % len(tiangan)] + dizhi[x % len(dizhi)] for x in range(60)]
Copy the code

The for loop can be followed by an if judgment.

>>> [x * x for x in range(1.11) if x % 2= =0]
[4.16.36.64.100]
Copy the code

You can also use a two-layer loop that generates a full permutation.

>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX'.'AY'.'AZ'.'BX'.'BY'.'BZ'.'CX'.'CY', ‘CZ']
Copy the code

The generator

With list generators, we can create a list directly. However, due to memory limitations, list capacity is definitely limited. Also, not only does building a list of 1 million elements take up a lot of storage, but if we only need to access the first few elements, most of the space taken up by the latter elements is wasted.

So, if the list elements can be calculated by some algorithm, can we deduce the following elements as we go through the loop? This saves a lot of space by eliminating the need to create a complete list. In Python, this mechanism for looping while calculating is called a generator.

There are two ways to generate a generator.

1. Simply change a list generator [] to () to create a generator.

>>> L = [x * x for x in range(10)]
>>> L
[0.1.4.9.16.25.36.49.64.81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>
Copy the code

The generator holds the algorithm. Each call to next(g) computs the value of the next element of G until it computs to the last element. When there are no more elements, it raises a StopIteration error. In general, you can use a for loop to iterate over the contents of a generator.

2. If the algorithm is complex, you can use functions to achieve it.

def fib(max) :
    n, a, b = 0.0.1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'
Copy the code

If a function definition contains the yield keyword, the function is no longer a normal function, but a generator. Functions are executed sequentially, returning when they encounter a return statement or the last line of function statements. Functions that become generators, on the other hand, execute each time next() is called, return from a yield statement, and continue execution from the last yield statement when executed again.

The iterator

The main distinction here is between Iterable and Iterator.

Iterable data types, called iterables, can be iterated over using a for loop, including list, tuple, dict, set, STR, Generator, and Generator functions with yield. You can use the isinstance() function to determine whether it is Iterable.

Iterators can not only use the for loop, they can also use the next() function to call and return the next value until a StopIteration error is raised indicating that they cannot return the next value. In this way, we can think of the data stream as an ordered sequence, the length of which we do not know, but the next value can be obtained by continuous calculation.

You can use iter() to turn iterables like lists, dict, and STR into iterators.

Functional programming

In PHP and C, which I am familiar with before, programs are mostly written by dividing tasks into functions and then combining them together to solve problems. Such decomposition is called process-oriented programming, while functions are the basic unit of process-oriented programming.

The idea of Functional Programming is closer to mathematical computation. Functional programming is a programming paradigm with a high degree of abstraction. Functions written in pure functional programming languages have no variables. Therefore, as long as the input of any function is determined, the output is determined, and this pure function is called no side effects. While allowing the use of variables in programming languages, because of the variable state of the function is uncertain, the same input, may get different output, therefore, this function is a side effect.

Python provides partial support for functional programming.

High order function

Variables can point to functions

This is a little subversive to me. Look at the following example.

>> abs(-10)
10
>>> abs
<built-in function abs>
>>> f = abs
>>> f(-10)
10
Copy the code

Function names are also variables

A function name in Python is a variable that refers to a function.

>>> abs=10
>>> abs
10
>>> abs(-10)
Traceback (most recent call last):
  File "<stdin>", line 1.in <module>
TypeError: 'int' object is not callable
>>> f(-10)
10
Copy the code

The incoming function

The argument to a function that takes a variable that points to a function becomes a function that takes another function as an argument, which is called a higher-order function. Functional programming refers to this highly abstract programming paradigm

map / reduce

Python has built-in map() and reduce() functions. The map() function takes two arguments, a function and an Iterable. Map applies the passed function to each element of the sequence in turn and returns the result as a new Iterator.

>>> def f(x) :
.    return x * x
...
>>> r = map(f, [1.2.3.4.5.6.7.8.9])
>>> list(r)
[1.4.9.16.25.36.49.64.81]
Copy the code

Reduce applies a function to a sequence [x1, x2, x3… Reduce (f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)).

filter

Python’s built-in filter() function is used to filter sequences. It takes a function and a sequence, applies the passed function to each element, and then decides whether to keep or discard the element based on whether the return value is True or False.

def is_odd(n) :
    return n % 2= =1

list(filter(is_odd, [1.2.4.5.6.9.10.15]))
Copy the code

Note that filter() returns an Iterator, that is, an inert sequence, so to force filter() to complete the calculation, you need to use list() to get all the results and return the list.

Sorted sorting algorithm

Sorting is often used in programs. Whether you use bubble sort or quicksort, the core of sorting is to compare the size of two elements. Python’s built-in sorted() function sorts lists. The sorted() function is also a higher-order function that can also accept a key function for custom sorting, such as by absolute size. The function specified by key will be applied to each element of the list and sorted according to the result returned by the key function. To reverse sort, you don’t have to change the key function; you can pass a third parameter reverse=True.

>>> sorted([36.5, -12.9, -21[-])21, -12.5.9.36]
>>> sorted([36.5, -12.9, -21], key=abs)
[5.9, -12, -21.36]
Copy the code

Function as the return value

In addition to accepting functions as arguments, higher-order functions can also return functions as result values. In the following example, when lazy_sum is called, instead of the sum result, it returns the sum function. This structure is called a Closure.

def lazy_sum(*args) :
    def sum() :
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum
Copy the code

One thing to keep in mind when returning closures is that the return function should not reference any loop variables, or variables that will change later.

Anonymous functions

In Python, there is limited support for anonymous functions. Again using the map() function as an example, when calculating f(x)=x2, in addition to defining a function of f(x), you can also pass in an anonymous function directly. The lambda keyword stands for anonymous functions, and the x before the colon stands for function arguments. Anonymous functions have one limitation: they can only have one expression. Instead of writing a return, the return value is the result of that expression.

>>> list(map(lambda x: x * x, [1.2.3.4.5.6.7.8.9[]))1.4.9.16.25.36.49.64.81]
Copy the code

One advantage of using anonymous functions is that they don’t have names, so you don’t have to worry about function name conflicts. In addition, an anonymous function is also a function object. It is also possible to assign an anonymous function to a variable and use the variable to call the function.

A decorator

The function object has a __name__ attribute that takes the name of the function. Now, suppose we want to enhance the now() function by, for example, automatically printing a log before and after a function call, but we don’t want to change the definition of the now() function. This way of dynamically adding functionality while the code is running is called a Decorator.

def log(func) :
    def wrapper(*args, **kw) :
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper
Copy the code

Use Python’s @ syntax to place the decorator at the function definition.

@log
def now() :
    print('2015-3-25')

>>> now()
call now():    # Calling now() not only runs now() itself, but also prints a line of logs before running now()
2015-3-25
Copy the code

Putting @log in the definition of now() is equivalent to executing the statement now = log(now).

In this case, if the __name__ method is called and returns a function named Wrapper, use Python’s built-in functools.wraps.

import functools

def log(func) :
    @functools.wraps(func)
    def wrapper(*args, **kw) :
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper
Copy the code
import functools

def log(text) :
    def decorator(func) :
        @functools.wraps(func)
        def wrapper(*args, **kw) :
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator
Copy the code

Partial function

Python’s funcTools provides many useful functions, one of which is a Partial function.

def int2(x, base=2) :
    return int(x, base)

>>> int2('1000000')
64
>>> int2('1010101')
85
Copy the code

In the example above, by using partial functions, we wrap the function so that some parameters are entered by default, reducing the number of parameters entered during subsequent calls. You can do this with FuncTools.

>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85
>>> int2('1000000', base=10)
1000000
Copy the code

The module

Any language to achieve a project, can not do without file organization management. In Python, a.py file is called a Module. Using modules improves code maintainability and avoids function and variable name conflicts. However, be careful not to conflict with the built-in function name. To avoid module name conflicts, Python also introduces a way to organize modules by directory, called packages.

Once packages are introduced, no module will conflict with anyone else as long as the top-level package name does not conflict. Each package directory has an __init__.py file underneath it, which must exist otherwise Python treats the directory as a normal directory rather than a package. Init. py can be an empty file or have Python code, since __init__.py is itself a module. Similarly, there can be multiple levels of directories that form a multilevel package structure.

When creating a module, use a name that does not conflict with the Python module name. For example, if the system provides the sys module, the sys module cannot be named sys.py. Otherwise, the sys module cannot be imported.

Use the module

Take a look at the code that references the SYS module and defines the Hello module.

#! /usr/bin/env python3
# -*- coding: UTF-8 -*- # Indicates that the.py file itself uses the standard UTF-8 encoding

' a test module '

__author__ = 'Michael Liao'

import sys

def test() :
    args = sys.argv
    if len(args)==1:
        print('Hello, world! ')
    elif len(args)==2:
        print('Hello, %s! ' % args[1])
    else:
        print('Too many arguments! ')

if __name__=='__main__':
    test()
Copy the code

After importing the SYS module, we have a variable sys pointing to the module, which gives us access to all the functions of the SYS module.

scope

Normal function and variable names are public and can be referenced directly, such as ABC, x123, PI, etc. Variables like __xxx__ are special variables that can be referenced directly, but have a special purpose. Functions or variables such as _xxx and __xxx are private and should not be directly referenced. The reason we say that private functions and variables “should not” be referred to directly, rather than “cannot”, is because Python does not have a way to completely restrict access to private functions or variables. However, it is programming convention not to refer to private functions or variables.

Installing third-party Modules

In Python, installing third-party modules is done through the package management tool PIP. Try running PIP in a command prompt window, and if Windows says the command was not found, rerun setup to add PIP.

Note: It is possible to co-exist Python 3.x and Python 2.x on Mac or Linux, so the corresponding PIP command is pip3.

To install a third-party library, you must first know the name of the library. You can search for it on the Python website or pypi. For example, the name of Pillow is called Pillow

pip install Pillow
Copy the code