python模块二(递归,反射,正则表达式)

故事扮演 提交于 2020-01-26 23:18:07

一、递归,阶乘

递归之实例:

def func(num):
    """
    1*2*3*4*5... 计算类型形式的阶乘
    :param num: 计算阶乘的最大值
    :return: 7 * (7 - 1)
    """
    # 如果参数为1,直接返回1
    if num == 1:
        return 1
    # 否则返回2 * (2 - 1)
    return num * func(num - 1)

x = func(5)
print(x)
# ########print###########
120

print(1 * 2 * 3 * 4 * 5)
# ########print###########
120

 二、反射

反射关键: 

  反射: 基于字符串的形式去对象(模块)中操作其成员   

    基于内存操作的
    delattr    删除成员
    setattr    设置成员
    getattr    获取成员
    hasattr    检查成员 

学习反射之前先了解一下下面的知识

# 定义一个函数名为f1
def f1():
    print('F1')

# 字符串f1
"f1"

# 那么函数名的f1与字符串的f1是否一样
答案是不一样
 f1 是 函数名,代表整个函数体
"f1"是 字符串,仅代表字符串本身

现在以一个实例来学习反射

#!/bin/bin/env python
# -*-coding:utf-8 -*-

def login():
    print("登录界面")


def loginout():
    print("退出界面")


def index():
    print("主界面")
reflection

先对比俩个图

代码块

#!/bin/bin/env python
# -*-coding:utf-8 -*-

def run():
    import reflection
    select = input("请输入你要访问的URL:")
    if select == 'login':
        reflection.login()
    elif select == 'loginout':
        reflection.loginout()
    elif select == 'index':
        reflection.index()
    else:
        print("404")

run()

# ########################
"""
请输入你要访问的URL:loginout
退出界面

请输入你要访问的URL:login
登录界面

请输入你要访问的URL:index
主界面

请输入你要访问的URL:inde
404
"""
call_reflecation

代码块

#!/bin/bin/env python
# -*-coding:utf-8 -*-

def runs():
    import reflection
    res = input("输入你要访问的URL:")
    if hasattr(reflection, res):
        func = getattr(reflection, res)
        func()
    else:
        print("404")
runs()

# #######################
'''
输入你要访问的URL:index
主界面

输入你要访问的URL:login
登录界面

输入你要访问的URL:loginout
退出界面

输入你要访问的URL:3434
404
'''
call_reflecation

以上呢是在同一个模块中做的,那如果是在不同模块中要怎么使用呢???

 

代码块

# __import__("day6.%s" % m, fromlist=True)
def runs():
    # reflection/login
    res = input("输入你要访问的URL:")
    m, s = res.split("/")
    obj = __import__("day6.%s" % m, fromlist=True)  # 可以在不同级目录中使用
    # print(obj)
    # <module 'day6.str_module' from 'E:\\PyCharm4.5.2\\PyCharm 文件\\day6\\str_module.py'>
    # obj = __import__("day6.%s" % m,)
    # print(obj)
    # <module 'day6' from 'E:\\PyCharm4.5.2\\PyCharm 文件\\day6\\__init__.py'>
    if hasattr(obj, s):
        func = getattr(obj, s)
        func()
    else:
        print("404")
runs()

# #######################
'''
输入你要访问的URL:reflection/index
主界面

输入你要访问的URL:reflection/login
登录界面

输入你要访问的URL:reflection/loginout
退出界面

输入你要访问的URL:reflection/3434
404
'''

三、模块

特殊变量

 1 # 将文件中的注释添加到文档中
 2 __doc__    
 3 # .pyc 字节码在哪个路径,然后打印出来
 4 __cached__    
 5 # 当前py文件所在的路径
 6 __file__    
 7 # 当前py文件中返回None,被调用输出当前文件的上一级目录名
 8 __package__    
 9 # 只有执行当前文件的时候,当前文件的特殊变量  __name__ == "__main__"
10 __name__    

一个进度条实例

import time
import sys

def view_bar(num, total):
    rate = num / total
    rate_num = rate * 100
    # \r 表示替换这个位置
    r = "\r%s%d%%" % (['=' * num], rate_num,)
    # 输出不加换行符
    sys.stdout.write(r)
    # 实时刷新
    sys.stdout.flush()
    # print(r)

# view_bar(1, 100)
for i in range(1, 101):
    view_bar(i, 100)
    time.sleep(0.1)

1、hashlib模块

用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

import hashlib
obj = hashlib.md5(bytes('jdffjdslf', encoding='utf-8'))
obj.update(bytes("123", encoding='utf-8'))
result = obj.hexdigest()

##########################################################
  print(result)
  # e6da8580c5b4c3a6e1b0da4957abd271
import hashlib
obj = hashlib.sha1()
obj.update(bytes('123', encoding='utf-8'))
result = obj.hexdigest()

##############################################################
print(result)
# 40bd001563085fc35165329ea1ff5c5ecbdbbeef
import hashlib
obj = hashlib.sha256()
obj.update(bytes('123', encoding='utf-8'))
result = obj.hexdigest()#######################################################################
print(result)
# a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3
import hashlib
obj = hashlib.sha512()
obj.update(bytes('123', encoding='utf-8'))
result = obj.hexdigest()

#######################################################################
print(result)
# 3c9909afec25354d551dae21590bb26e38d53f2173b8d3dc3eee4c047e7ab1c1eb8b85103e3be7ba613b31bb5c9c36214dc9f14a42fd7a2fdb84856bca5c44c2

以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。

import hashlib
obj = hashlib.md5(bytes('rain', encoding='utf-8'))
obj.update(bytes("123", encoding='utf-8'))
result = obj.hexdigest()

###########################
print(result)
# b19575adf69aca85fb4c1523d258a885

python 还有一个 hmac 模块,它内部对我们创建 key 和 内容 再进行处理然后再加密

import hmac
obj = hmac.new(bytes("rain", encoding='utf8'))
obj.update(bytes("123", encoding='utf8'))
result = obj.hexdigest()

###########################
print(result)
# 1895606979c7fcd5cf926f46a36d096a可以与hashlib.md5()加密之后做一个对比

 2、正则表达式

正则也是一种小型的语言

re模块用于对python的正则表达式的操作

1)导入re模块

import  re

2)正则表达式匹配模式

模式描述
^ 匹配字符串的开头
$ 匹配字符串的末尾。
. 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
[...] 用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k'
[^...] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
re* 匹配0个或多个的表达式。
re+ 匹配1个或多个的表达式。
re? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
re{ n}  
re{ n,} 精确匹配n个前面表达式。
re{ n, m} 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
a| b 匹配a或b
(re) G匹配括号内的表达式,也表示一个组
(?imx) 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
(?-imx) 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。
(?: re) 类似 (...), 但是不表示一个组
(?imx: re) 在括号中使用i, m, 或 x 可选标志
(?-imx: re) 在括号中不使用i, m, 或 x 可选标志
(?#...) 注释.
(?= re) 前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。
(?! re) 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功
(?> re) 匹配的独立模式,省去回溯。
\w 匹配字母数字
\W 匹配非字母数字
\s 匹配任意空白字符,等价于 [\t\n\r\f].
\S 匹配任意非空字符
\d 匹配任意数字,等价于 [0-9].
\D 匹配任意非数字
\A 匹配字符串开始
\Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。c
\z 匹配字符串结束
\G 匹配最后匹配完成的位置。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\n, \t, 等. 匹配一个换行符。匹配一个制表符。等
\1...\9 匹配第n个分组的子表达式。
\10 匹配第n个分组的子表达式,如果它经匹配。否则指的是八进制字符码的表达式。

 3)正则表达式修饰符 - 可选标志

修饰符描述
re.I 使匹配对大小写不敏感
re.L 做本地化识别(locale-aware)匹配
re.M 多行匹配,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的所有字符
re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理 解。

正则详解

1、match(pattern, string, flags=0)

从起始位置开始根据模型去字符串中匹配指定内容,匹配单个

  • 正则表达式
  • 要匹配的字符串
  • 标志位,用于控制正则表达式的匹配方式
import re

obj = re.match('\d+', '123djfjjf')
print(obj.group())
# 123

obj = re.match('\d+', 'dj123fjjf')
print(obj.group())
# 由于match只匹配开始位置,所以这里会报错
# flags
I = IGNORECASE = sre_compile.SRE_FLAG_IGNORECASE # ignore case
L = LOCALE = sre_compile.SRE_FLAG_LOCALE # assume current 8-bit locale
U = UNICODE = sre_compile.SRE_FLAG_UNICODE # assume unicode locale
M = MULTILINE = sre_compile.SRE_FLAG_MULTILINE # make anchors look for newline
S = DOTALL = sre_compile.SRE_FLAG_DOTALL # make dot match newline
X = VERBOSE = sre_compile.SRE_FLAG_VERBOSE # ignore whitespace and comments
flags

2、search(pattern, string, flags=0)

根据模型去字符串中匹配指定内容,匹配单个

import re

obj = re.search('\d+', 'dfjs123456')
print(obj.group())
# 123456

obj = re.search('\d+', '456dfjs123456')
print(obj.group())
# 456

3、findall(pattern, string, flags=0)

上述两中方式均用于匹配单值,即:只能匹配字符串中的一个,如果想要匹配到字符串中所有符合条件的元素,则需要使用 findall。

import re

obj = re.findall('\d+', '123jfj123456')
print(obj)
# ['123', '123456']

obj = re.findall('\d+', 'afsf789sjfj123456')
print(obj)
# ['789', '123456']

 4、sub(pattern, repl, string, count=0, flags=0)

用于替换匹配的字符串

import re

content = "123abc456"
# 将所有数字替换成abc
new_content = re.sub('\d+', 'abc', content)
print(new_content)
# abcabcabc

content = "123abc456"
# 只替换第一个匹配到的数字
new_content = re.sub('\d+', 'sb', content, 1)
print(new_content)
# sbabc456

content = "123ab123c456"
# 只替换前二个匹配到的数字
new_content = re.sub('\d+', 'rain', content, 2)
print(new_content)
# rainabrainc456

 5、split(pattern, string, maxsplit=0, flags=0)

根据指定匹配进行分组

import re

content = "'1 - 2 * ((60-30+1*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2) )'"
new_content = re.split('\*', content)
print(new_content)
# ["'1 - 2 ", ' ((60-30+1', '(9-2', '5/3+7/3', '99/4', '2998+10', '568/14))-(-4', '3)/(16-3', "2) )'"]

content = "'1 - 2 * ((60-30+1*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2) )'"
new_content = re.split('\*', content, 1)
print(new_content)
# ["'1 - 2 ", " ((60-30+1*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2) )'"]
import re

content = "'1 - 2 * ((60-30+1*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2) )'"
# 以+、-、*、/为分隔符
new_content = re.split('[\+\-\*\/]+', content)
# new_content = re.split('\*', content, 1)
print(new_content)
# ["'1 ", ' 2 ', ' ((60', '30', '1', '(9', '2', '5', '3', '7', '3', '99', '4', '2998', '10', '568', '14))', '(', '4', '3)', '(16', '3', "2) )'"]
import re

inpp = '1-2*((60-30 +(-40-5)*(9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2))'
# 将inpp里面的任意空白字符替换为空
inpp = re.sub('\s*', '', inpp)
# new_content = re.split('\(([\+\-\*\/]?\d+[\+\-\*\/]?\d+){1}\)', inpp, 1)
new_content = re.split('\(([^()]+)\)', inpp, 1)
print(new_content)
# ['1-2*((60-30+', '-40-5', '*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']

6、group和groups

import re

a = "123abc456"
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group())
# 123abc456
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(0))
# 123abc456
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(1))
# 123
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(2))
# abc
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).groups())
# ('123', 'abc', '456')
group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。

 

字符类

实例描述
[Pp]ython 匹配 "Python" 或 "python"
rub[ye] 匹配 "ruby" 或 "rube"
[aeiou] 匹配中括号内的任意一个字母
[0-9] 匹配任何数字。类似于 [0123456789]
[a-z] 匹配任何小写字母
[A-Z] 匹配任何大写字母
[a-zA-Z0-9] 匹配任何字母及数字
[^aeiou] 除了aeiou字母以外的所有字符
[^0-9] 匹配除了数字外的字符

正则例子:

匹配手机号

import re

phone_str = "hey my name is alex, and my phone number is 13651054607, please call me if you are pretty!"
# 完全匹配11位电话号码
m = re.search('([\d]{11})', phone_str)
print(m.group())
# 13651054607

phone_str2 = "hey my name is alex, and my phone number is 18651054604, please call me if you are pretty!"
# 匹配以1开头并且第二位为[358]的11位电话号话
m = re.search('(1)([358]\d{9})', phone_str2)
print(m.group())
# 18651054604

匹配IP V4

import re

ip_addr = "inet 192.168.60.223 netmask 0xffffff00 broadcast 192.168.60.255"
m = re.search('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', ip_addr)
print(m.group())
# 192.168.60.223

ip_addr = "inet 192.168.60.223 netmask 0xffffff00 broadcast 192.168.60.255"
m = re.findall('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', ip_addr)
print(m)
# ['192.168.60.223', '192.168.60.255']

分组匹配地址

import re

contactInfo = 'Oldboy School, Beijing Changping Shahe: 010-8343245'
m = re.search(r'(\w+), (\w+) (\S+)', contactInfo)  # 分组
# School, Beijing Changping
m = re.search(r'(\w+) (\w+): (\S+)', contactInfo)  # 分组
# Changping Shahe: 010-8343245
print(m.group())
# School, Beijing Changping
print(m.group(0))
# School, Beijing Changping
print(m.group(1))
# School
print(m.group(2))
# Beijing
print(m.group(3))
# Changping

匹配email

import re

email = "rain_linux@163.com  http://www.oldboyedu.com"
# \w中包含_下划线
m = re.search(r"[\w0-9.a-z]{0,26}@[0-9.a-z]{0,20}.[0-9a-z]{0,8}", email)
print(m.group())
# rain_linux@163.com 

  未完待续!!!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!