python成长之路第三篇(4)_作用域,递归,模块,内置模块(os,ConfigParser,hashlib),with文件操作

打个广告欢迎加入linux,python资源分享群群号:478616847

目录:

1、作用域

2、递归

3、模块介绍

4、内置模块-OS

5、内置模块-ConfigParser

6、内置模块-hashlib

7、with文件操作

代码执行环境默认为3.5.1

一、作用域

(1)什么是作用域,官方来说作用域就是就是有不同的命名空间,就像下面的代码一样,a=1它的作用域是全局的,也在全局的命名空间当中,当函数 action中的a=2它就在局部的作用域中,也在局部的命名空间当中。

a = 1def action():    a = 2action()print(a)
我们来看,上面的代码,当我们运行完成后我们得到的结果是1,这就是作用域的结果,明明是相同的变量但是a=2是在局部作用域当中所以当我们打印a的时候还是1。
(2)那么我们如果想要在局部作用域中使用全局作用域中的变量和内容怎么办,python中的global语句是被用来声明全局的,在函数内可把全局变量重新赋值。
a = 1def action():    global a    a = 2action()print(a)

二、递归

在此之前我们已经了解到了函数,还介绍了几个内置函数,那么我们想,我们在使用函数的时候都是来引用这个函数的函数名也就是像上面的例子中的action(),那么我们说,函数本身能否来去调用函数本身呢?答案是能,那么我们将这种调用的方法叫做递归!递归的意义在于提示代码执行效率,在这里我们来使用两个经典的例子

(1)阶乘

什么是阶乘,我们可以这么来看,有一个数是n,那么n的阶乘定义就是nx(n-1)x(n-2)x(n-3)…..x1

首先我们用普通的方法来去实现:

n = 4def  factorial():    global n  #设置全局变量    for i in range(1,n):        n*=ifactorial() #执行函数print(n)
这个很容易理解,因为是乘法运算所以先乘哪个都一样,所以我们使用range,生成1-n的数字,那么i就分别等于1,2,3因为range的特点最后的数字会比n小,然后在使用 n*=i也就是 n = n*i,最终就算出了结果
我们来看递归版本:
def factorial(n):    if n == 1:        return n    else:        return n*factorial(n-1)c = factorial(5)print(c)

首先我们先不管它跟普通方法的代码量和优点,我们就先来理解这个递归,有条件的同学使用下pycharm断点来看下执行过程,好我们来解释下这个流程:

递归的返回值:

我们来看首先我们传入数字n = 5 ,然后进入函数,来执行函数自己调用自己的操作,那么我按照现在的理解来看,当调用第四次n等于了1,那么按照道理来说执行了return n,那么这时候按理来说c应该等于1,为什么c不等于1而是120呢?

我们来剖析递归的流程请看图
 
 
我们来解释一下
①当n = 5 的时候调用 n = 4 当n = 4的时候调用 n=3 一次类推
②那么我们调用函数的返回值的表达式是return n*factorial(n-1)这样我们就可以知道每次返回的是下一次的执行结果,n*factorial(n-1)就等于 
  5 * (5-1)*(4-1)*(3-1)*(2-1)*1 
③因为python的特性所以每次返回的是计算出来的值然后就变成了

fact(5) -> 5*factorial(4) -> 5*(4*(3*(2*factorial(1))))  #这是最终结果的表达式,1是从n = 1返回上来的
             -> 5*(4*(3*(2)))  #将每一层的值计算出来返回上层
             ->  5*(4*(6))
             ->  5*24    #顶层
             -> 120     #最终c = 120

(2)二分查找

上面的例子我们看不出递归如何提升了代码的执行效率那么我们看这个例子,什么是二分查找,我们假设这么个情景,我们需要判断一个数,是否在一组数中,假设这组数有 100个,那么我们需要挨个进行比较,可以使用for循环,或者if in,if in 也是使用的 for循环的机制来去找,那么加入这组数有10000个呢?并且要找的数在最后,那么岂不是要循环10000次?这样的方法太low,所以出来了二分查找。

递归写法:

def  seek(data,find_in):  #定义一个函数,接收数组,和要找的值    mid = int(len(data)/2) #将这个数组除2    if len(data) >1: #判断剩余的数组是否大于1,如果大于1则进行二分算法否则就是没找到退出        if data[mid] > find_in: #判断这个除以2的数大于还是小于我们要找的数            seek(data[:mid],find_in)#如果大于则确定这个数在数组中间位置的右边,并将值传给这个函数,再次判断        elif data[mid] < find_in:            seek(data[mid:],find_in)#如果小于则确定这个数在数组中间位置的左边        else: #当这个数组不大于也不小于我们要找的数时,那就表示这个数组等于 我们要找的数            print("ok")#那么也就是说我们要找的数在这个数组中    else:        print("no")datas = range(1,10000000)seek(datas,1000000)
那么这样写就可以用少量的次数就能判断我们要找的数是否在数组里
 
bisect模块
python的标准库中bisect模块也是非常有效的实现二分查找,这个模块是判断数字实在数组中的哪里,如果数字小于等于数组中的最小的数小则返回0,数字大于等于数组中的最大的数则返回最大的数在列表中的位置,否则返回这个数在列表中的正确位置。
 
bisect.bisect源码剖析:
bisect.bisect
def bisect_right(a, x, lo=0, hi=None): #a是传入的列表,x是要找的数字,lo和hi不用传入

if lo < 0:    #先判断 lo列表的长度,默认为0 ,这里是报错提示,传入的lo不能比0小        raise ValueError(‘lo must be non-negative‘)    if hi is None:  #判断hi是否为空        hi = len(a)  #如果为空则把列表a的长度赋值给hi    while lo < hi:  #判断lo是否小于hi         mid = (lo+hi)//2  #如果不小于则 执行mid = (lo+hi)//2也就是取出列表中的中间数的标识符        if x < a[mid]: hi = mid  #判断要找的数字是否小于传入列表的中间数,如果小于则hi = mid 也就是中间数的标识符然后再次循环        else: lo = mid+1 #只要要找的数不小于传入列表的中间数则执行这句 lo = mid+1,    return lo

bisect = bisect_right   #这句话表示向下兼容,意思是使用函数bisect.bisect就等于bisect.bisect_right
#推荐大家传入变量来去进行pycharm的断点看看执行流程

三、模块介绍

首先什么是模块,模块的定义呢在这里就是实现某个功能的代码集合

(1)模块分为三种:

  • 自定义模块

  • 内置模块
  • 开源模块

自定义模块,就是我们自己来写功能,然后其他的代码来去调用我们的这个功能

例子: 就像下面的图一样将不同的功能分开

内置模块,就是python自带的一些功能

开源模块,就是别人开发好的方法功能,我们安装到我们的python中使用

(安装方法)

在linux下安装:

在使用源码安装时,需要使用到gcc编译和python开发环境

yum install gcc

yum install python-devel

下载源码
解压源码
进入目录
编译源码    python setup.py build
安装源码    python setup.py install

(2)导入模块

  • import

  • from  xxx   import   xxx
  • from  xxx   import   xxx   as   xxx
  • from  xxx   import   *

import,和from xxx  import xxx

用于导入相应的模块,模块其实就是一些函数和类的集合文件,它能实现一些相应的功能,那么他们的区别是什么

我们来看个例子:

这里以接下来要说的os模块为例,os模块下有rename方法是用来重命名文件或者目录的,我们清晰的看到用from导入的模块后我们直接就可以使用rename方法,而import就需要我们是os.rename来使用这个rename方法(也就是需要指定模块名)

from os  import rename

rename(‘method.py‘,‘test.py‘)

import os

os.rename(‘method.py‘,‘test.py‘)
这里推荐import来去导入因为这样可以使你的程序更加易读,也可以避免名称的冲突
from  xxx   import   xxx   as   xxx
我们可以发现这就是给方法或者模块起个别名
from os  import rename as newname

newname(‘method.py‘,‘test.py‘)

import os as os_name

os_name.rename(‘method.py‘,‘test.py‘)
最后一个就不用解释了相信大家都明白了。

(3)sys.path

sys.path这是什么鬼?我们发现没有在系统自带的模块中我们只需要import就可以直接导入,然而我们自己写的模块就只能导入当前路径下的,这就是因为这个sys.path下面存储着系统查找模块时的路径,所以喽就能系统自带的模块了,就跟linux查找命令一样的道理,那么我们可不可以把其他路径加入到这里面呢,让我们好导入其他目录下的自定义模块,这里是肯定可以的,我们使用sys.path.append(‘路径‘)来去添加

python模块中有一个

包的概念,就是说目录下有一个 __init__.py文件那么我们就称为这个目录为包

例子:

首先我们常见的目录结构是一个文件夹下面接着好几个包就像下面,每个包中存着各自要实现的功能代码

我们使用下面两个方法将test1中的main文件可以导入test目录下的任意包中的方法:

os.path.abspath()

这个功能是获取当前文件下的目录

sys.path.append(‘路径‘)

这个方法是添加系统默认查找路径

那么我们在main.py文件中就可以这么写

import osimport sysPATH = os.path.dirname(os.path.dirname(__file__)) 
#因为我们这里的目录结构是二层目录所以我们就需要获取当前文件的目录的目录,这样才可以获取到我们的父目录testsys.path.append(PATH)
#将获取的路径添加到系统默认查找路径中,然后我们就可以使用test目录下的包中的方法了

if __name__ == "__main__":   #这句话表示这个文件是个入口    from test2 import hellow  #导入这个包中的这个文件    hellow.hello()           #执行这个文件中的hello函数
 
#hellow.py内容:
def hello():    print("How are you doing tomorrow!!")
 

四、内置模块-OS

这个模块提供了一种便携式的方式使用操作系统来处理目录和文件相关的功能。

官方说明

(1)os.getcwd()

获取当前工作目录,即当前python脚本工作的目录路径

import os
     print(os.getcwd())
     #结果为E:\pycharm\exercise

(2)os.chdir("dirname")

改变当前脚本工作目录;相当于shell下cd

  #请在linux下执行
  import os  path = "/tmp"  # 查看当前工作目录  retval = os.getcwd()  print ("当前工作目录为 %s" % retval)  # 修改当前工作目录  os.chdir( path )  # 查看修改后的工作目录  retval = os.getcwd()  print ("目录修改成功 %s" % retval)

(3)os.curdir

  返回当前目录: 返回值为(‘.‘)

(4)os.pardir

获取当前目录的父目录字符串名:返回值为(‘..‘)

(5)os.makedirs(‘dir1/dir2‘)

可生成多层递归目录余mkdir –d /dir1/dir2

(6)os.removedirs(‘dir1/dir2‘)

若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推,如果在dir1下面建立个文件dir1就不会被删除

(7)os.mkdir(‘dir‘)

生成单级目录;相当于shell中mkdir dir

(8)os.rmdir(‘dir‘)    
   删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dir
(9)os.listdir(‘dirname‘)    
   列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
(10)os.remove()  
   删除一个文件
(11)os.rename("oldname","newname")  
    重命名文件/目录
(12)os.stat(‘path/filename‘)  
    获取文件/目录信息
(13)os.sep    
    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
(14)os.linesep    
    输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
(15)os.pathsep    
    输出用于分割文件路径的字符串
(16)os.name    
    输出字符串表示当前使用平台。win->‘nt‘; Linux->‘posix‘
(17)os.system("bash command")  
    运行shell命令,直接显示
     import os     print(os.system("ping  www.baidu.com"))
(18)os.environ  
    获取系统环境变量
(19)os.path.abspath(path)  
    返回path规范化的绝对路径   
     import os     print(os.path.abspath(‘hellow.py‘))
(20)os.path.split(path)  
    将path分割成目录和文件名二元组返回,不会判断文件或者目录是否存在    
     import os     fileName=r"C:\Users\SS\test.txt"     print(os.path.split(fileName))
(21)os.path.dirname(path)  
    去掉文件名,返回目录路径   
     import os        print(os.path.dirname(os.__file__))
(22)os.path.basename(path)  
    返回path最后的文件名。如果path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素  
    import os      print(os.path.basename(r"d\aaa\aa.txt") )
(23)os.path.exists(path)  
    如果path存在,返回True;如果path不存在,返回False
(24)os.path.isabs(path)  
    如果path是绝对路径,返回True
(25)os.path.isfile(path)  
    如果path是一个存在的文件,返回True。否则返回False
(26)os.path.isdir(path)  
    如果path是一个存在的目录,则返回True。否则返回False
(27)os.path.join(path1[, path2[, ...]])  
    将多个路径组合后返回,第一个绝对路径之前的参数将被忽略   

     imprort os

     os.path.join(‘b‘,‘b‘,‘ss.txt‘#输出#‘b/b/ss.txt’
(28)os.path.getatime(path)

    返回path所指向的文件或者目录的最后存取时间
(29)os.path.getmtime(path)  
    返回path所指向的文件或者目录的最后修改时间
注!:28和29返回的时间是unix时间戳,可以使用detetime库来处理这个时间戳
import datetime, osa = os.path.getmtime(‘/‘)aa = datetime.datetime.fromtimestamp(t)aaa = aa.strftime(‘%Y‘) # %Y是时间处理的格式,只能返回年份。更多格式写法请百度print aaa
 

五、内置模块-ConfigParser

这个内置模块呢一般用处用来做配置文件的操作,那么这个模块能够处理什么样的配置文件呢?我们来看下

例子:

读操作

-read(filename) 直接读取ini文件内容
-sections() 得到所有的section,并以列表的形式返回
-options(section) 得到该section的所有option
-items(section) 得到该section的所有键值对
-get(section,option) 得到section中option的值,返回为string类型
-getint(section,option) 得到section中option的值,返回为int类型

写操作
-add_section(section) 添加一个新的section
-set( section, option, value) 对section中的option进行设置

aaa文件内容
[a]one = 1two = ins

[b]one = 2two = ins
示例代码
#!/usr/bin/env python# -*- coding:utf-8 –*-
#首先我们加载模块import configparser
#创建一个config对象

c  = configparser.ConfigParser()
#读取aaa文件c.read("aaa")
#读取aaa中的section [‘a‘, ‘b‘]
print(c.sections()) 
#读取aaa中的section 是a 的option(选项的意思)
print(c.options(‘a‘)) #[‘one‘, ‘two‘]
#读取aaa中的section 是a 的所有键值对(选项和值) print(c.items(‘a‘))#[(‘one‘, ‘1‘), (‘two‘, ‘int‘)]
#读取aaa中的section 是a的option是one的值,返回的是str类型
print(c.get(‘a‘,‘one‘)) print(type(c.get(‘a‘,‘one‘))) # 1
#读取aaa中的section 是a的option是one的值,返回的是int类型
print(c.getint(‘a‘,‘one‘)) print(type(c.getint(‘a‘,‘one‘))) #1
 

写:

import configparser
#创建一个config对象

c  = configparser.ConfigParser()
#读取aaa文件c.read("aaa")
#在文件中添加section
c.add_section("c")
#在section(部分的意思)中添加键值对
c.set("c","one","2")c.set("c","two","1")
#最后写入文件c.write(open("aaa","w"))
#删除section为c的键值对onec.remove_option(‘c‘,‘one‘)
#写入文件c.write(open("aaa","w"))
官方入口

六、内置模块-hashlib

hashlib是个加密模块,主要提供了 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

import hashlibc = "test"
#这里要进行转换编码c = c.encode(encoding=‘utf-8‘)# ######## md5 ########

hash = hashlib.md5()hash.update(c)print(hash.hexdigest())

# ######## sha1 ########

hash = hashlib.sha1()hash.update(c)print (hash.hexdigest())

# ######## sha256 ########

hash = hashlib.sha256()hash.update(c)print (hash.hexdigest())

# ######## sha384 ########

hash = hashlib.sha384()hash.update(c)print (hash.hexdigest())

# ######## sha512 ########添加自定义的

hash = hashlib.sha512()hash.update(c)print (hash.hexdigest())

上面的算法虽然比较强,但是通过撞库仍然可以破解,所以为了防止这样,还可以在加密算法中key来做加密

import hashlibc = "test"c = c.encode(encoding=‘utf-8‘)key = "aaa"key = key.encode(encoding=‘utf-8‘)# ######## md5 ########hash = hashlib.md5(key)hash.update(c)print(hash.hexdigest())
 
hmac模块
python 还有一个 hmac 模块,它内部对我们创建 key 和 内容 再进行处理然后再加密
import hmacc = "test"c = c.encode(encoding=‘utf-8‘)key = "aaa"key = key.encode(encoding=‘utf-8‘)hash = hmac.new(key)hash.update(c)print(hash.hexdigest())

七、with文件操作

对于我们来说普通的操作文件每次执行完文件还要给他加上关闭的语句这样非常麻烦,所以python2.7以后就增加了with

with又支持同时对多个文件的上下文进行管理所以非常的方便

with open("aaa") as test1 ,open("ss","w") as test2:    test2.write(test1.read())
时间: 2024-10-25 13:48:11

python成长之路第三篇(4)_作用域,递归,模块,内置模块(os,ConfigParser,hashlib),with文件操作的相关文章

python成长之路第三篇(1)_初识函数

目录: 函数 1.为什么要使用函数 2.什么是函数 3.函数的返回值 4.文档化函数 5.函数传参数 文件操作(二) 1.文件操作的步骤 2.文件的内置方法 函数: 一.为什么要使用函数 在日常写代码中,我们会发现有很多代码是重复利用的,这样会使我们的代码变得异常臃肿,比如说: 我们要写一个验证码的功能 例子: 比如说我们要进行一些操作,而这些操作需要填写验证码 验证码代码:  1 import random   2 number_check = ''   3 for i in range(0,

python成长之路第三篇(2)_正则表达式

打个广告欢迎加入linux,python资源分享群群号:478616847 目录: 1.什么是正则表达式,python中得正则简介 2.re模块的内容 3.小练习 一.什么是正则表达式(re) 正则表达式相信很多人都熟悉了,在python中正则表达式的支持是通过re(regular expression)模块,正则表达式是可以匹配文本片段的模式,简单的是正则表达式就是普通的字符串,可以处理字符串.也就是说正则表达式的存在就是来处理文本字符串的 下面来熟悉下正则中的几个概念: 1.通配符 通配符是

我的Python成长之路---第三天---Python基础(12)---2016年1月16日(雾霾)

四.函数 日常生活中,要完成一件复杂的功能,我们总是习惯把“大功能”分解为多个“小功能”以实现.在编程的世界里,“功能”可称呼为“函数”,因此“函数”其实就是一段实现了某种功能的代码,并且可以供其它代码调用. 假设我们在编程过程中需要计算圆形的面积.如果我们不是用函数,每次需要计算原型面积的时候都需要这样 1 r1 = 12.34 2 r2 = 9.08 3 r3 = 73.1 4 s1 = 3.14 * r1 * r1 5 s2 = 3.14 * r2 * r2 6 s3 = 3.14 * r

python成长之路【第九篇】:网络编程

一.套接字 1.1.套接字套接字最初是为同一主机上的应用程序所创建,使得主机上运行的一个程序(又名一个进程)与另一个运行的程序进行通信.这就是所谓的进程间通信(Inter Process Communication,IPC).有两种类型的套接字:基于文件的和面向网络的. 第一种:基于文件的 因为两个进程运行在同一台计算机上,所以这些套接字都是基于文件的,这意味着文件系统支持他们的底层基础结构.这是能够说的通的,因为文件系统是一个运行在同一个主机上的多个进程之间的共享常量.第二种:基于网络的 基于

Python成长之路【第二篇】Python基础之数据类型

阅读目录 简介 1 什么是数据? x=10,10是我们要存储的数据 2 为何数据要分不同的类型 数据是用来表示状态的,不同的状态就应该用不同的类型的数据去表示 3 数据类型 数字(整形,长整形,浮点型,复数) 字符串 列表 元组 字典 集合 4 如何学习 #一:基本使用 1 用途 2 定义方式 3 常用操作+内置的方法 #二:该类型总结 1 存一个值or存多个值 只能存一个值 可以存多个值,值都可以是什么类型 2 有序or无序 3 可变or不可变 !!!可变:值变,id不变.可变==不可hash

我的Python成长之路---第三天---Python基础(13)---2016年1月16日(雾霾)

五.Python的常用的内置函数 Python为我们准备了大量的内置函数,如下图所示 这里我们只讨论红框内的内置函数 abs(x) 返回一个数的绝对值(模),参数可以是真说或浮点数 >>> abs(-10) 10 all(iterable) 如果可迭代对象(列表.元祖等)中所有的元素都是True,则返回True,否则返回False.相当于and >>> all([1, True, 1 == 1]) True any(iterable) 如果可迭代对象中任意一个元素是Tr

我的Python成长之路---第三天---Python基础(9)---2016年1月16日(雾霾)

一.集合 set和dict类似,也是一组key的集合,但不存储value.由于key不能重复,所以,在set中,没有重复的key. 集合和我们数学中集合的概念是一样的,也有交集,并集,差集,对称差集等概念 1.集合的定义 定义一个集合需要提供一个列表作为参数,也可以不传入参数创建一个空的集合 >>> s = set([1, 2, 2, 3]) >>> s {1, 2, 3} # 可以看到在创建集合对象对过程中已经为我们把重复的元素剔除掉了 >>> s

Python 学习之路(三)

Python 学习之路(三) 以下所用的是Python 3.6 一.集合部分 集合是一个无序的,不重复的数据集合,主要用来去重,以及关系测试:交集,差集,并集等 1.1 关系操作 1.1.1 列表去重 可以给列表去重,例如: 1 set_demo = [1,2,3,4,5,3,2,1] # 列表 2 set_demo = set(set_demo) # 转换成集合,来去重 3 print(set_demo) 1.1.2 取交集 intersection()方法 可以获得两个集合的交集部分,例如:

python成长之路第一篇(5)文件的基本操作

一.三元运算 我们在上章学习的if,,else,,有一种简便的方法 他的表达式是这样的:变量 = 值1 if 条件 else 值2 解释过来就是如果aaa等于sss则输出值1否则输出值2 二.类的概念 类是面向对象编程的核心, 它扮演相关数据及逻辑的容器角色.它们提供了创建"真实"        对象(也就是实例)的蓝图.对于Python,一切事物都是对象,对象基于类创建. 如何查询对象的类呢? 为啥分为有下划线和没下划线的呢,这些又是什么呢?本例中以查看的是列表的类,那么这个类下面就