本文是自己学习廖雪峰Python教程的笔记,记录些常用用法,方便以后找代码片段。

JfzPylib.py文件:

#!/usr/bin/env python3
#coding=utf-8
'''
异想家Python函数库
'''
import math
# 求绝对值
def Fun_abs(x):
    if not isinstance(x, (int, float)): 
        raise TypeError('bad operand type') 
    if x>=0:
        return x
    else:
        return -x

# 解一元二次方程
def Fun_Solve2yuanEquation(a,b,c): 
    delta = b*b-4*a*c
    if delta < 0:
        return
    elif delta == 0:
        x1 = (-b + math.sqrt(b*b-4*a*c))/(2*a)
        return x1
    else:
        x1 = (-b + math.sqrt(b*b-4*a*c))/(2*a)
        x2 = (-b - math.sqrt(b*b-4*a*c))/(2*a)
        return x1,x2

JfzPyStudy.py文件:

#!/usr/bin/env python3
# coding=utf-8
' 异想家Python学习 '
__author__ = 'Sandeepin'

# 【1】输出
print('\n\033[1;31m【1】输出\033[0m\n')
print("异想家")  # 双引号
print('Fuck''Bitch','Shit')  # 单引号,逗号间隔,输出变空格
print('1234 - 5678 =',1234-5678)  # 输出数字计算

# 【2】输入
print('\n\033[1;31m【2】输入\033[0m\n')
#name = input()
#print(name)
#name2 = input('输入网名')
#print(name2)

# 【3】Python基础
print('\n\033[1;31m【3】Python基础\033[0m\n')
# 缩进强迫写出格式化代码,坚持使用【4个空格】的缩进
# Python程序【大小写敏感】

# 【4】数据类型、变量
print('\n\033[1;31m【4】数据类型、变量\033[0m\n')
print(1024)
print(0xff)
print(1.23e9)
print('abc')
print("xyz")
print("x\'y\'z\n")  # 转义字符\n换行
print(r'\\\t\\')  # r表示内部字符不转义
print('''123
456
789''')  # '''括起的内容可多行
# True False and or not  # 布尔运算
# None  # 空值

a = 123  # 变量数值
print(a)
a = 'jfz'  # 变量字符串,同一变量反复赋值
b = a
a = '666'
print(a)
print(b)
PI = 3.14159265359  # 常量用大写表示,实际上是变量,想改就改
print(PI)
print(10 / 3)
print(10 // 3)  # 地板除,整数部分
print(10 % 3)  # 余数部分
# Python整数无大小限制,浮点数也没限制,太大会变成inf(无限大)

# ASCII 1个字节,Unicode 通常2个字节, UTF-8 可变长编码(英语1个,中文3个,特殊4-6个)
print('中文str')  # python字符串以Unicode编码
print(ord('A'))  # ord获取字符整数表示
print(ord('蒋'))
print(chr(66))   # ord编码整数转字符
print(chr(26041))
print('\u4e2d\u6587')  # 用16进制写中文
print(b'ABC')# 编码为bytes
print('ABC'.encode('ascii'))
print('异想家123'.encode('utf-8'))
print(b'fuck'.decode('ascii'))# 解码为str
print(b'\xe8\x92\x8b\xe6\x96\xb9\xe6\xad\xa3'.decode('utf-8'))

print(len('ABC'))  # 计算str字符数
print(len('异想'))
print(len(b'ABCddd'))  # 计算bytes字节数

# 【5】格式化输出
print('\n\033[1;31m【5】格式化输出\033[0m\n')
# 和C语言类似,%d %f %s %x
print('Jfz %d poi %s' %(77, 'sandeepin') )  # 几个%号,在后面就用%(1,2)填几个
print('%02d %07.3f' %(7, 33.3333333333) )  # 补零,类似C语言
print('年龄: %s %% 男士: %s' %(23, True) )  # %s永远起作用,不知道用什么的时候用它, %%转义%
s1 = 72
s2 = 85
r = s1/s2
print('比率s1/s2 = %.2f' % r)
print('彩色显示:\033[1;31mSandeepin\033[0m')

# 【6】list列表
print('\n\033[1;31m【6】list列表\033[0m\n')
# list列表是可变有序集合,用xxx = ['1','2','3']表示
classmates = ['Sandeepin', 'Samothrace', 'Bitch']
print(classmates)
print(len(classmates))  # list元素个数
print(classmates[0])  # 类似数组下标的方式访问元素,从0开始
print(classmates[2])
print(classmates[-1])  # 倒数第一个,即classmates[2]
print(classmates[-2])  # 倒数第二个
classmates.append('Jfz')  # 追加元素
classmates.insert(1,'poi')  # 插入元素,插在第1个(下标从0开始)
print(classmates)
classmates.pop()  # 弹出,最后一个元素删除
print(classmates)
classmates.pop(2)  # 弹出下标为2的那个
print(classmates)
classmates[0] = 'jiangfangzheng'  # 替换用赋值方法
print(classmates)
mixlist = ['poi',123,3.5678,['www','jj']]  # list元素类型可混合,list套list
print(mixlist[3][1])  # 相当于二维数组
nonelist=[]
print(len(nonelist))  # 空list

# 【7】tuple元组
print('\n\033[1;31m【7】tuple元组\033[0m\n')
# tuple元组是有序列表,类似list,但是tuple初始化后不能改,用xxx = ('1','2','3')表示
classmates = ('Michael', 'Bob', 'Tracy')
print(classmates)
print(classmates[1])
t = (1,)  # 只有一个元素的tuple要加个逗号,避免歧义为赋值1
print(t)  # 显示时也会加逗号防止误解
t = ('a', 'b', ['A', 'B'])
t[2][0] = 'X'
print(t)  # tuple元素不变,里面有list,list元素可变

# 【8】条件判断
print('\n\033[1;31m【8】条件判断\033[0m\n')
age = 19
if age >= 18:
    print('成年人')  # 从上往下判断,符合要求后剩下的判断忽略
elif age>=6:
    print('青少年')
else:
    print('小孩')
x =3
if x:
    print('True')   # 简写,x非0,非空就为True

#year = input()
##if year > 2000:         # 输入1999程序出错,因为输入的是字符串,要转成整数
#if int(year) > 2000:     # int()函数转整数
#    print('2000年之后')
#else:
#    print('2000年之前')

#print('体重判断程序')
#height = input('输入身高')
#weight = input('输入体重')
#bmi = int(weight)/(int(height)*int(height))
#if bmi>25:
#    pass  # pass跳过,不填报错
#else:
#    print('不胖')

# 【9】循坏
print('\n\033[1;31m【9】循坏\033[0m\n')
# 第1种 for...in循坏
names = ['异想家','sandeepin','jfz']
for aaa in names:  # 就是把每个元素带入aaa,执行下面语句一回
    print(aaa)
# 求和举例
qiuhe = 0
for x in [1,2,3,4,5,6,7,8,9,10]:
    qiuhe = qiuhe + x
print(qiuhe)

qiuhe = 0
for x in range(11):  # 生成从0开始的小于11的数的list
    qiuhe = qiuhe + x
print(qiuhe)

# 第2种 while循坏
n = 10
qiuhe = 0
while n > 0:
    qiuhe = qiuhe + n
    n = n -1
print(qiuhe)
# 【技巧】死循环时按Ctrl + C 强制退出

# 【10】字典
print('\n\033[1;31m【10】字典\033[0m\n')
# 字典dictionary类似其它语言中的map,键-值存储,快速查找,其内部存放顺序与放入顺序无关
# 字典以空间(内存)换时间,list以时间换空间,dictionary适合高速场合
# 字典的Key不能变,因此不能以list作为Key
jfzn = {'jfz':100,'sandeepin':96,'poi':88}
print(jfzn['poi'])  # 就像给数组的下标起别名,访问对应数值
jfzn['jfz'] = 99  # 字典内容赋值
print(jfzn['jfz'])
print('Thomas' in jfzn)  # 判断Key是否在字典中
print(jfzn.get('Thomas'))  # 不在返回None
print(jfzn.get('Thomas', 999))  # 不在返回自定义的999
print(jfzn.pop('poi'))  # 弹出Key
print(jfzn)

# set类似字典dict,是Key的集合,可作交并计算,不储存value
s = set([1, 2, 3])  # list作为输入
ss = set([1,1,2,2,3,3])  # 滤除重复元素
print(s)
s.add(4)  # 添加Key,重复无用
s.remove(1)  # 移除Key
print(s)
s1 = set([1, 2, 3])
s2 = set([2, 3, 4])
print(s1 & s2)  # 交运算
print(s1 | s2)

# 【11】可变与不可变学习
print('\n\033[1;31m【11】可变与不可变学习\033[0m\n')
# list可变
abc = ['b','a','c']
abc.sort()  # 排序
print(abc)
# str不可变
strabc = 'bac'
print(strabc.replace('b','B'))  # 替换只对当前有效,strabc本质没变
print(strabc)

# 【12】函数
print('\n\033[1;31m【12】函数\033[0m\n')
# 调用函数 help(abs) 查看abs函数信息,官网看文档 http://docs.python.org/3/library/functions.html#abs
print(abs(-5))
print(max(2, 3, 1, -5))
# 数据类型转换函数
print(int('123'))
print(int(12.3))
print(float(123.456))
print(bool(1))
# 函数名本身就是一个引用,完全可以给函数名取别名
ShiLiu = hex
print(ShiLiu(12))
# 自定义函数
def Fun_SanCiFang(x):
    return x*x*x
print(Fun_SanCiFang(3))  # 调用函数
from JfzPylib import Fun_abs  # 从JfzPylib.py文件中导入函数Fun_abs
print(Fun_abs(-93))
# 返回多个值
import math

def move(x, y, step, angle=0):
    nx = x + step * math.cos(angle)
    ny = y - step * math.sin(angle)
    return nx, ny

print(move(10, 20, 50))  # 返回的本质是一个元组
x, y = move(10, 20, 50)  # 返回一个元组可省略括号
print(x, y)

def Fun_Solve2yuanEquation(a,b,c):  # 解二次方程函数
    delta = b*b-4*a*c
    if delta < 0:
        return
    elif delta == 0:
        x1 = (-b + math.sqrt(b*b-4*a*c))/(2*a)
        return x1
    else:
        x1 = (-b + math.sqrt(b*b-4*a*c))/(2*a)
        x2 = (-b - math.sqrt(b*b-4*a*c))/(2*a)
        return x1,x2
print(Fun_Solve2yuanEquation(1,4,7774))
# 函数参数——默认参数、可变参数、关键字参数
def CiFang(x):
    return x*x
print(CiFang(2))
def LiFang(x):
    return x*x*x
print(LiFang(2))
# 位置参数,顺序要定好,n=2是默认参数
def CiFangN(x, n=2):
    out = 1
    while n > 0:
        out = out * x
        n = n - 1
    return out
print(CiFangN(2,4))# 位置参数
print(CiFangN(2))  # 默认参数,必选参数在前,默认参数在后,否则有歧义
# 默认参数,变化大的放在前面,变化小的放在后面
def ZhuCe(name, gender , age=6, city = 'Guilin'):
    print('name=%s, gender=%d, age=%d, city=%s'%(name,gender,age,city))
    return 'OK'
print(ZhuCe('jfz', 2))
print(ZhuCe('poi', 1, 8))  # 按顺序补全
print(ZhuCe('poi', 1, city='wuhan'))  # 选择输入city,其它默认
# 一个坑
def add_end(L=[]):
    L.append('END')
    return L
poid=[3,2,1]
print(add_end(poid))
print(add_end())
print(add_end())  # 输出了['END', 'END'],默认参数L被记着了,不能这么用
# 正确写法:
def add_endfix(L=None):
    if L is None:
        L=[]
    else:
        L.append('END')
    return L
print(add_endfix())
print(add_end())
# 【技巧】能设计为不变对象时,就尽量设计成不变对象,防止意外修改

# 可变参数——传入的参数可变
# 传统方法:传list或tuple
def calcX2(shuru):
    sum = 0
    for fuck in shuru:
        sum = fuck*fuck +sum
    return sum
fuckk=[1,2,3]
print('calcX2 =',calcX2(fuckk))
# 可变参数法——仅在参数前加个*号
def calcX2B(*shuru):
    sum = 0
    for fuck in shuru:
        sum = fuck*fuck +sum
    return sum
print('calcX2B =',calcX2B(fuckk[0], fuckk[1], fuckk[2]))  # 输入参方法1
print('calcX2B =',calcX2B(*fuckk))  # 输入参方法2
print('calcX2B =',calcX2B(1, 2, 3))  # 输入参方法3

# 关键字参数——加两个**,扩展函数功能,获得额外信息
def ZhuCeKW(name, gender , **kw):
    print('name=%s, gender=%d other='%(name, gender), kw)
    return 'OK'
print(ZhuCeKW('duck', 3))
print(ZhuCeKW('duck', 3, city='wuhan'))
extra = {'age':12, 'city':'guilin'}  # 键值形式输入
print(ZhuCeKW('duck', 3, **extra))  # extra加**
# 限制关键字参数——命名关键字参数
# 例如只接受city和age
# 命名关键字参数以特殊的单个*表示,后面的为命名关键字参数
# 命名关键字参数必须传入参数名
def ZhuCeCheck(name, gender, *, age, city='guilin'):
     print(name, gender, age, city)
     return 'OK'
print(ZhuCeCheck('Jack', 24, city='Beijing', age = 11))
# print(ZhuCeCheck('Jack', 24, city='Beijing', job='Engineer'))  # 输出出错

# 参数组合举例——必选、默认、可变、关键字、命名关键字
# 顺序: 必选、默认、可变\关键字\命名关键字
# 可变和命名显然不能混在一起
def f1(a, b, c=0, *args, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
def f2(a, b, c=0, *, d, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
f1(1, 2)
f1(1, 2, c=3)
f1(1, 2, 3, 'a', 'b')  # a、b是可变
f1(1, 2, 3, 'a', 'b', x=99)  # x=99是关键字,用 = 表示键值配对
f2(1, 2, d=99, ext=None)   # d为命名关键字,只有写d=xx才对,**kw就换成关键字了,变成键值配对
args = (1, 2, 3, 4)  # 通过tuple和dict作为输入
kw = {'d': 99, 'x': '#'}
f1(*args, **kw)  # 任意函数都可以以形式f1(*args, **kw)调用
args = (1, 2, 3)
kw = {'d': 88, 'x': '#'}
f2(*args, **kw)
# 【小结】
# *args是可变参数,接收tuple元组
# **kw是关键字参数,接收dict字典
# func(1,2,3)可以装list、tuple通过*args传入func(*(1,2,3))
# func(a=1,b=2),可以装dict通过**kw传入func(**{'a':1,'b':2})

# 【13】递归函数——函数调用本身
print('\n\033[1;31m【13】递归函数\033[0m\n')
def JieCheng(n):
    if n == 1:
        return 1
    else:
        return n * JieCheng(n-1)
print('递归阶乘:', JieCheng(5))
# 递归太多层会栈溢出,解决方法:尾递归优化
# 常规递归过程如下:
# ===> fact(5)
# ===> 5 * fact(4)
# ===> 5 * (4 * fact(3))
# ===> 5 * (4 * (3 * fact(2)))
# ===> 5 * (4 * (3 * (2 * fact(1))))
# ===> 5 * (4 * (3 * (2 * 1)))
# ===> 5 * (4 * (3 * 2))
# ===> 5 * (4 * 6)
# ===> 5 * 24
# ===> 120
def fact(n):
  return fact_iter(n, 1)
def fact_iter(num, product):
  if num == 1:
    return product
  return fact_iter(num - 1, num * product)
print('优化阶乘:', fact(5))
# 优化递归过程如下:
# ===> fact_iter(5, 1)
# ===> fact_iter(4, 5)
# ===> fact_iter(3, 20)
# ===> fact_iter(2, 60)
# ===> fact_iter(1, 120)
# ===> 120
# 【遗憾的是】python没对尾递归优化,这样写照样爆栈

# 利用递归函数移动汉诺塔:
def move(n, a, b, c):
    if n == 1:
        print('move', a, '-->', c)
        return
    move(n-1, a, c, b)
    print('move', a, '-->', c)
    move(n-1, b, a, c)
move(3, 'A', 'B', 'C')  # n为A盘数量1

# 【14】高级特性
print('\n\033[1;31m【14】高级特性\033[0m\n')
# 传统的循坏实现 1 3 5 7 9
L = []
n = 1
while n <= 99:
    L.append(n)
    n = n + 2
print(L)

print('\n【1、切片Slice】')
# 切片Slice
L = ['Fuck','Bitch','Shit','Porn']
LL = [L[0],L[1],L[2]]  # 笨办法
print(LL)
LL = []
for n in range(2):   # 循环办法
    LL.append(L[n])
print(LL)
LLL = L[0:3]    # 切片办法,代表取0 1 2号元素
LLL = L[:3]     # 切片办法,0开始取可省略0
LLL = L[1:4]    # 切片办法,1 2 3
LLL = L[-2:-1]  # 切片办法,取倒数第二个2到倒数第1个(不包括倒数第1个)
LLL = L[-2:]    # 包括倒数第1个
print(LLL)
# 各种取法
L = list(range(100))
print(L)
LL = L[:10]
print(LL)
LL = L[-10:]
print(LL)
LL = L[0:10:2]  # 取0~10,隔2-1=1个取一个(第一个必取,从第一个开始,2个中取一个)
print(LL)
LL = L[::5]  # 全取,每5个取一个
print(LL)
LL = L[:]  # 全取,等于复制
print(LL)
T = (1,2,3,4,5)
TT = T[2:4]  # Tuple也可切片(1,2,3)[:3]类似形式
print(TT)
Str1 = 'abcdefg'
Str2 = Str1[0:3]  # 字符串也可切片
print(Str2)
# 【总结】切片可以节省循环,一句话实现

# 【迭代Iteration】
print('\n【2、迭代Iteration】')
# for循环遍历一遍就是迭代
# Python的for是高度抽象的循环
Fuck = {'Bitch':'Good','Porn':'OK','Shit':'No'}
for key in Fuck:  # 默认迭代key
    print(key)
for value in Fuck.values():  # 迭代value
    print(value)
for item in Fuck.items():  # 迭代key和value
    print(item)
for ch in 'Sandeepin':  # 字符串迭代
    print(ch)
# 判断一个对象是否能迭代
from collections import Iterable
print(isinstance('abc', Iterable))   # str可以
print(isinstance(123, Iterable))     # 整数不行
# 对list实现类似Java的下标循环
for i, value in enumerate(['A', 'B', 'C']):
    print(i,value)
for x, y in [(1, 1), (2, 4), (3, 9)]:  # 实现for循环引用两个变量
    print(x, y)

# 【列表生成式List Comprehensions】
print('\n【3、列表生成式List Comprehensions】')
# 用来创建list的生成式
# 生成 1 2 3 ... 10
print(list(range(1, 11)))
L = []
# 生成 1 4 9 ... 100
for x in range(1, 11):
    L.append(x * x)
print(L)
# 列表生成式的方法,生成 1 4 9 ... 100
LLL = [x * x for x in range(1, 11)]  # 生成结果 for 序号 in 序列
print(LLL)
# 后面能加 if 条件,例如只生成偶数的平方结果
LLL2 = [x * x for x in range(1, 11) if x%2 is 0]  # 生成结果 for 序号 in 序列
print(LLL2)
# 还可以两层、多层循环,实现全排列
LL = [m+n for m in 'ABC' for n in 'xyz']
print(LL)
# 字典键值同时迭代
for key,value in Fuck.items():  # 迭代key和value
    print(key,'=',value)
# 利用两个变量生成list
d = {'x': 'A', 'y': 'B', 'z': 'C' }
dd = [k + '=' + v for k, v in d.items()]
# list元素变小写
L = ['Hello', 'World', 'IBM', 'Apple']
L = [s.lower() for s in L]
print(L)
# 列出当前文件夹所有文件和目录
import os  # 导入OS模块
dirr = [d for d in os.listdir('.')]  # os.listdir列出当前文件夹所有文件和目录
print(dirr)
# 混合整型字符串的list转小写
L = ['Hello', 'World', 18, 'Apple', None]
S = [ss.lower() for ss in L if isinstance(ss, str)]  # 判断是否为字符串
print(S)

# 【生成器Generator】
print('\n【4、生成器Generator】')
# 列表生成式生成List受内存限制,很浪费空间。生成器在循环过程中不断推出后续元素,不必创建大量list,节省空间。
# 创建生成器Generator方法1:列表生成式[]改为()
g = (x * x for x in range(10))
print(next(g))
print(next(g))
print(next(g))  # 用next方法打印生成器

for n in g:    # 用for打印
    print(n)
# 复杂情况for循环实现不了的时候用函数实现,就需要生成器了
# Fibonacci数列 1, 1, 2, 3, 5, 8, 13, 21, 34
def FibonacciNum(num):
    n, a, b = 0, 0, 1
    while n < num:
        print(b)
        c = b
        b = a + b
        a = c
        # a, b = b, a + b  # 同时进行,可以省去一个变量
        n = n + 1
    return 'poi'
FibonacciNum(10)
# 递归实现Fibonacci数列
def FibonacciNumDigui(num):
    if num == 1:
        return 1
    elif num == 2:
        return 1
    else:
        out = FibonacciNumDigui(num - 1) + FibonacciNumDigui(num - 2)
        return out
print(FibonacciNumDigui(8))

# 变成生成器,只需要把print变成yield
def FibonacciGenerator(max):
  n, a, b = 0, 0, 1
  while n < max:
    yield b
    a, b = b, a + b
    n = n + 1
  return 'ppp'
# 变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行
fg = FibonacciGenerator(6)
print(next(fg))  # 在执行过程中,遇到yield就中断,下次又继续执行
print(next(fg))
print(next(fg))
print(next(fg))
print(next(fg))
print(next(fg))
for n in FibonacciGenerator(6):  # for循坏调用生成器,基本上不用next
    print(n)  # 但是拿不到return的值,要用StopIteration,以后再说

# 杨辉三角形生成[jfz写,不完善]
def YangTriangles(num):
    if num == 1:
        a = [1,]
        #print(a)
        return a
    if num == 2:
        a = [1,1]
        #print(a)
        return a
    if num >=3:
        c = list(range(num))
        c[0] = 1
        c[-1] = 1
        for i in range(1,num-1):
            c[i] = YangTriangles(num-1)[i-1] + YangTriangles(num-1)[i]
        return c
print(YangTriangles(6))

# 【迭代器Iterable】
print('\n【5、迭代器Iterable】')
# 可以直接作用于for循环的对象统称为可迭代对象:Iterable: list、tuple、dict、set、str、generator
# 用isinstance()判断
from collections import Iterable
print('迭代对象:',isinstance((x for x in range(10)), Iterable))
print('迭代对象:',isinstance('1232',Iterable))  # 字符串可以
print('迭代对象:',isinstance(1232,Iterable))  # 数字不可以
# 可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator
from collections import Iterator
print('迭代器:',isinstance((x for x in range(10)), Iterator))
print('迭代器:',isinstance('1232',Iterator))
# 可迭代对象变迭代器:iter()
print('变迭代器:',isinstance(iter([]), Iterator))
print('变迭代器:',isinstance(iter('1232'),Iterator))
# Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。


# 【15】函数式编程
print('\n\033[1;31m【15】函数式编程\033[0m\n')
# Functional  Programming,函数式编程就是一种抽象程度很高的编程范式
# 函数式编程的一个特点: 允许把函数本身作为参数传入另一个函数,还允许返回一个函数!
# 【高阶函数Higher-order function】

print('\n【1、高阶函数Higher-order function】')
absxxx = abs(-10)  # 变量指向函数返回值
print(absxxx)
absxx = abs  # 变量指向函数本身,函数名本身可看作一个变量,它指向具有某种作用的一个函数
print(absxx(-777))
# 一个函数接受另一个函数作为变量
def add(x, y, f):
    return f(x) + f(y)
print(add(-2, -3, abs))
# 把函数作为参数传入,这样的函数称为【高阶函数】

#【map/reduce】
# 有一个函数f(x)=x^2,要把这个函数作用在一个list[1, 2, 3, 4, 5, 6, 7, 8, 9]上,就可以用map()实现
fuck = [1,2,3,4,5,6]
def square2(x):
    return x * x
xxx = map(square2,fuck)  # 结果r是一个Iterator惰性序列
print(list(xxx))  # 用list算迭代器,计算出来
print(list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])))  # 将数字字符串化

# reduce把一个函数作用在一个序列[x1, x2, x3, ...]上, 把结果继续和序列的下一个元素做累积计算
# 效果就是:reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
from functools import reduce
def add(x, y):
    return x + y
print(reduce(add, [1, 2, 3, 4, 5]))  # 等于是求和,还可用sum
# 把序列[1, 3, 5, 7, 9]变换成整数13579
def fn(x, y):
    return x * 10 + y
print(reduce(fn, [1, 3, 5, 7, 9]))

# map/reduce配合,整理成一个str2int的函数
def str2int(s):
    def fn(x, y):
        return x * 10 + y
    def char2num(s):
        return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
    return reduce(fn, map(char2num, s))
print(str2int('123'))

# (jfz)实现输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart']
def normalize(name):
    namelow = name.lower()  # 转小写
    return namelow.capitalize()  # 转首字母大写
L1 = ['adam', 'LISA', 'barT']
L2 = list(map(normalize, L1))
print(L2)

# (jfz)实现类似sum求和的求积函数prod()
def prod(L):
    def squareXxY(x, y):
        return x * y
    return reduce(squareXxY, L)
print('3 * 5 * 7 * 9 =', prod([3, 5, 7, 9]))

# (jfz)实现str2float函数
def str2float(instr):
    def str2int(s):
        def fn(x, y):
            return x * 10 + y
        def char2num(s):
            return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
        return reduce(fn, map(char2num, s))
    [z, x]=instr.split('.')
    return str2int(z) + str2int(x)/(pow(10, len(x)))
print(str2float('123.456777'))

#【filter】
# filter()函数用于过滤序列
# 和map()类似,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
# 例如删掉偶数
def is_odd(n):
    return n % 2 == 1
print(list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])))
# 例如删掉空字符串
def not_empty(s):
    return s and s.strip()
print(list(filter(not_empty, ['A', '', 'B', None, 'C', '  '])))
# 【注意】filter()函数返回的是Iterator,也要list化

# 埃氏筛法用filter求素数
# 先构造一个从3开始的奇数序列:
def _odd_iter():
    n = 1
    while True:
        n = n + 2
        yield n
# 定义一个筛选函数:
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
# (jfz)利用filter()滤掉非回文数:
print('回文数:')
def is_palindrome(n):
    strn = str(n)  # 转字符串
    i= len(strn)//2  # 半长度
    k = 0  # 回文计数
    for j in range(i):
        if strn[j] == strn[-(j+1)]:
            k = k + 1
    if k == i:# 回文次数=半长度说明回文
        return True
    else:
        return False
output = filter(is_palindrome, range(1, 1000))
print(list(output))

#【排序算法sorted】
# 排序的核心是比较两个元素的大小
# 数字直接比较,字符串或者两个dict呢?比较的过程必须通过函数抽象出来。
# 默认从小到大排list
print('从小到大排序:',sorted([36, 5, -12, 9, -21]))
# sorted()函数是高阶函数,可以接收一个key函数来实现自定义的排序
print('绝对值排序:',sorted([36, 5, -12, 9, -21],key=abs))
# 字符串排序,按ASCII的大小比较
print('字符串排序:',sorted(['bob', 'about', 'Zoo', 'Credit']))
# 按照字母序排序,忽略大小写
print('按字母排序(忽略大小写):',sorted(['bob', 'about', 'Zoo', 'Credit'],key=str.lower))
# 反向排序,只需要传入第三个参数reverse=True
print('反向排序(从大到小):',sorted([36, 5, -12, 9, -21],reverse=True))
# 学生名字和成绩: 按名字排序
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_name(t):
    tt = t[0]
    return tt
L2 = sorted(L, key=by_name)
print('按名字排序:',L2)
# 学生名字和成绩: 按成绩从高到低排序
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_score(t):
    tt = t[1]
    return tt
L2 = sorted(L, key=by_score, reverse=True)
print('按成绩排序:',L2)

# 返回函数
print('\n【2、返回函数】')
# 把函数作为结果值返回
# 通常求和的函数
def calc_sum(*args):
    ax = 0
    for n in args:
        ax = ax + n
    return a
print('直接求和:',calc_sum(1, 3, 5, 7, 9))
# 如果不需要立刻求和,而是在后面的代码中,根据需要再计算怎么办?可以不返回求和的结果,而是返回求和的函数
def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum
# 定义的函数内部再定义一个函数,外函数返回内函数
print('延迟求和(返回求和函数):',lazy_sum(1, 3, 5, 7, 9))
# 当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力
# 当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数
f1 = lazy_sum(1, 3, 5, 7, 9)
f2 = lazy_sum(1, 3, 5, 7, 9)
print('闭包不等:',f1==f2)

# 【闭包】
# 返回的函数并没有立刻执行,而是直到调用了f()才执行
def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i
        fs.append(f)
    return fs
f1, f2, f3 = count() # 将一个list中每个元素分别给f1, f2, f3
print('闭包调用才执行:', f1(), f2(), f3())  # 结果是9 9 9
# 原因就在于返回的函数引用了变量i,但它并非立刻执行。
# 等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9
# 【注意】返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量
# 如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值
def count():
    def f(j):
        def g():
            return j*j
        return g
    fs = []
    for i in range(1, 4):
        fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
    return fs
f1, f2, f3 = count() # 将一个list中每个元素分别给f1, f2, f3
print('多一层函数:', f1(), f2(), f3())  # 结果是1 4 9

# 匿名函数
print('\n【3、匿名函数】')
# 就是没有名字的函数,关键字lambda表示匿名函数,冒号前面的x表示函数参数。
a = list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
print(a)
# 等于是:
def f(x):
    return x * x
a = list(map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
print(a)
# 匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果
f = lambda x: x * x
print(f(5))
# 把匿名函数作为返回值返回
def build(x, y):
    return lambda:x*x+y*y
aaa = build(3, 4)
print(aaa())

# 装饰器
print('\n【4、装饰器】')
# 通过变量也能调用该函数
def jfz():
    print('poi')
sa = jfz
sa()
# 函数对象有一个__name__属性,可以拿到函数的名字
print(sa.__name__)
print(jfz.__name__)
# 假设要增强jfz()的功能,如在函数调用前后自动打印日志,但又不希望修改函数
# 这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)
# 本质上,decorator就是一个返回函数的高阶函数,定义如下函数:
def flog(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper
kxy = flog(jfz)
kxy()
# 借助Python的@语法,把decorator置于函数的定义处:
@flog  # 调用now()函数,不仅会运行now()函数本身,还会在运行now()函数前打印一行日志
def now():  # 相当于执行了语句:now = flog(now)
    print('fuck')
# 由于flog()是一个decorator,返回一个函数,所以,原来的now()函数仍然存在,
# 只是现在同名的now变量指向了新的函数,于是调用now()将执行新函数,即在flog()函数中返回的wrapper()函数
# 如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数
# 比如,要自定义flog的文本:
def flog(text):
    def decorator(func):  # 原来def flog(func)放到了内层,外层传文本text
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator
# 这个3层嵌套的decorator用法如下:
@flog('异想家')
def now():
    print('fuck')
now()  # 显示结果为:异想家 now():\n fuck; now()相当于 now = log('execute')(now)
# 经过decorator装饰之后的函数,它们的__name__已经从原来的'now'变成了'wrapper':
print(now.__name__)
# 需要把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错
# Python内置的functools.wraps就是干这个事的,一个完整的decorator的写法如下:
import functools
def flog(func):
    @functools.wraps(func)  # 最后一层函数时用functools.wraps
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper
# 针对带参数的decorator:
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

# (jfz)编写一个decorator,能在函数调用的前后打印出'begin call'和'end call'的日志
def belog(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('开始 %s()' % func.__name__)
        # f = func(*args, **kw)
        # print('结束 %s()' % func.__name__)
        # return f
        return [func(*args,**kw), print('结束 %s()' % func.__name__)][0]  # 网友的巧妙写法
    return wrapper
@belog
def now():
    print('fuck')
now()
print(now.__name__)

# (jfz)能否写出一个@log的decorator,使它既支持:
# @log
# def f():
#     pass
# 又支持:
# @log('execute')
# def f():
#     pass
def log(xxx):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    if isinstance(xxx,str):
        text = xxx
        return decorator
    else:
        text = '开始'
        return decorator(xxx)

@log
def lrz():
    print('路然真')
lrz()
print(lrz.__name__)

@log('姐姐')
def lrz():
    print('路然真')
lrz()
print(lrz.__name__)

# 偏函数Partial function
print('\n【5、偏函数Partial function】')
# 通过设定参数的默认值,可以降低函数调用的难度。而偏函数也可以做到这一点。
print('默认转十进制',int('12'))
print('自定义转八进制',int('12',base=8))
print('自定义转十六进制',int('12',16))
# 要转换大量的二进制字符串,定义一个int2()的函数,默认把base=2传进去:
def int2(x, base=2):
    return int(x, base)
# functools.partial就是帮助我们创建一个偏函数, 可以直接使用下面的代码创建一个新的函数int2:
import functools
intp2 = functools.partial(int, base=2)
print('偏函数转二进制',intp2('11111'))
# 【总结】functools.partial的作用就是把一个函数的某些参数给固定住,返回一个新的函数
# 也可以在函数调用时传入其他值:
print('偏函数转八进制',intp2('11', base=8))
# 创建偏函数时,实际上可以接收函数对象、*args和**kw这3个参数,当传入:
# int2 = functools.partial(int, base=2)相当于:
# kw = { 'base': 2 }
# int('10010', **kw)
max2 = functools.partial(max, 10)  # 把10作为*args的一部分自动加到左边
print('加了10的求最大',max2(5, 6, 7))  # 相当于:args = (10, 5, 6, 7);max(*args)

# 【16】模块Module
print('\n\033[1;31m【16】模块Module\033[0m\n')
# 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,一个.py文件就称之为一个模块Module
# 最大的好处是大大提高了代码的可维护性。
# 其次,编写代码不必从零开始。
# 使用模块还可以避免函数名和变量名冲突。
# Python的所有内置函数:https://docs.python.org/3/library/functions.html
# 例如:一个abc.py的文件就是一个名字叫abc的模块

# 如果不同的人编写的模块名相同怎么办?
# 为了避免模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)
# 方法是选择一个顶层包名,比如sandeepin,按照如下目录存放:
# -sandeepin
#    - abc.py
#    - jfz.py
# 现在,abc.py模块的名字就变成了sandeepin.abc
# 【注意】__init__.py文件必须存在,否则Python就把这个目录当成普通目录,而不是一个包。
# 类似的,可以有多级目录,组成多级层次的包结构。如fuck.bitch.shit
import sandeepin.poi.poilib
sandeepin.poi.poilib.poi()

# [使用模块]模板
# #!/usr/bin/env python3
# # -*- coding: utf-8 -*-
# ' a test module '
# __author__ = 'Sandeepin'
import sys
def test():
    # sys模块有一个argv变量,用list存储了命令行的所有参数。
    # argv至少有一个元素,因为第一个参数永远是该.py文件的名称
    # 运行python3 hello.py jfz获得的sys.argv就是['hello.py', 'jfz']
    args = sys.argv
    if len(args)==1:
        print('Hello, world!')
    elif len(args)==2:
        print('Hello, %s!' % args[1])
    else:
        print('Too many arguments!')
# 当我们在命令行运行hello模块文件时,Python解释器把一个特殊变量__name__置为__main__
# 如果在其他地方导入该hello模块时,if判断将失败
# 因此,这种if测试可以让一个模块通过命令行运行时执行一些额外的代码
if __name__=='__main__':
    test()
# 启动Python交互环境,再导入hello模块, 没有打印Hello, word!,因为没有执行test()函数。

# [作用域]
# 在一个模块中,有的函数和变量我们希望给别人使用,有的函数和变量我们希望仅仅在模块内部使用
# 在Python中,是通过_前缀来实现,正常的函数和变量名是公开的(public),可以被直接引用
# 类似_xxx和__xxx这样的函数或变量就是非公开的(private),【不应该】被直接引用,比如_abc,__abc等
# private函数和变量不是【不能】被直接引用,是因为Python没有一种方法可以完全限制访问private函数或变量
def _private_1(name):
    return 'Hello, %s' % name
def _private_2(name):
    return 'Hi, %s' % name
def greeting(name):
    if len(name) > 3:
        return _private_1(name)
    else:
        return _private_2(name)
# 我们在模块里公开greeting()函数,而把内部逻辑用private函数隐藏起来
# 【技巧】外部不需要引用的函数全部定义成private,只有外部需要引用的函数才定义为public
print(greeting('jfz'))
print(greeting('Sandeepin'))
print(_private_1('San'))  # 并不限制用
print(_private_2('sss'))

# [安装第三方模块]
# 在Python中,安装第三方模块,是通过包管理工具pip完成的
# 比如安装Pillow的命令就是:pip install Pillow

# 图片生成缩略图
from PIL import Image
def JfzBlogImgThumb(ImgName):
    im = Image.open(ImgName)
    print(im.format, im.size, im.mode)
    if max(im.size[0], im.size[1]) > 1000:
        if im.size[0] > im.size[1]:
            im.thumbnail((1280, 1280))
        else:
            im.thumbnail((1000, 1000))
        im.save('thumb\\'+ImgName, 'JPEG')
    return 'OK'
JfzBlogImgThumb('1.jpg')

最后附上廖雪峰的教程地址:https://www.liaoxuefeng.com/wiki/1016959663602400

如果学习的话,更推荐直接阅读他的教程,讲得更详细。