Getting started with Python

Life is short, I use Python.

版本:3.6
文档:The Python Language Reference
入门:廖雪峰Python教程
环境:Win 10 / Linux
安装:sudo apt install python

基础

hello,world!

print('hello,world!')

Python之禅

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

指定解释器,对Linux

#!/usr/bin/python3

输入输出

a = input()
print(a)

数据类型:整数,浮点数,字符串
格式化输入输出(与C语言一致):%d %f %s %x
整数浮点运算:* / // %

print(10/3)
print(10//3)
print(10%3)

字符串与编码
指定编码格式,确保编辑器使用UTF-8 without BOM编码

# -*- coding: utf-8 -*-

list(可变) & tuple(不可变对象) & dict(可变)& set(可变)

A = [1, 2, 'hello', 'world']
B = (1,23,5,'shit')
C = {1:10, 'hello':'world'}
D = {1,2,3}

条件分支

a = 5
if a > 10:
    print('a > 10')
elif a > 5:
    print('5 < a <= 10')
else:
    print('a <= 5')

循环

A = [1,2,3]
for a in A:
    print(a)
n = 1
while n < 10:
    print(n)
    n = n+1

缩进控制代码块层次,推荐使用空格而不是制表符。

函数

内建函数
函数定义

def power2(x):
    return x*x
print(power2(10))

默认参数,从后往前添加(与C++类似)

def power(x, n = 2):
    res = 1
    while n > 0:
        res *= x
        n = n-1
    return res

可变参数

# variable arguments, pass arguments as a tuple
def calc(*numbers):
    sum  = 0
    for n in numbers:
        sum = sum + n*n
    return sum

print(calc(1,2,3,4))
print(calc(*[1,2,3,4]))
# use * to change elements of a tuple or list into variable arguments
nums = [1,2,3,4,5]
print(calc(*nums))
print(*nums)

关键字参数可选

# keyword arguments, pass alternative arguments to kw as a dict
def person(name, age, **kw):
    if 'job' in kw:
        pass
    if 'gender' in kw:
        pass
    if 'city' in kw:
        pass
    print('name:', name, 'age:', age, 'other:',kw)

person('Michael', 18, job='coder', gender='man')
person('Michael', 18, **{'job':'coder', 'gender':'man'})

命名关键字参数,*前面的为位置参数,后面为命名关键字参数,命名关键字参数需传入其参数名

# named keyword arguments after *, must be passed with it's name
def person2(name, age, *, city = 'Shanghai', job):
    print(name, age, city, job)

person2('lucy', 18, job = 'coder')

上面几种参数可组合使用。

递归函数

# recursive function 
def fun(n): 
    if n == 1:
        return 1
    else:
        return fun(n-1) * n
print(fun(100))
print(fun(999)) # maximum recursion depth exceeded

默认最大递归深度限制为1000,上面传入999就会挂,修改限制

sys.setrecursionlimit(2000)

据说可以这样进行尾递归优化,但实际实验并没有什么卵用,尾递归请直接改为循环

# tail-call optimization
def fun2(n, res=1):
    if n == 1:
        return res
    else:
        return fun2(n-1, res * n)

print(fun2(1800))

经典递归问题:汉诺塔

# the tower of hanio, move n disks from a to c
def move(n, a, b, c):
    if n==1:
        print(a, '-->', c)
    else:
        move(n-1, a, c, b)
        move(1, a, b, c)
        move(n-1, b, a, c)

move(3, 'A', 'B', 'C')

高级特性

切片:

# slice 
print(L[0:3])
print(L[::5])   # fetch first one from every five elements
print(L[-10:])  # last 10 elements
print('ABCDEF'[::2])

例程,去掉一个字符串首尾两端的空格,简单而健壮

# strip spaces at head and tail of a string
# simple and strong
def trim(s):
    while s[:1] == ' ':
        s = s[1:]
    while s[-1:] == ' ':
        s = s[:-1]
    return s

瞬间感觉到python的编写风格与C/C++之流太不一样了。

迭代:

# iteration
D = {1:2, 'hi':'luck', 'holy':'shit'}
for key in D:
    print('%s:%s'%(key,D[key]))
for value in D.values():
    print(value)
# 同时迭代key和value
for k,v in D.items():
    print('%s:%s'%(k,v))
for ch in 'ABC':
    print(ch)

可迭代对象:list tuple set dict

from collections import Iterable
print(isinstance(123, Iterable)) # False
print(isinstance([1234, 2342, 243], Iterable)) # True

例程:找到一个序列中最大与最小值

def findMinAndMax(L):
    if len(L) == 0:
        return None, None
    min = max = L[0]
    for x in L:
        if x < min:
            min = x
        if x > max:
            max = x
    return min, max

函数:range(n, m) 生成nm-1的整数
列表生成式:[x*x for x in [1,2,3]] 将生成方法写在[]

for x in range(10):
    print(x)

例程:
打印1到100的所有偶平方数构成的list
生成一个’ABCD’与’XYZ’的全排列构成的list

L1 = [x * x for x in range(1, 11) if x % 2 == 0]
print(L1)
L2 = [m + n for m in 'ABCD' for n in 'XYZ']
print(L2)

生成器:generator
特点:生成一个序列,但是并不完整创建,而是保存生成的算法一边使用,一边生成
语法:列表生成式[]换为(),使用next()获得generator的下一个返回值

g = (x * x for x in range(10))
print(g) # generator object <genexpr> at 0x00000186CD989D58>
print(next(g)) # 0
print(next(g)) # 1
print(next(g)) # 4
print(next(g)) # 9

也可以在函数定义中使用yield返回

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'
f = fib(10)
print(f) # <generator object fib at 0x0000012E71849B48>
for x in f:
    print(x)

迭代器Iterator

  1. 凡是可作用于for循环的对象都是Iterable类型
  2. 凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列
  3. 集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象
  4. for循环的本质就是先获得一个Iterator对象,再不断调用next()实现的
  5. Iterator对象表示一个数据流,而数据流可以是无限的
from collections import Iterable
from collections import Iterator
print(isinstance('abc', Iterable))
print(isinstance([], Iterable))
print(isinstance({}, Iterable))
print(isinstance((), Iterable))
print(isinstance([x ** x for x in range(10)], Iterable))
print(isinstance(iter([]), Iterator))
def f(n):
    for x in range(n):
        yield x * x
fun = f(10)
print(isinstance(fun, Iterator))

函数式编程

函数式大法好?这我不评价,但函数式肯定是很有趣的。Python对函数式编程提供部分支持。

可以函数赋给变量,也可以给函数名赋值来覆盖。函数也可以作为参数传递,并且可以返回函数。

def add(x, y, f):
    return f(x) + f(y)

print(add(-1, -3, abs))

高阶函数:map reduce filter sorted

# high-level functions
# map(function, Iterable) 
# reduce(function, Iterable) -> f(f(f(x1,x2),x3),x4)
from functools import reduce
A = range(0, 11);
def f(x):
    return x * x
B = map(f, range(0, 11)) # B is a Iterator
print(list(B))

# numbers to character
print(list(map(str, range(0,10))))
def add(x, y):
    return x + y
print(reduce(add, [1,3,42,345,34,5]))

例程:将表示一个浮点数的字符串变为浮点数(没有错误处理)

# string to float
from functools import reduce
digits = {'0':0, '1':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9}
def str2float(s):
    def f1(x, y):
        return x * 10 + y
    def char2num(c):
        return digits[c]
    def find(s):
        i = 0
        for a in s:
            if a == '.':
                return i
            i = i + 1
        return len(s)+1
    return (reduce(f1, map(char2num, s[:find(s)])) + reduce(f1, map(char2num, s[find(s)+1:]))/pow(10, len(s)-find(s)-1))

例程:埃托拉色尼筛法求素数(generator真好用)

def _odd_iter():
    n = 1
    while True:
        n = n + 2
        yield n
# x is not divisialbe by n, return a lambda function
def _not_divisible(n):
    return lambda x : x % n > 0
def primes():
    yield 2
    it = _odd_iter() # 初始序列,奇数序列
    while True:
        n = next(it)
        yield n
        it = filter(_not_divisible(n), it)
# 打印1000以内的素数
for n in primes():
    if n < 1000:
        print(n)
    else:
        break

其中的_not_divisible(n)为返回的函数,接受的参数若不能被n整除则返回True.

例程:回文数

# 判断是否是回文数
def is_palindrome(s):
    return str(s)[::-1] == str(s)

print(list(filter(is_palindrome, range(1,1000))))

排序:sorted

L = [234, 1234, -234, 43, -8, 0, -10, -4, ]
A = sorted(L, key = abs)
print(A)
B = sorted(L, key = abs, reverse = True)
print(B)

例程:对list中的tuple按照姓名和分数排序

L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_name(t):
    return t[0]
L1 = sorted(L, key = by_name)
print(L1)

def by_score(t):
    return t[1]
L2 = sorted(L, key = by_score)
print(L2)

函数作为返回值,惰性求值

def lazy_sum(*args):
    def sum():
        res = 0
        for n in args:
            res += n
        return res
    return sum

f = lazy_sum(1, 3, 5, 7, 9)
print(f)    # <function lazy_sum.<locals>.sum at 0x0000019BEF2C7EA0>
print(f())  # 25

python中的闭包,与离散数学中关系的闭包感觉就不是一个东西。
这里的闭包意思是:在一个外函数中定义了一个内函数,内函数使用了外函数的临时变量,并且外函数的返回值是内函数的引用。
用处:装饰器、面向对象。
注意:返回内函数时,内函数并未执行。返回函数不要引用任何循环变量,或者后续会发生变化的变量。
例程:计数器,每次调用返回下一个值

def createCounter():
    ax = 0
    def counter():
        nonlocal ax   # nonlaocal 指定为非局部变量
        ax += 1
        return ax
    return counter

counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5

匿名函数:即lambda表达式,不能用return,表达式结果就是返回值

f = lambda x : x * x
print(list(map(f, [1,3,4,5])))

装饰器:函数运行期间动态增加功能,而不改变函数定义,使用语法@

# decorator
# warpper(*args, **kw) 可以接受任何参数
import functools
def log(func):
    def wrapper(*args, **kw):
        print('call %s :'%func.__name__)
        return func(*args, **kw)
    return wrapper

@log
def now():
    print('2018-6-2')
now()
print(now.__name__) # wrapper

更复杂一点,再加一层

def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

@log('execute')
def now():
    print('2018-6-2')
now()
print(now.__name__) # wrapper

但是上面的工作还没有做完,函数亦是对象,装饰器的使用使得now__name__属性变成了wrapper,所以需要将now__name__等属性复制到wrapper中。使用Python内置的@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

@log
def now():
    print('2018-6-2')
now()
print(now.__name__) # now 

偏函数:functools.partial

import functools
int2 = functools.partial(int, base = 2)
print(int2('1010101'))

猜你喜欢

转载自blog.csdn.net/qq_35527032/article/details/80555263