day18_python

参考Eva_J的博客,原文连接:https://www.cnblogs.com/Eva-J/p/7277026.html

# 递归常见错误
# 超过最大递归限制
# solve 递归必须要有结束条件
# 返回值
# slove 不要只看到return就认为返回了,要看返回操作是在递归的第几层的时候发生的,然后返回给了谁
# 如果不是返回给最外层函数,调用者就接收不到
# 需要再分析,看如何把结果返回回来
# 循环 ,几乎所有的递归可以用循环解决,快速排序需要用递归实习
# 斐波那契数列,第N个斐波那契数是?

两次递归

from sys import flags
from urllib.request import urlopen
import json
import re

def fib(n):
    if n == 1 or n == 2:
        return 1
    else:
        return fib(n-1)+fib(n-2)  # 调用了两层,会使效率降低,尽量不用两层
    

print(fib(10))

一次递归

def fib(n, lis=[0]):
    lis[0] += 1
    if n == 1 or n == 2:
        lis[0] -= 1
        return 1, 1
    else:
        a, b = fib(n-1)  # 位置不能放在lis[0] -=1下面
        lis[0] -= 1
        if lis[0] == 0:
            return a+b
        return b, a+b


print(fib(50))

阶乘

def fac(n):
    if n == 1:
        return 1
    return n*fac(n-1)


print(fac(10))

常用模块

计算器

re模块

正则表达式 字符串匹配

re模块操作正则表达式

while 1:
    phone_number = input('输入手机号码:')
    if len(phone_number) == 11\
        and phone_number.isdigit()\
            and (phone_number.startswith('13')
                 or phone_number.startswith('14')
                 or phone_number.startswith('15')
                 or phone_number.startswith('16')):
        print('合法的手机号')
    else:
        print('手机号不合法,请检查后重新输入')

使用re模块

import re
phone_number = input('输入手机号码:')
if re.match('^(13|14|15|18)[0-9]{9}$', phone_number):
    print('合法的手机号')
else:
    print('手机号不合法,请检查后重新输入')

正则表达式本身和python没有什么关系,就是匹配字符串内容的一种规则

[字符组]用于同一个位置可能出现的字符的范围,可以用数字、字母、标点

[0-9]表示省略,[a-z],[A-Z],[A-Za-z0-9],A是65,a是97,此正则按照ASCILL码来读取的

元字符 在正则表达式中有特殊的意义

.匹配换行符以外的任意字符

\w 匹配字母或数字或者下划线 word

\s 匹配任意空白符 space

\d 匹配数字 digit

\n 匹配一个换行符

\t 匹配一个制表符

\b 匹配一个单词的结尾 前面要加上结尾的字母

^ 匹配字符串的开始 后面要加上开头的字母、数字、符号

$ 匹配字符串的结尾

\W 匹配非字母或者非数字或者非下划线

\D 匹配非数字

\S 匹配非空白符

a|b 匹配字符a或者字符b 从左向右匹配,匹配到第一个就不匹配第二个

() 匹配括号内的表达式,也表示一个组

[...] 匹配字符组中的字符

[^...] 匹配除了字符组中字符的所有字符 [^ab]除了ab都匹配

[\W\w] 相当于匹配任意字符

元字符可以组合使用

量词

* 重复零次或者更多次 默认多了匹配,贪婪匹配

+ 重复一次或者更多次

?重复零次或者一次

{n} 重复n次

{n,} 重复n次或者更多次

{n,m} 重复n到m次

所有的规则要用在正则匹配的后面,先规则,后跟一个量词,[a-z]+\d+

绿茶白茶黄茶青茶红茶黑茶 用.茶匹配

海燕海娇海东 海.匹配

李杰和李莲英和李二棍子 [^和]+匹配

李杰和李莲英和李二棍子 李.? 前面的,+,?都是贪婪匹配,后面的?使其变成惰性匹配,放在后面会向少的地方匹配

456bdha3 [\d]为4 5 6 3,[\d]+为456 3

分组匹配

#需要对一个整体的事情运用量词时需要用到分组,如([abc][123])+
#身份证号的正则表达式 ,身份证号为15或者18位不能以0开头,15位的为纯数字,18位的可以结尾为x
'^[1-9]\d{14}(\d{2}[0-9x])?$'  # 后面的?为量词,匹配0次或者1次,前面的匹配上后面就不匹配了
#2解:
'^([1-9]\d{16}[0-9x]|[1-9]\d{14})$'18位身份证号正则放前面

转义

print(r'\n')  # r让字符串不转义

*?重复任意次,但尽可能少重复

+?重复1次或者更多次,但尽可能少重复

??重复0次或者1次,但尽可能少重复

{n,m} ? 重复n到m次,但尽可能少重复

{n,}? 重复n次以上,但尽可能少重复

.*?x 取前面任意长度的字符,直到出现一个x

findall()

match()

ret = re.findall('a', 'eva egon yuan')  # 返回所有满足匹配条件的结果,放在列表里,列表
print(ret)  # 结果 : ['a', 'a']
# 从前往后,找到一个就返回,返回结果的对象,group()显示结果,找不到返回None,调用group()会报错
ret = re.search('a', 'eva egon yuan').group()
print(ret)  # 结果 : 'a'
ret = re.search('a', 'eva egon yuan')
if ret:
    print(ret.group())
ret = re.match('a', 'abc').group()  # 同search,不过尽在字符串开始处进行匹配
print(ret)
# 结果 : 'a'
# match从头开始匹配,如果这个正则规则从头该市可以匹配上,就返回一个变量,需要group(),没匹配上返回None

split()

sub()

subn()

compile()

finditer()

ret = re.split('[ab]', 'abcd')  # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
print(ret)  # ['', '', 'cd']
ret = re.sub('\\d', 'H', 'eva3egon4yuan4', 1)  # 将数字替换成'H',参数1表示只替换1个
print(ret)  # evaHegon4yuan4
ret = re.subn('\\d', 'H', 'eva3egon4yuan4')  # 将数字替换成'H',返回元组(替换的结果,替换了多少次)
print(ret)


obj = re.compile('\\d{3}')  # 将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字
ret = obj.search('abc123eeee')  # 正则表达式对象调用search,参数为待匹配的字符串
print(ret.group())  # 结果 : 123

ret = re.finditer('\\d', 'ds3sy4784a')  # finditer返回一个存放匹配结果的迭代器
print(ret)  # <callable_iterator object at 0x10195f940>
print(next(ret).group())  # 查看第一个结果
print(next(ret).group())  # 查看第二个结果
print([i.group() for i in ret])  # 查看剩余的左右结果

ret = re.search('^[1-9]\\d{14}(\\d{2}[0-9x])?$', '110105199912122277')
print(ret.group())
print(ret.group(1))  # 227 取到分组里面的,可以用来取局部分组

# 优先级,没有分组机制,使用优先级的形式
ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')
print(ret)  # ['oldboy']     这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可

ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com')   # ?:取消分组优先
print(ret)  # ['www.oldboy.com']

ret = re.split("\\d+", "eva3egon4yuan")
print(ret)  # 结果 : ['eva', 'egon', 'yuan']

ret = re.split("(\\d+)", "eva3egon4yuan")
print(ret)  # 结果 : ['eva', '3', 'egon', '4', 'yuan']

# 在匹配部分加上()之后所切出的结果是不同的,
# 没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项,
# 这个在某些需要保留匹配部分的使用过程是非常重要的。

爬虫的例子,因网站的登录选项,不能实际使用,仅参考

def getPage(url):
    response = urlopen(url)
    return response.read().decode('utf-8')


def parsePage(s):
    com = re.compile(
        '<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\\d+).*?<span class="title">(?P<title>.*?)</span>'
        '.*?<span class="rating_num" .*?>(?P<rating_num>.*?)</span>.*?<span>(?P<comment_num>.*?)评价</span>', re.S)


# 2解
# re.findall('<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\\d+).*?<span class="title">(?P<title>.*?)</span>'
#            '.*?<span class="rating_num" .*?>(?P<rating_num>.*?)</span>.*?<span>(?P<comment_num>.*?)评价</span>', s, re.S)
# re方法的flags:
#     re.I(IGNORECASE)忽略大小写,括号内是完整的写法
#     re.M(MULTILINE)多行模式,改变^和$的行为
#     re.S(DOTALL)点可以匹配任意字符,包括换行符
#     re.L(LOCALE)做本地化识别的匹配,表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境,不推荐使用
#     re.U(UNICODE) 使用\w \W \s \S \d \D使用取决于unicode定义的字符属性。在python3中默认使用该flag
#     re.X(VERBOSE)冗长模式,该模式下pattern字符串可以是多行的,忽略空白字符,并可以添加注释
    ret = com.finditer(s)
    for i in ret:
        yield {
            "id": i.group("id"),
            "title": i.group("title"),
            "rating_num": i.group("rating_num"),
            "comment_num": i.group("comment_num"),
        }


def main(num):
    url = 'https://movie.douban.com/top250?start=%s&filter=' % num
    response_html = getPage(url)
    ret = parsePage(response_html)
    print(ret)
    f = open("move_info7", "a", encoding="utf8")

    for obj in ret:
        print(obj)
        data = str(obj)
        f.write(data + "\n")
    f.close()


count = 0
for i in range(10):
    main(count)
    count += 25

# url 从网页上把代码搞下来
# bytes类型,decode->为utf-8 网页内容就是待匹配的字符串
# re.findall(正则,待匹配的字符串)  # ret是所有匹配到的内容组成的列表

思考

a = '1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
# 去掉所有的空格
# 逻辑 实现加减乘除四则运算和括号优先级
# 先算括号里面的乘除,再算括号里面的加减
# 从括号里面取值要用到正则表达式
ss = '9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14'
# 从一个没有括号的表达式中取乘除法  == 正则表达式
posted @ 2021-08-07 11:19  二儿八月  阅读(59)  评论(0)    收藏  举报