异想家Python学习代码

本文是自己学习廖雪峰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

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