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

一、递归,阶乘

递归之实例:

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 

  未完待续!!!

转载于:https://www.cnblogs.com/yxy-linux/p/5578428.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值