(2018-03-23)0005.Python基础入门班_第5课、文件访问与函数式编程入门

上一篇文章:(2018-03-22)0004.Python基础入门班_第4课、面向对象基础

关于本人

个人信息:微博
写作区:个人博客、、开源中国、豆瓣、掘金、CSDN
代码管理区:码云、GitHub、GitBook、Python_NoteBook(这个仅仅限于自己的本地搭建)
我的网络制作书籍:Python3Book(基于廖雪峰的Python教程编写成书)、
july_Oneline(基于七月在线培训机构的教程编写成书)、LineCode刷题总结__GitBookEditor网络书籍


推荐网站


推荐软件


推荐书籍


第5课 面向对象基础


一、文本文件读写3种方法
百度维基

自身理解

文件阅读、文件编写

代码展示

# 一、文本文件读写3种方法
'''
第一种方法
    1、读文件有3种方法
    read() 将文本文件所有行 读到一个字符串中。
    readline() 是一行一行的读
    readlines() 是将文本文件中所有行 读到一个list中,文本文件每一行是list的元素
    优点:readline()可以在读行过程中跳过特定行
'''
print('一、文本文件读写3种方法')
file1 = open('test.txt')
file2 = open('output.txt','w') # w可写 r可读 a 继续往下写 

while True:
    line = file1.readline() # 这一行
    # 这里可以进行逻辑处理
    file2.write('"'+line+'"'+",") 
    if not line:
        break
#记得文件处理完,关闭是个好习惯
file1.close()
file2.close()
print('!end!\n')

'''
2、第二种方法
文件迭代器,用for循环的方法
file2 = open('output.txt','w')
for line in open('test.txt')
    #这里可以进行逻辑处理
    file2.write('"'+line[:s]+'"'+",")
3、第三种方法
    文件上下文管理器
# 用 with..open 自带关闭文本的功能
with open('somefile.txt','r') as f:
        data = f.read()
# loop整个文件
with open('somefile.txt','r') as f:
    for line in f:
        # 处理每一行
#写入文件
with open('somefile.txt','w') as f:
    f.write(text1)
    f.write(text2)
#把要打印的line写入文件中
with open('somefile.txt','w') as f:
    print(line1,file = f)
    print(line2,file = f)
'''

控制台打印

一、文本文件读写3种方法
!end!

二、二进制文件读写
百度维基

自身理解

逢二进一

代码展示

# 二、二进制文件读写
'''
python默认读取的都是文本文件。
要是想要读取二进制文件,需要把刚刚的'r'改成'rb'

对于py2 标准是ascii
对于py3 标准是unicode
f = open('file.txt','rb')
u = f.read().decode('file') # 解码
'''
print('二、二进制文件读写')

f = open('avatar.jpg','rb')
print(f.read())
print('!end\n!')

控制台打印

二、二进制文件读写
b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00H\x00H\x00\x.....
!end
!

三、文件和目录操作(获取当前目录、创建文件夹、删除文件夹、文件夹名字拆分、获取文件扩展名、文件重命名、删除文件)
自身理解

文件的一些操作,复制、移动、删除、重命名

代码展示

#三、文件和目录操作
'''
3.1、基本操作
用python内置的os模块直接调用系统 提供的皆空函数
'''
print('三、文件和目录操作')
import os
print(os.name) # nt 是window系统 posix 说明是linux系统


'''
3.2、环境变量
在操作系统中定义的环境变量,全部保持在os.environ这个dict中,可以直接查看
一般会存放的是
python安装路径
系统缓存地方
本程序根目录等

3.3、 把其他文件放到environ里面  sys.path.append(xxx)
'''
print(os.environ)
#3.4、 操作文件与目录
print(os.path.abspath('.')) #当前目录的绝对路径
os.path.join('C:/Users/Hasee/Desktop/Python_七月在线/01-Python课程___Python基础入门班/Code/第5课 文件访问与函数式编程入门','hello') # 在某个目录下创建一个新目录
#3.5、 创建一个文件夹
# os.mkdir('/Users/Hasee/Desktop/Python_七月在线/01-Python课程___Python基础入门班/Code/第5课 文件访问与函数式编程入门/hello')# 需要用mkdir创建
#3.6、 删除一个文件夹
# os.rmdir('/Users/Hasee/Desktop/ython_七月在线/01-Python课程___Python基础入门班/Code/第5课 文件访问与函数式编程入门/hello/')# 需要用mkdir创建
#3.7、 文件夹名字拆分
print(os.path.split('/Users/Hasee/Desktop/Python_七月在线/01-Python课程___Python基础入门班/Code/第5课 文件访问与函数式编程入门/output.txt'))
#3.8、 获取文件扩展名
print(os.path.splitext('/Users/Hasee/Desktop/Python_七月在线/01-Python课程___Python基础入门班/Code/第5课 文件访问与函数式编程入门/output.txt'))
#3.9、 文件重命名
# print(os.rename('output.txt','o.txt'))
#3.10、 删除文件
# os.remove('o.txt')
print('!end!\n')

控制台打印

三、文件和目录操作
nt
environ({'PATH': 'C:\\Program Files (x86)\\Intel\\iCLS Client\\;C:\\Program Files\\Intel\\iCLS Client\\;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files (x86)\\NVIDIA Corporation\\PhysX\\Common;C:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\IPT;C:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C:\\Program Files (x86)\\GtkSharp\\2.12\\bin;C:\\Windows\\system32\\config\\systemprofile\\.dnx\\bin;C:\\Program Files\\Microsoft DNX\\Dnvm\\;C:\\Program Files\\Microsoft SQL Server\\120\\Tools\\Binn\\;C:\\Program Files\\Microsoft SQL Server\\130\\Tools\\Binn\\;F:\\lyh_SVN_Location\\bin;F:\\lyh_tortoiseSVN\\bin;E:\\Tools\\NodeJs\\;C:\\Users\\Hasee\\AppData\\Local\\Programs\\Python\\Python35-32\\Scripts\\;C:\\Users\\Hasee\\AppData\\Local\\Programs\\Python\\Python35-32\\;C:\\Users\\Hasee\\AppData\\Local\\Programs\\Python\\Python36-32\\Scripts\\;C:\\Users\\Hasee\\AppData\\Local\\Programs\\Python\\Python36-32\\;C:\\Java\\jdk1.6.0_22/bin;C:\\Users\\Hasee\\AppData\\Local\\GitHubDesktop\\bin;C:\\Users\\Hasee\\AppData\\Roaming\\npm', 'COMMONPROGRAMW6432': 'C:\\Program Files\\Common Files', 'PROCESSOR_REVISION': '5e03', 'JAVA_HOME': 'C:\\Java\\jdk1.6.0_22', 'ALLUSERSPROFILE': 'C:\\ProgramData', 'FPS_BROWSER_USER_PROFILE_STRING': 'Default', 'HOMEDRIVE': 'C:', 'PROGRAMDATA': 'C:\\ProgramData', 'PROCESSOR_ARCHITEW6432': 'AMD64', 'USERPROFILE': 'C:\\Users\\Hasee', 'PROCESSOR_LEVEL': '6', 'VISUALSVN_SERVER': 'F:\\lyh_SVN_Location\\', 'SYSTEMROOT': 'C:\\Windows', 'TMP': 'C:\\Users\\Hasee\\AppData\\Local\\Temp', 'COMSPEC': 'C:\\Windows\\system32\\cmd.exe', 'PROMPT': '$P$G', 'CLASSPATH': '.;C:\\Java\\jdk1.6.0_22/lib/tools.jar;C:\\Java\\jdk1.6.0_22/lib/dt.jar', 'NUMBER_OF_PROCESSORS': '2', 'ONEDRIVE': 'F:\\MicrosoftOneDrive\\OneDrive', 'HOMEPATH': '\\Users\\Hasee', 'APPDATA': 'C:\\Users\\Hasee\\AppData\\Roaming', 'COMMONPROGRAMFILES': 'C:\\Program Files (x86)\\Common Files', 'PROCESSOR_IDENTIFIER': 'Intel64 Family 6 Model 94 Stepping 3, GenuineIntel', 'LOGONSERVER': '\\\\DESKTOP-3E4J31B', 'PUBLIC': 'C:\\Users\\Public', 'VS140COMNTOOLS': 'E:\\学习工作\\VisualStudio2015\\Common7\\Tools\\', 'USERDOMAIN': 'DESKTOP-3E4J31B', 'LOCALAPPDATA': 'C:\\Users\\Hasee\\AppData\\Local', 'PYTHONIOENCODING': 'utf-8', 'PROGRAMW6432': 'C:\\Program Files', 'SESSIONNAME': 'Console', 'COMPUTERNAME': 'DESKTOP-3E4J31B', 'PSMODULEPATH': 'C:\\Program Files\\WindowsPowerShell\\Modules;C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\Modules;F:\\lyh_SVN_Location\\PowerShellModules', 'USERNAME': 'lyh165', 'COMMONPROGRAMFILES(X86)': 'C:\\Program Files (x86)\\Common Files', 'WINDIR': 'C:\\Windows', 'PROGRAMFILES': 'C:\\Program Files (x86)', 'TEMP': 'C:\\Users\\Hasee\\AppData\\Local\\Temp', 'SYSTEMDRIVE': 'C:', 'FPS_BROWSER_APP_PROFILE_STRING': 'Internet Explorer', 'PROCESSOR_ARCHITECTURE': 'x86', 'PROGRAMFILES(X86)': 'C:\\Program Files (x86)', 'PATHEXT': '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC', 'GTK_BASEPATH': 'C:\\Program Files (x86)\\GtkSharp\\2.12\\', 'USERDOMAIN_ROAMINGPROFILE': 'DESKTOP-3E4J31B', 'OS': 'Windows_NT'})
C:\Users\Hasee\Desktop\Python_七月在线\01-Python课程___Python基础入门班\Code\第5课 文件访问与函数式编程入门
('/Users/Hasee/Desktop/Python_七月在线/01-Python课程___Python基础入门班/Code/第5课 文件访问与函数式编程入门', 'output.txt')
('/Users/Hasee/Desktop/Python_七月在线/01-Python课程___Python基础入门班/Code/第5课 文件访问与函数式编程入门/output', '.txt')
!end!


四、 shutil库 基本看以看作os的补充,它提供copyfile()方法,来复制你的文件
shutil基本使用
代码展示

# 四、 shutil库 基本看以看作os的补充,它提供copyfile()方法,来复制你的文件
print('四、 shutil库')
import shutil
shutil.copyfile('/Users/Hasee/Desktop/Python_七月在线/01-Python课程___Python基础入门班/Code/第5课 文件访问与函数式编程入门/output.txt','/Users/Hasee/Desktop/Python_七月在线/01-Python课程___Python基础入门班/Code/第5课 文件访问与函数式编程入门/hello/output.txt')

'''
4.1、列出当前目录下的所有目录:
#  第一个 x 是每一个参数 第二个x是一个数组
# (.)当前目录的位置
# if os.path.isdir(f) 如果f 是一个文件夹就会返回true
推导
lis = [i * 2 for i in range(10)]
print(lis)
'''

[x for x in os.listdir('.') if os.path.isdir(x)]
print([x for x in os.listdir('.') if os.path.isdir(x)])

#4.2、只想列出.py文件
# 第二个x是一个数组 进行遍历当前目录,如果是文件并且进行文件的分割获取最后一部分是.py
# 然后复制给第一个x参数 再将第一个x加入到第二个x数组里面
[x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py']
print([x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py'])
print('!end!')

控制台打印

四、 shutil库
['hello', 'PPT']
['文件访问与函数式编程入门.py']
!end!

五、序列化和反序列化(JSON一种多语言标准统一的格式)
序列化

序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程。
在序列化期间,对象将其当前状态写入到临时或持久性存储区。
以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

自身理解

自身也不太懂,需要多看相关知识
序列化:需要将某些数据持久化存储到磁盘中。下次运行的时候从磁盘中读取相关数据
反序列化:把变量内容从序列化的对象重新读取到内存中

代码展示

#五、序列化 和 反序列化 (使用pickle包,cpickle(C语言编写比较快一点,在python2的时候可以使用) )
'''
什么序列化?
程序运行过程中,所有变量都是在内存中操作的,当程序一旦执行完毕,结束退出后。
变量占有的内存就被操作系统回收了。
因此我们需要将某些数据持久化存储到磁盘中。下次运行的时候从磁盘中读取相关数据

我们将变量从内存变成可存储或者传输的过程称之为序列化。
在python中叫picking。
在其他语言中称之为 serialization、marshaling、flattening等等
说的都是同一个意思。

反之、则为反序列化。称之为unpickling,
把变量内容从序列化的对象重新读取到内存中
'''
print('五、序列化 和 反序列化')

# 5.1怎么把一个对象序列化
import pickle
# 此处定义一个dict 字典对象
d = dict(name = 'lyh',age = 22,score = 80)
str = pickle.dumps(d) # 调用pickle的dumps函数进行序列化处理
print(str) # 二进制形式

# 定义和创建一个file文件对象,设定模式为wb(写入二进制文件)
f = open('dump.txt','wb')
# 将内容序列化写入到file文件中
pickle.dump(d,f) # 第二个参数是放到那个文件中去
f.close() # 最后关闭掉文件资源


# 5.2反序列化
'''
就是把刚刚的搞成的'序列化'的码,转成python看得懂的object
'''
import pickle

# 从之前序列化的dump.txt文件里边读取内容
f = open('dump.txt','rb') # 设置文件选项模式为 rb (读二进制)
d = pickle.load(f) # 调用load做反序列处理过程
f.close() # 关闭文件资源
print(d)
print('name is %s' %d['name'])

# 5.3 为了保证2.3的和谐,可以使用这个方法保证import正确
'''
try:
    import cPickle as pickle # 用cPickle 重命名为 pickle
 except ImportError:
    import pickle # 如果python3.x 里面没有cPickle 那么 就走到这里except
'''

# 5.4 json (一个标准)
'''
python的序列化 和 反序列化 只有python能看懂
其他语言看不懂
同时,也许你们会发现,这个pickle完的东西,是让人看不懂的。
只有python自己可以把它upickle回来。
如果我们有一个文件现在存下来,并且日后要在其他地方用到的话,
我们可以用json来做序列化
python的数据结果跟json有非常完美的兼容

如果你有一个比较结果话的数据 想要序列化,并且想要别的地方 别的语言也能看懂。
那么你可以用json来做
'''

import json
# 定义dict 字典对象
d1 = dict(name = 'l',age = 23,score = 99)
str = json.dumps(d1) # 调用json的dumps函数进行json序列化处理
print(str)

# 调用json的loads函数进行反序列化处理
d2 = json.loads(str)
print(d2)
print('name = %s' %d2['name'])
print('!end!\n')

控制台打印

五、序列化 和 反序列化
b'\x80\x03}q\x00(X\x05\x00\x00\x00scoreq\x01KPX\x03\x00\x00\x00ageq\x02K\x16X\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00lyhq\x04u.'
{'score': 80, 'age': 22, 'name': 'lyh'}
name is lyh
{"score": 99, "age": 23, "name": "l"}
{'score': 99, 'age': 23, 'name': 'l'}
name = l
!end!

六、高阶函数(lambda匿名函数、reduce二元操作函数、map函数、filter过滤函数)
百度维基

在无类型 lambda演算,所有函数都是高阶的;
在有类型 lambda演算(大多数函数式编程语言都从中演化而来)中,
高阶函数一般是那些函数型别包含多于一个箭头的函数。
在函数式编程中,返回另一个函数的高阶函数被称为柯里化的函数。
在很多函数式编程语言中能找到的 map 函数是高阶函数的一个例子。
它接受一个函数 f 作为参数,并返回接受一个列表并应用 f 到它的每个元素的一个函数。

自身理解

比较高级的函数

代码展示

# 六、高阶函数
'''
可以把别的函数作为参数传入的函数 叫高阶函数
举个列子 : 求绝对值的函数abs()
'''
print('六、高阶函数(lambda、reduce)')
print(abs(-10))
print(abs)

#6.1 简单的高阶函数
def add(x,y,f):
    return f(x) + f(y)

print(add(-5,6,abs))

#6.2 匿名函数
'''
python 使用lambda来创建匿名函数
    lambda只是一个表达式,函数体比def简单很多
    lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中风中有限的逻辑进去
    lambda函数拥有自己的命名空间,且不能访问自由参数列表之外或全局命名空间里的参数
    虽然lambda函数看起来只能写一行,却不等同于C或C++的内练函数。后者的目的是调用小函数时不占用栈内存从而增加运行效率

    最重要一点,lambda表达式可以体现你的逼格。华尔街和伦敦银行高街最逼的一群人都是
    自诩用且只用函数式编程的
    什么事函数式编程?就是类似于全篇程序都用python中lambda这样的一行代码来解决问题。。
    为什么他们逼?因为数学家学编程的时候,脑子还在数学公式这条线上
    他们不会写面对对象变成。只会想写出一条公式来解决问题。
    其实是智商堪忧的体现。
    但是因为投行基金们很倾向聘用这群数学家转型的半吊子程序员。
    他们的使用习惯于是成了圈内高逼的体现。嗯。葡萄就是这么酸
语法
lambda函数的语法 只包含一个语句,如下
lambda[arg1[,arg2,.....argn]]:expression
'''
sum = lambda arg1,arg2: arg1 + arg2
'''
def sum(arg1,arg2):
    return arg1 + arg2
'''
print(sum(10,20))


# 除了lambda本社,python还提供了其他几个辅助工具,让你的函数式代码块更加牛逼:

#6.3、reduce (在functools包里面)
'''
Python中的reduce内建函数 是一个二元操作函数。
他用啦将一个数据集合(列表、元组等)中的所有数据进行如下操作
传给reduce的函数func()(必须是一个二元操作函数)
现对集合中的第1,2个数据进行操作,得到的结果再与第三个数据用func()函数运算。
最后得到一个结果。

顾名思义,reduce 就是要把一个list给缩成一个值。
所以你必须用二元操作函数。

'''
from functools import reduce
l = [1,2,3,4,5]
print(reduce(lambda x,y: x + y,l))
# 这里代表着,把list中的值,一个个放进lambda的x,y中
#如果你给出一个初始值,可以放到list后面
print(reduce(lambda x,y: x + y,l,10))

#6.4、map
'''
格式: map(func,seq1[,seq2])
map 函数应用于每一个可迭代的项,返回的是一个结果list。
如果有其他的可迭代参数传进来,map函数则会把每一个参数都以相应的处理函数进行迭代处理。
map()函数接收两个参数,一个是函数。一个是序列。
map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。

python函数式编程中的map()函数是将func作用于seq中的每一个元素,
并用一个列表给出返回值。
map可以使用任务的lambda函数操作。
本质上是把原有的list根据lambda发展变成另一个list

!!!
py3里面,外面需要套一个list
这里是为了让里面的值给显示出来,要不然你会得到这个map函数
而不是里面的值
py2的童鞋不虚
'''

l = [1,2,3]
new_list = list(map(lambda i:i+1,l))
print(new_list)

# 我们也可以把两个数组搞成一个单独的数组
l2 = [4,5,6]
new_list = list(map(lambda x,y:x+y,l,l2)) # [5,7,9]
print(new_list)

#6.5、filter
'''
语法:filter(func,seq)
filter()函数可以对序列做过滤处理,就是说可以使用一个自定的函数过滤一个序列。
把序列的每一项传到自定义的过滤函数里处理,并返回结果做过滤。
最终一次性返回过滤后的结果。
和map()类似。filter()也接受一个函数和序列。
和map()不同的是,filter()把传入的函数依次作用于每个元素
然后根据返回值是true还是false决定保留还是丢球该元素。
'''
l = [100,20,24,50,110]
new = list(filter(lambda x : x < 50,l))
# 同理,py3得套个list转换list函数,便于打印出来
print(new)

# 熟悉运用以上三个玩意儿,你就可以一行写出几乎所有的复杂计算了
print('!end!\n')

控制台打印

六、高阶函数(lambda、reduce)
10

11
30
15
25
[2, 3, 4]
[5, 7, 9]
[20, 24]
!end!

七、装饰器(1.wrapper、2.decorator|多个decorator|带参数的decorator、3.decorator这个东西也可以写成class样式、4.装饰器的副作用)
代码展示

#七、装饰器
'''
7.1、装饰器就是函数的[包装]:
我们来一个代码

作用就是在运行函数的前后多做一点事情
比较类似的一个生命周期的开始和结束
'''
print('七、装饰器')
def hello(fn): # 传递一个函数
    def wrapper(): # 作为装饰器,
        print('hello,%s' %fn.__name__) # 导入这个方程的名字是什么
        fn() # 进行这个函数
        print('goodby,%s' %fn.__name__) # 然后告诉系统这件事情做完了
    return wrapper # 返回自己
@hello # 用@装饰这个函数
def foo():
    print('i am foo')
foo()


#7.2、decorator|多个decorator|带参数的decorator
'''
你可以看到如下的东西
1、函数foo前面有个@hello的‘注释’,hello 就是我们前面定义的函数hello
2、在hello函数中,其需要一个fn的函数(这就用来做回调的函数)
3、hello函数中返回了一个inner函数wrapper,这个wrapper函数回调了传进的fn.
并在回调前后加了两条语句

所以,本质上来讲,用@decorator来装饰某个函数时,其实是做了下面这件事情儿
@decorator
def func():
    pass
    变成了==>
    func = decorator(func)
    在简单点说,就是把一个函数传到另一个函数中,在调回给自己
所以:
hello(foo)返回了wrapper()函数,所以,foo其实变成了wrapper的一个变量,
而后面的foo()执行其实变成了wrapper()

同理,我们也可以搞多几个decorator

@decorator_one
@decorator_two
def func():
    pass
相当于
func = decorator_one(decorator_two(func))

你还可以给这个decorator带个参数:
@decorator(arg1,arg2)
def func():
    pass
相当于:
    func = decorator(arg1,arg2)(func)
好了,讲这么多比较复杂,我们来看个网页编程的case:

'''
def makeHtmlTag(tag,*args,**kwds):
    def real_decorator(fn):
        css_class = " class='{0}'".format(kwds["css_class"])\
                                    if "css_class" in kwds else ""
        def wrapped(*args,**kwds):
            return "<"+tag+css_class+">" + fn(*args,**kwds) + ""
            #hello world
            #
        return wrapped
    return real_decorator
#makeHtmlTag1(makeHtmlTag(func))
@makeHtmlTag(tag="b",css_class="bold_css")
@makeHtmlTag(tag="i",css_class="italic_css")

def hello():
    return "hello world"
print(hello()) # hello是最后才回调的

"""
最主要的是 def 写自己 回自己

在上面这个例子中,我们可以看到:makeHtmlTag有两个参数。
所以,为了让hello = makeHtmlTag(arg1,arg2)(hello)成功,
makeHtmlTag必须返回一个decorator
(这就是为什么我们在makeHtmlTag中加入了real_decorator()的原因),
这样一来,我们就可以进入到decorator的逻辑中去了---
decorator得返回一个wrapper,wrapper里回调hello

    在这里差一个知识,我们看到parameters里面有个(*args,**kwargds)指的是
    一个星星,指的是这里可以随便放多少个参数,内部提及的时候,当做一个list看
    两个星星指的也是随便多少个参数,但是这里可以带上参数的名字,比如
    (x ='1',y = '2'),内部提及的时候,当做一个dict看。
"""

#7.3、decorator这个东西,也可以写成class样式:
class myDecorator(object):
    def __init__(self,fn):
        print('inside myDecorator.__init__()')
        self.fn = fn

    def __call__(self):
        self.fn()
        print('inside myDecorator.__call__()')
@myDecorator

def aFunction():
    print('inside aFunction()')

print('Finished decorating aFunction()')
aFunction()

#7.4、decorator用class修改网页的case
class makeHtmlTagClass(object):
    def __init__(self,tag,css_class=""):
        self.tag = tag
        #  " class='{0}'" 其中'{0}'是一个占位符,可以在format填写值
        self.css_class = " class='{0}'".format(css_class) \
                                        if css_class !="" else ""
    def __call__(self,fn): # 相当于上面的 real_decorator
        def wrapped(*args,**kwargs):
            return "<"+self.tag+self.css_class+">" \
                        + fn(*args,**kwargs) + ""
        return wrapped
@makeHtmlTagClass(tag='b',css_class='bold_css')
@makeHtmlTagClass(tag='i',css_class='italic_css')
@makeHtmlTagClass(tag='c',css_class='ctalic_css')
# func = decorator_one(decorator_two(func))

def hello(name):
    return "hello,{}".format(name)
print(hello('baby'))

#7.5、装饰器的副作用
'''
装饰器的副作用:
y因为decorator的因素,我们原本的函数其实已经变成了一个wrapper函数。
比如,你在调用__name__的时候,他会告诉你,这是wrapper,而不是foo或者hello
当然,虽然功能效果不变,但是有些处女座的童鞋会觉得不爽
所以,python的functool包提供了一个叫wrap的decorator来消除这样的副作用
'''

from functools import wraps
def hello(fn):
    @wraps(fn) #如果没有 则 print(foo.__name__) 为wrapper
    def wrapper():
        print("hello %s" %fn.__name__)
        fn() # 如果没有添加@wraps(fn) 那么fn()这个函数是在wrapper函数里面的,所以会输出wrapper
        print("hello %s" %fn.__name__)
    return wrapper
@hello
def foo():
    print('i am foo')
    pass
foo()
print(foo.__name__)
print(foo.__doc__)
print('!end!\n')

控制台打印

七、装饰器
hello,foo
i am foo
goodby,foo
hello world
inside myDecorator.__init__()
Finished decorating aFunction()
inside aFunction()
inside myDecorator.__call__()
hello,baby
hello foo
i am foo
hello foo
foo
None
!end!


八、递归例子
代码展示

斐波那契数列
https://baike.baidu.com/item/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97/99145?fr=aladdin


#八、递归例子
'''
1
1
2
3
5
8
fib(5) = fib(3) + fib(4) = fib(2) + fib(2) + fib(1) -- + fib(1) + fib(2)
fib(4) = fib(2) + fib(3) = fib(2) + fib(2) + fib(1)
fib(3) = fib(1) + fib(2) = 
fib(2) = 2
fib(1) = 1
'''
print('八、递归例子')
from functools import wraps
def memo(fn): #记忆的方法
    cache = {} # 存下来的值(是一个字典)
    miss = object()
    @wraps(fn)

    def wrapper(*args):
        result = cache.get(args,miss)
        if result is miss:
            result = fn(*args)
            cache[args] = result
        return result
    return wrapper

@memo
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

print(fib(6))
print('!end!\n')
'''
我们知道,这个递归是相当于没有效率的,因为会重复调用。
比如:我们要计算fib(5),于是其分解成fib(4)+fib(3),而fib(4)分解fib(3)+fib(2),
fib(3)又分解fib(2)+fib(1)...
你可以看到,基本上来说,
fib(3),fib(2),fib(1)在整个递归过程中被调用了两次。
而我们用decorator,在调用函数前查询一下缓存,如果没有才调用,
有了就缓存中反值。一下子,
这个递归从二叉树式的递归成了线性的递归
'''

控制台打印

八、递归例子
8
!end!

九、偏函数
代码展示

#九、偏函数 (import functools)
'''
python的functools模块提供了很多有用的功能,其中一个就是偏函数
偏函数又可以翻译成部分函数,大概意思就是说,只设置一部分参数。
'''
print('九、偏函数 ')
print(int('12345'))
print(int('12345',base=8))
print(int('12345',16))

'''
假设要转换大量的二进制,每次都传入int(x,base=2)非常麻烦,于是,
我们想到,可以定义一个int2()函数。默认把base=2传进去:
'''
def int2(x,base=2):
    return int(x,base)
print(int2('1000000'))

import functools
int2p = functools.partial(int,base=2)
print(int2p('1000000'))

max2 = functools.partial(max,10)
print(max2(5,6,7))
# 相当于 args = (10,5,6,7)
args = (10,5,6,7)
print(max(*args))

控制台打印

九、偏函数 
12345
5349
74565
64
64
10
10

十、实战(作业)
题目

今天的课程实践会结合上节课给你们的代码内容。

上节课我们讲了如果写个Dataset类来帮我们下载和处理数据。

这节课我们学习了文本的读入,那我们就来做做更加复杂的内容:

本节课的压缩包里有一个数据文件,是我们今天实战的数据。

这是美国亚利桑那州Pima印第安女人患有糖尿病状况的数据集(因为他们的得病率很高)。

这个数据是一个txt文件(其实是个csv),每一行就是一个数据条,长这样:

6,148,72,35,0,33.6,0.627,50,1
1,85,66,29,0,26.6,0.351,31,0
8,183,64,0,0,23.3,0.672,32,1
1,89,66,23,94,28.1,0.167,21,0
0,137,40,35,168,43.1,2.288,33,1
其中,前面N-1个数据,分别是一些身体的指标,比如:血压,血糖,身高,是否怀孕等等。 最后第N个数据点是记录她是否患有糖尿病,它只有0或者1两种可能。这也就是我们说的数据标签。

所以,这里我们脑海中应该浮现的数据结构如下:

x = [
        [6,148,72,35,0,33.6,0.627,50],
        [1,85,66,29,0,26.6,0.351,31],
        [8,183,64,0,0,23.3,0.672,32],
        ...
    ]

y = [1,0,1,0,1,1,1,0,...]
所以,这是一个二元分类问题。

参照上一堂课的内容,我们要做如下的修改:

Dataset这个类中的download_data函数要被修改,改成我们从外部读入数据的过程。并且要把我们的x和y分开储存,并返回。

我们这次依旧是以0.7的比率分开训练集和测试集。当我们得到区分开的 x_train, x_test, y_train, y_test以后,我们把这些个数据分别用Json或者Pickle的方法序列化在我们文件夹内。然后我们新建一个程序,从中反序列化我们处理好的数据。并进行之后的Machine Learning过程。

当我们把一个model训练好以后,我们代入全部的x_test数据,并得到我们预测出来的分类值y_preds。我们把这个值(list)与我们的y_test相互比较,用一些正确率统计的方法计算我们model的准确率,并用lambda函数来实现

预测数据的直接准确率怎么计算?

准确率 = (对的数据数 / 全部数据数) * 100%

高级一点,

我们可以再实现一点其他准确率计算方式:

AUC,MSE,...

详情可见附录的cheat sheet,或者自行百度。

OK!

自己动手尝试一下吧!

么么哒

代码:ufcq

明天将会更新→0006.Python基础入门班_第6课、高级面向对象

代码都是上传百度云

你可能感兴趣的:((2018-03-23)0005.Python基础入门班_第5课、文件访问与函数式编程入门)