- Python基础
- 文件操作
- 模块与包
- 数据类型
- 企业面试题
- python2和python3区别?列举5个
- python新式类和经典类的区别?
- python中内置的数据结构有几种?
- 可变类型和不可变类型
- python如何实现单例模式?请写出两种实现方式?
- 反转一个整数,例如-123 --> -321
- 设计实现遍历目录与子目录,抓取.pyc文件
- 一行代码实现1-100之和
- Python-遍历列表时删除元素的正确做法
- 字符串的操作题目
- is和==有什么区别?
- 求出列表所有奇数并构造新列表
- 用一行python代码写出1+2+3+10248
- Python中变量的作用域?(变量查找顺序)
- 字符串
"123"转换成123,不使用内置api,例如int() - 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数
- 给列表中的字典排序
- 统计一个文本中单词频次最高的10个单词?
- 利用collections库的Counter方法统计字符串每个单词出现的次数"kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h"
- 请写出一个函数满足以下条件
- 使用单一的列表生成式来产生一个新的列表
- 用一行代码生成[1,4,9,16,25,36,49,64,81,100]
- 输入某年某月某日,判断这一天是这一年的第几天?
- 两个有序列表,l1、l2对这两个列表进行合并不可使用extend
- 给定一个任意长度数组,实现一个函数
- 写一个函数找出一个整数数组中,第二大的数
- 阅读一下代码他们的输出结果是什么?
- 统计一段字符串中字符出现的次数
- super函数的具体用法和场景
- Python高级
- 元类
- 内存管理与垃圾回收机制
- 函数
- 简述read、readline、readlines的区别?
- 什么是Hash(散列函数)?
- python函数重载机制?
- 手写一个判断时间的装饰器
- 编写函数的4个原则
- 函数调用参数的传递方式是值传递还是引用传递?
- 如何在function里面设置一个全局变量
- 对缺省参数的理解?
- 带参数的装饰器?
- 为什么函数名字可以当做参数用?
- Python中pass语句的作用是什么?
- map函数和reduce函数?
- 回调函数,如何通信的?
- Python主要的内置数据类型都有哪些? print(dir("a")) 的输出?
- hasattr()、getattr()、setattr()函数使用详解?
- 一句话解决阶乘函数?
- Python 递归深度默认是多少?递归深度限制的原因是什么?
- 递归函数停止的条件?
- 什么是lambda函数?它有什么好处?写一个匿名函数求两个数的和
- 设计模式
- 面向对象
- 正则表达式
- 字符串a = "not 404 found 张三 99 深圳",每个词中间是空格,用正则过滤掉英文和数字,最终输出"张三 深圳"
- 请写出一段代码用正则匹配出ip?
- 正则匹配,匹配日期2018-03-20
- a = “abbbccc”,用正则匹配为abccc,不管有多少b,就出现一次?
- Python字符串查找和替换?
- 用Python匹配HTML
<div class="nam">中国</div>,用正则匹配出标签里面的内容(“中国”),其中class的类名是不确定的,并说明<.> 和 <.*?> 有什么区别 - 正则表达式贪婪与非贪婪模式的区别?
- 写出开头匹配字母和下划线,末尾是数字的正则表达式?
- 正则表达式操作
- 请匹配出变量A中的json字符串。
- 怎么过滤评论中的表情?
- 正则匹配以163.com结尾的邮箱
- a="张明 98分",用re.sub,将98替换为100
- 简述Python里面search和match的区别
- 正则re.complie作用
- 系统编程
- 10个Linux常用命令
- 进程总结
- 请介绍一下Python的线程同步?
- 谈谈你对多进程,多线程,以及协程的理解,项目是否用?
- 多进程更稳定还是多线程更稳定?为什么?
- 多线程的致命缺点是什么?
- 进程间通信有哪些方式?
- Python的GIL
- Python异步使用场景有那些?
- 多线程共同操作同一个数据互斥锁同步?
- 什么是多线程竞争?
- 解释以下什么是锁,有哪几种锁?
- 什么是死锁?
- 多线程交互访问数据,如果访问到了就不访问了?
- 什么是线程安全,什么是互斥锁?
- 说说下面几个概念:同步,异步,阻塞,非阻塞?
- 什么是僵尸进程和孤儿进程?怎么避免僵尸进程?
- python中进程与线程的使用场景?
- 线程是并发还是并行,进程是并发还是并行?
- 并行(parallel)和并发(concurrency)?
- IO密集型和CPU密集型区别?
- python asyncio的原理?
- 网络编程
- 怎么实现强行关闭客户端和服务器之间的连接?
- 简述TCP和UDP的区别以及优缺点?
- 简述浏览器通过WSGI请求动态资源的过程?
- 描述用浏览器访问www.baidu.com的过程
- Post和Get请求的区别?
- cookie和session的区别?
- 列出你知道的HTTP协议的状态码,说出表示什么意思?
- 请简单说一下三次握手和四次挥手?
- 说一下什么是tcp的2MSL?
- 为什么客户端在TIME-WAIT状态必须等待2MSL的时间?
- 说说HTTP和HTTPS区别?
- 谈一下HTTP协议以及协议头部中表示数据类型的字段?
- HTTP请求方法都有什么?
- 使用Socket套接字需要传入哪些参数 ?
- HTTP常见请求头?
- 七层模型?
- url的形式?
- Web
- 分别从前端、后端、数据库阐述web项目的性能优化
- Flask
- Django
- 什么是wsgi,uwsgi,uWSGI?
- Django、Flask、Tornado的对比?
- 简述同源策略
- CORS和CSRF的区别?
- Session、Cookie、JWT的理解
- 简述Django请求生命周期
- 用的restframework完成api发送时间时区
- nginx,tomcat,apache都是什么?
- 请给出你熟悉关系数据库范式有哪些,有什么作用?
- 简述QQ登陆过程
- 项目中日志的作用
- 异常名称及其意义
- django中间件的使用?
- 谈一下你对uWSGI和nginx的理解?
- Python中三大框架各自的应用场景?
- Django中哪里用到了线程?哪里用到了协程?哪里用到了进程?
- 有用过Django REST framework吗?
- 爬虫
- 什么是爬虫,为什么要用爬虫?
- 爬虫的基本流程?
- 如何提高爬取效率?
- 爬虫协议?
- 试列出至少三种目前流行的大型数据库
- 列举您使用过的Python网络爬虫所用到的网络数据包?
- 你用过的爬虫框架或者模块有哪些?优缺点?
- 写爬虫是用多进程好?还是多线程好?
- 常见的反爬虫和应对方法?
- 解析网页的解析器使用最多的是哪几个?
- 需要登录的网页,如何解决同时限制ip,cookie, session
- 验证码的解决?
- 使用最多的数据库,对他们的理解?
- 编写过哪些爬虫中间件?
- “极验”滑动验证码如何破解?
- 爬虫多久爬一次,爬下来的数据使用哪个数据库存储数据,是怎么存储,为什么,部署是你做的吗?怎么部署?
- cookie过期的处理问题?
- 动态加载又对及时性要求很高怎么处理?
- HTTPS有什么优点和缺点?
- HTTPS是如何实现安全传输数据的?
- TTL,MSL,RTT各是什么?
- 平常怎么使用代理的 ?
- 存放在数据库(redis、mysql等)。
- 怎么监控爬虫的状态?
- 爬取数据的影响因素?
- scrapy和requests的使用情况?
- 描述下scrapy框架运行的机制?
- 谈谈你对Scrapy的理解?
- 怎么样让scrapy框架发送一个post请求(具体写出来)
- 怎么监控爬虫的状态 ?
- 怎么判断网站是否更新?
- 图片、视频爬取怎么绕过防盗连接
- 你爬出来的数据量大概有多大?大概多长时间爬一次?
- 增量爬取
- 爬取下来的数据如何去重,说一下scrapy的具体的算法依据。
- Scrapy的优缺点?
- 怎么设置爬取深度?
- scrapy和scrapy-redis有什么区别?为什么选择redis数据库?
- 分布式爬虫主要解决什么问题?
- 什么是分布式存储?
- 你所知道的分布式爬虫方案有哪些?
- scrapy-redis,有做过其他的分布式爬虫吗?
- 数据库
- MySQL
- Redis
- RabbitMQ
- MongoDB
- 测试
- 数据结构
- 数组中出现次数超过一半的数字-Python版
- 求100以内的质数
- 无重复字符的最长子串-Python实现
- 通过2个5和6升得水壶从池塘得到3升水
- 什么是MD5加密,有什么特点?
- 什么是对称加密和非对称加密
- 冒泡排序的思想?
- 快速排序的思想?
- 如何判断单向链表中是否有环?
- 你知道哪些排序算法(一般是通过问题考算法)
- 斐波那契数列
- 如何翻转一个单链表?
- 青蛙跳台阶问题
- 两数之和Two Sum
- 搜索旋转排序数组(Search in Rotated Sorted Array)
- Python实现一个Stack的数据结构
- 写一个二分查找
- set用in时间复杂度是多少,为什么?
- 列表中有n个正整数范围在[0,1000],进行排序
- 面向对象编程中有组合和继承的方法实现新的类
- 大数据
- 机器学习和深度学习
def get_lines():
with open('file.txt','rb') as f:
return f.readlines()
if __name__ == '__main__':
for e in get_lines():
process(e) # 处理每一行数据现在要处理一个大小为10G的文件,但是内存只有4G,如果在只修改get_lines 函数而其他代码保持不变的情况下,应该如何实现?需要考虑的问题都有那些?
def get_lines():
with open('file.txt','rb') as f:
for i in f:
yield iPandaaaa906提供的方法
from mmap import mmap
def get_lines(fp):
with open(fp, "r+") as f:
m = mmap(f.fileno(), 0)
tmp = 0
for i, char in enumerate(m):
if char == b"\n":
yield m[tmp:i+1].decode()
tmp = i + 1
if __name__=="__main__":
for i in get_lines("fp_some_huge_file"):
print(i)要考虑的问题有:内存只有4G无法一次性读入10G文件,需要分批读入分批读入数据要记录每次读入数据的位置。分批每次读取数据的大小,太小会在读取操作花费过多时间。具体可以参考此处
- 打印输出当前文件所在目录路径
import os print(os.path.dirname(os.path.abspath(__file__)))
- 打印输出当前文件路径
import os print(os.path.abspath(__file__))
- 打印输出当前文件上两层文件目录路径
import os print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
def print_directory_contents(sPath):
"""
这个函数接收文件夹的名称作为输入参数
返回该文件夹中文件的路径
以及其包含文件夹中文件的路径
"""
import os
for s_child in os.listdir(s_path):
s_child_path = os.path.join(s_path, s_child)
if os.path.isdir(s_child_path):
print_directory_contents(s_child_path)
else:
print(s_child_path)os: 提供了不少与操作系统相关联的函数 sys: 通常用于命令行参数 re: 正则匹配 math: 数学运算 datetime: 处理日期时间
import datetime
def dayofyear():
year = input("请输入年份: ")
month = input("请输入月份: ")
day = input("请输入天: ")
date1 = datetime.date(year=int(year), month=int(month), day=int(day))
date2 = datetime.date(year=int(year), month=1, day=1)
return (date1 - date2).days + 1import random
alist = [1,2,3,4,5]
random.shuffle(alist)
print(alist)d = [val for value in iterable]sorted(d.items(), key=lambda x:x[1])d = {key:value for (key, value) in iterable}print("aStr"[::-1])str1 = "k:1|k1:2|k2:3|k3:4"
def str2dict(str1):
dict1 = {}
for iterms in str1.split('|'):
key,value = iterms.split(':')
dict1[key] = value
return dict1
#字典推导式
d = {k:int(v) for t in str1.split("|") for k, v in (t.split(":"), )}alist = [{'name':'a','age':20},{'name':'b','age':30},{'name':'c','age':25}]
def sort_by_age(list1):
return sorted(alist, key=lambda x:x['age'], reverse=True)list = ['a','b','c','d','e']
print(list[10:])代码将输出[],不会产生IndexError错误,就像所期望的那样,尝试用超出成员的个数的index来获取某个列表的成员。例如,尝试获取list[10]和之后的成员,会导致IndexError。然而,尝试获取列表的切片,开始的index超过了成员个数不会产生IndexError,而是仅仅返回一个空列表。这成为特别让人恶心的疑难杂症,因为运行的时候没有错误产生,导致Bug很难被追踪到。
print([x*11 for x in range(10)])list1 = [1,2,3]
list2 = [3,4,5]
set1 = set(list1)
set2 = set(list2)
print(set1 & set2)
print(set1 ^ set2)l1 = ['b','c','d','c','a','a']
l2 = list(set(l1))
print(l2)用list类的sort方法:
l1 = ['b','c','d','c','a','a']
l2 = list(set(l1))
l2.sort(key=l1.index)
print(l2)也可以这样写:
l1 = ['b','c','d','c','a','a']
l2 = sorted(set(l1), key=l1.index)
print(l2)也可以用遍历:
l1 = ['b','c','d','c','a','a']
l2 = []
for i in l1:
if not i in l2:
l2.append(i)
print(l2)随机整数: random.randint(a,b),生成区间内的整数
随机小数: 习惯用numpy库,利用np.random.randn(5)生成5个随机小数
0-1随机小数: random.random(),括号中不传参
assert() 方法,断言成功,则程序继续执行,断言失败,则程序报错
- Python3中使用
print必须要以小括号包裹打印内容,比如print('hi') Python2中既可以使用带小括号的方式,也可以使用一个空格来分隔打印内容,比如print 'hi' - python2中range(1,10)返回列表,python3中返回迭代器,节约内存
- python2中使用ascii编码,python中使用utf-8编码
- python2中unicode表示字符串序列,str表示字节序列,python3中str表示字符串序列,byte表示字节序列
- python2中为正常显示中文,引入coding声明,python3中不需要
- python2中是raw_input()函数,python3中是input()函数
- 在python里凡是继承了object的类,都是新式类
- Python3里只有新式类
- Python2里面继承object的是新式类,没有写父类的是经典类
- 经典类目前在Python里基本没有应用
- 整型 int、 长整型 long、浮点型 float、 复数 complex
- 字符串 str、 列表 list、 元组 tuple
- 字典 dict 、 集合 set
- Python3 中没有 long,只有无限精度的 int
- 可变类型有list,dict.不可变类型有string,number,tuple.
- 当进行修改操作时,可变类型传递的是内存中的地址,也就是说,直接修改内存中 C9BC 的值,并没有开辟新的内存。
- 不可变类型被改变时,并没有改变原内存地址中的值,而是开辟一块新的内存,将原地址中的值复制过去,对这块新开辟的内存中的值进行操作。
第一种方法:使用装饰器
def singleton(cls):
instances = {}
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton
class Foo(object):
pass
foo1 = Foo()
foo2 = Foo()
print(foo1 is foo2) #True第二种方法:使用基类 New是真正创建实例对象的方法,所以重写基类的new方法,以此保证创建对象的时候只生成一个实例
class Singleton(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
return cls._instance
class Foo(Singleton):
pass
foo1 = Foo()
foo2 = Foo()
print(foo1 is foo2) #True第三种方法:元类 元类是用于创建类对象的类,类对象创建实例对象时一定要调用call方法,因此在调用call时候保证始终只创建一个实例即可,type是python的元类
class Singleton(type):
def __call__(cls, *args, **kwargs):
if not hasattr(cls,'_instance'):
cls._instance = super(Singleton,cls).__call__(*args,**kwargs)
return cls._instanceclass Foo(object):
__metaclass__ = Singleton
foo1 = Foo()
foo2 = Foo()
print(foo1 is foo2) #Trueclass Solution(object):
def reverse(self, x):
if -10 < x < 10:
return x
str_x = str(x)
if str_x[0] != "-":
str_x = str_x[::-1]
x = int(str_x)
else:
str_x = str_x[1:][::-1]
x = int(str_x)
x = -x
return x if -2147483648 < x < 2147483647 else 0
if __name__ == '__main__':
s = Solution()
reverse_int = s.reverse(-120)
print(reverse_int)第一种方法:
import os
def get_files(dir, suffix):
res = []
for root,dirs,files in os.walk(dir):
for filename in files:
name,suf = os.path.splitext(filename)
if suf == suffix:
res.append(os.path.join(root,filename))
print(res)
get_files("./",'.pyc')第二种方法:
import os
def pick(obj):
if ob.endswith(".pyc"):
print(obj)
def scan_path(ph):
file_list = os.listdir(ph)
for obj in file_list:
if os.path.isfile(obj):
pick(obj)
elif os.path.isdir(obj):
scan_path(obj)
if __name__=='__main__':
path = input('输入目录')
scan_path(path)第三种方法
from glob import iglob
def func(fp, postfix):
for i in iglob(f"{fp}/**/*{postfix}", recursive=True):
print(i)
if __name__ == "__main__":
postfix = ".pyc"
func("K:\Python_script", postfix)count = sum(range(0, 101))
print(count)遍历在新在列表操作,删除时在原来的列表操作
a = [1,2,3,4,5,6,7,8]
print(id(a))
print(id(a[:]))
for i in a[:]:
if i>5:
pass
else:
a.remove(i)
print(a)
print('-----------')
print(id(a))#filter
a=[1,2,3,4,5,6,7,8]
b = filter(lambda x: x > 5, a)
print(list(b))列表解析
a=[1,2,3,4,5,6,7,8]
b = [i for i in a if i>5]
print(b)倒序删除 因为列表总是‘向前移’,所以可以倒序遍历,即使后面的元素被修改了,还没有被遍历的元素和其坐标还是保持不变的
a=[1,2,3,4,5,6,7,8]
print(id(a))
for i in range(len(a)-1,-1,-1):
if a[i]>5:
pass
else:
a.remove(a[i])
print(id(a))
print('-----------')
print(a)全字母短句 PANGRAM 是包含所有英文字母的句子,比如:A QUICK BROWN FOX JUMPS OVER THE LAZY DOG. 定义并实现一个方法 get_missing_letter, 传入一个字符串采纳数,返回参数字符串变成一个 PANGRAM 中所缺失的字符。应该忽略传入字符串参数中的大小写,返回应该都是小写字符并按字母顺序排序(请忽略所有非 ACSII 字符)
下面示例是用来解释,双引号不需要考虑:
(0)输入: "A quick brown for jumps over the lazy dog"
返回: ""
(1)输入: "A slow yellow fox crawls under the proactive dog"
返回: "bjkmqz"
(2)输入: "Lions, and tigers, and bears, oh my!"
返回: "cfjkpquvwxz"
(3)输入: ""
返回:"abcdefghijklmnopqrstuvwxyz"
def get_missing_letter(a):
s1 = set("abcdefghijklmnopqrstuvwxyz")
s2 = set(a)
ret = "".join(sorted(s1-s2))
return ret
print(get_missing_letter("python"))is: 比较的是两个对象的id值是否相等,也就是比较俩对象是否为同一个实例对象。是否指向同一个内存地址 ==: 比较的两个对象的内容/值是否相等,默认会调用对象的eq()方法
a = [1,2,3,4,5,6,7,8,9,10]
res = [ i for i in a if i % 2 == 1]
print(res)#1.使用sum内置求和函数
num = sum([1,2,3,10248])
print(num)
#2.reduce 函数
from functools import reduce
num1 = reduce(lambda x, y : x + y, [1,2,3,10248])
print(num1)1.什么是LEGB及其函数作用域的LEGB顺序? L: local 函数内部作用域 E: enclosing 函数内部与内嵌函数之间 G: global 全局作用域 B: build-in 内置作用
python在函数里面的查找分为4种,称之为LEGB,也正是按照这是顺序来查找的
方法一: 利用 str 函数
def atoi(s):
num = 0
for v in s:
for j in range(10):
if v == str(j):
num = num * 10 + j
return num方法二: 利用 ord 函数
def atoi(s):
num = 0
for v in s:
num = num * 10 + ord(v) - ord('0')
return num方法三: 利用 eval 函数
def atoi(s):
num = 0
for v in s:
t = "%s * 1" % v
n = eval(t)
num = num * 10 + n
return num方法四: 结合方法二,使用 reduce,一行解决
from functools import reduce
def atoi(s):
return reduce(lambda num, v: num * 10 + ord(v) - ord('0'), s, 0)你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。示例:给定nums = [2,7,11,15],target=9 因为 nums[0]+nums[1] = 2+7 =9,所以返回[0,1]
class Solution:
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
d = {}
size = 0
while size < len(nums):
if target - nums[size] in d:
if d[target - nums[size]] < size:
return [d[target-nums[size]], size]
else:
d[nums[size]] = size
size = size + 1
solution = Solution()
list = [2,7,11,15]
target = 9
nums = solution.twoSum(list,target)
print(nums)假设有如下list对象,alist=[{"name":"a","age":20},{"name":"b","age":30},{"name":"c","age":25}],将alist中的元素按照age从大到小排序 alist=[{"name":"a","age":20},{"name":"b","age":30},{"name":"c","age":25}]
alist_sort = sorted(alist, key=lambda e : e.__getitem__('age'), reverse=True)import re
# 方法一
def test(filepath):
distone = {}
with open(filepath) as f:
for line in f:
line = re.sub("\W+", " ", line)
lineone = line.split()
for keyone in lineone:
if not distone.get(keyone):
distone[keyone] = 1
else:
distone[keyone] += 1
num_ten = sorted(distone.items(), key=lambda x:x[1], reverse=True)[:10]
num_ten =[x[0] for x in num_ten]
return num_ten
# 方法二
# 使用 built-in 的 Counter 里面的 most_common
import re
from collections import Counter
def test2(filepath):
with open(filepath) as f:
return list(map(lambda c: c[0], Counter(re.sub("\W+", " ", f.read()).split()).most_common(10)))from collections import Counter
a = "kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h"
res = Counter(a)
print(res)该函数的输入是一个仅包含数字的list,输出一个新的list,其中每一个元素要满足以下条件: 1、该元素是偶数 2、该元素在原list中是在偶数的位置(index是偶数)
def num_list(num):
return [i for i in num if i % 2 == 0 and num.index(i) % 2 == 0]
num = [0,1,2,3,4,5,6,7,8,9,10]
result = num_list(num)
print(result)该列表只包含满足以下条件的值,元素为原始列表中偶数切片
list_data = [1,2,5,8,10,3,18,6,20]
res = [x for x in list_data[::2] if x % 2 == 0]
print(res)[x * x for x in range(1, 11)]import datetime
y = int(input("请输入4位数字的年份:"))
m = int(input("请输入月份:"))
d = int(input("请输入是哪一天"))
targetDay = datetime.date(y, m, d)
dayCount = targetDay - datetime.date(targetDay.year - 1, 12, 31)
print("%s是 %s年的第%s天。"%(targetDay, y, dayCount.days))def loop_merge_sort(l1, l2):
tmp = list()
while len(l1) > 0 and len(l2) > 0:
if l1[0] <
C9BC
l2[0]:
tmp.append(l1[0])
del l1[0]
else:
tmp.append(l2[0])
del l2[0]
if len(l1) > 0:
while len(l1):
tmp.append(l1[0])
del l1[0]
if len(l2) > 0:
while len(l2) > 0:
tmp.append(l2[0])
del l2[0]
return tmp让所有奇数都在偶数前面,而且奇数升序排列,偶数降序排序,如字符串'1982376455',变成'1355798642'
# 方法一
def func1(l):
if isinstance(l, str):
l = [int(i) for i in l]
l.sort(reverse=True)
for i in range(len(l)):
if l[i] % 2 > 0:
l.insert(0, l.pop(i))
print(''.join(str(e) for e in l))
# 方法二
def func2(l):
print("".join(sorted(l, key=lambda x: int(x) % 2 == 0 and 20 - int(x) or int(x))))def find_second_large_num(num_list):
"""
找出数组第2大的数字
"""
# 方法一
# 直接排序,输出倒数第二个数即可
tmp_list = sorted(num_list)
print("方法一\nSecond_large_num is :", tmp_list[-2])
# 方法二
# 设置两个标志位一个存储最大数一个存储次大数
# two 存储次大值,one 存储最大值,遍历一次数组即可,先判断是否大于 one,若大于将 one 的值给 two,将 num_list[i] 的值给 one,否则比较是否大于two,若大于直接将 num_list[i] 的值给two,否则pass
one = num_list[0]
two = num_list[0]
for i in range(1, len(num_list)):
if num_list[i] > one:
two = one
one = num_list[i]
elif num_list[i] > two:
two = num_list[i]
print("方法二\nSecond_large_num is :", two)
# 方法三
# 用 reduce 与逻辑符号 (and, or)
# 基本思路与方法二一样,但是不需要用 if 进行判断。
from functools import reduce
num = reduce(lambda ot, x : ot[1] < x and (ot[1], x) or ot[0] < x and (x, ot[1]) or ot, num_list, (0, 0))[0]
print("方法三\nSecond_large_num is :", num)
if __name__ == '__main___':
num_list = [34, 11, 23, 56, 78, 0, 9, 12, 3, 7, 5]
find_second_large_num(num_list)def multi():
return [lambda x : i * x for i in range(4)]
print([m(3) for m in multi()])正确答案是[9,9,9,9],而不是[0,3,6,9]产生的原因是Python的闭包的后期绑定导致的,这意味着在闭包中的变量是在内部函数被调用的时候被查找的,因为,最后函数被调用的时候,for循环已经完成, i 的值最后是3,因此每一个返回值的i都是3,所以最后的结果是[9,9,9,9]
# 方法一
def count_str(str_data):
"""定义一个字符出现次数的函数"""
dict_str = dict()
for i in str_data:
dict_str[i] = dict_str.get(i, 0) + 1
return dict_str
dict_str = count_str("AAABBCCAC")
str_count_data = ""
for k, v in dict_str.items():
str_count_data += k + str(v)
print(str_count_data)
# 方法二
from collections import Counter
print("".join(map(lambda x: x[0] + str(x[1]), Counter("AAABBCCAC").most_common())))- 为了调用父类(超类)的一个方法,可以使用super()函数
- super()函数的一个常见用法是在
__init__()方法中确保父类被正确的初始化 - super()的另外一个常见用法出现在覆盖Python特殊方法的代码中 具体详见调用父类方法
- 类方法: 是类对象的方法,在定义时需要在上方使用
@classmethod进行装饰,形参为cls,表示类对象,类对象和实例对象都可调用 - 类实例方法: 是类实例化对象的方法,只有实例对象可以调用,形参为self,指代对象本身;
- 静态方法: 是一个任意函数,在其上方使用
@staticmethod进行装饰,可以用对象直接调用,静态方法实际上跟该类没有太大关系
class Car:
def __init__(self, name, loss): # loss [价格,油耗,公里数]
self.name = name
self.loss = loss
def get_name(self):
return self.name
def get_price(self):
# 获取汽车价格
return self.loss[0]
def get_loss(self):
# 获取汽车损耗值
return self.loss[1] * self.loss[2]
Bmw = Car("宝马", [60,9,500]) # 实例化一个宝马车对象
print(getattr(Bmw,"name")) # 使用getattr()传入对象名字,属性值。
print(dir(Bmw)) # 获Bmw所有的属性和方法class Array:
__list = []
def __init__(self):
print "constructor"
def __del__(self):
print "destruct"
def __str__(self):
return "this self-defined array class"
def __getitem__(self,key):
return self.__list[key]
def __len__(self):
return len(self.__list)
def Add(self, value):
self.__list.append(value)
def Remove(self, index):
del self.__list[index]
def DisplayItems(self):
print "show all items---"
for item in self.__list:
print item- 使用生成器,因为可以节约大量内存
- 循环代码优化,避免过多重复代码的执行
- 核心模块用Cython、PyPy等,提高效率
- 多进程、多线程、协程
- 多个if elif条件判断,可以把最有可能先发生的条件放到前面写,这样可以减少程序判断的次数,提高效率
python程序性能优化的套路一般有两种:1)jit, 即just in time compiler, 即时编译器,在运行时将某些函数编译成二进程代码,使用这种方式的有:numba 和pypy;2)将python代码转换成c++/c代码,然后编译执行,这种方式有:cython和nuitka。总而言之,转换成c++/c代码以后编译成二进制文件执行的效率比用numba和pypy即时编译执行的效率要高
-
Cython Cython(Python的C语言扩展)是Python的超集,它能把Python代码编译成C代码,并与C和C++进行交互。它可以作为Python项目的扩展使用(重新性能要求高的部分),或者单独使用,不涉及传统的Python代码。缺点是你写的不是Python,所以需要手动迁移,缺乏可移植性。
据说,Cython提供了一些特性来让代码更高效,比如变量类型化,这本质上是C要求的。一些科学计算的包,如scikit-learn依赖Cython的一些特性来保持操作简洁快速。
-
Pypy 在CPython的替代品中,PyPy是最显眼的那一个(比如Quora就在生产环境中使用它)。它也最有机会成为默认解释器,它和现存Python代码高度兼容。
PyPy使用适时编译来加速Python,这项技术Google也在使用,Google在V8引擎中使用它加速Javascript。最近的版本PyPy2.5增加了一些提升性能的特性,其中有一项很受欢迎,它集成了Numpy,Numpy之前也一直被用来加速Python的运行。
使用Python3的代码需要对应地使用PyPy3。PyPy目前只支持到Python3.2.5,对Python3.3的支持正在进行中。
-
CPython CPython是特指C语言实现的Python,就是原汁原味的Python。
之所以使用CPython这个词,是因为Python还有一些其它的实现,比如Jython,就是Java版的Python,还有烧脑的PyPy,使用Python再把Python实现了一遍。
如下是官方对CPython的说明: CPython is Guido van Rossum’s reference version of the Python computing language. It’s most often called simply “Python”; speakers say “CPython” generally to distinguish it explicitly from other implementations.
-
Numba Numba接合了上面几个项目的想法。学习了Cython,Numba也采用了部分加速的策略,只加速CPU密集型的任务;同时它又学习了PyPy和Pyston,通过LLVM运行Python。你可以用一个装饰器指定你要用Numba编译的函数,Numba继承Numpy来加速函数的执行,Numba不做适时编译,它的代码是预先编译的。
Python之父说大部分觉得Python慢的应用都是没有正确地使用Python。对于CPU密集型的任务有多种方法来提升性能--使用Numpy来做计算,调用外部C代码,以及尽量避免GIL锁。由于GIL锁目前还无法被替代,所以有很多项目开始尝试一些短期可行的替代方案,当然这些方案也可能转变为长期的可选项。
使用abc模块可以很轻松的定义抽象基类:
抽象类的一个特点是它不能直接被实例化
抽象类的目的就是让别的类继承它并实现特定的抽象方法
抽象基类的一个主要用途是在代码中检查某些类是否为特定类型,实现了特定接口
除了继承这种方式外,还可以通过注册方式来让某个类实现抽象基类
import abc具体请看此处
dir([obj]):调用这个方法将返回包含obj大多数属性名的列表(会有一些特殊的属性不包含在内)。obj的默认值是当前的模块对象。 hasattr(obj, attr): 这个方法用于检查obj是否有一个名为attr的值的属性,返回一个布尔值。 getattr(obj, attr): 调用这个方法将返回obj中名为attr值的属性的值,例如如果attr为’bar’,则返回obj.bar。 setattr(obj, attr, val):调用这个方法将给obj的名为attr的值的属性赋值为val。例如如果attr为’bar’,则相当于obj.bar = val。
内存溢出:你申请了10个字节的内存,但写入了大于10个字节的数据会导致内存溢出
内存溢出原因:
- 内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
- 集合类中有对对象的引用,使用完后未清空,产生了堆积,使得JVM不能回收;
- 代码中存在死循环或循环产生过多重复的对象实体;
- 使用的第三方软件中的BUG;
- 启动参数内存值设定的过小 内存溢出的解决方案:
- 修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)
- 检查错误日志,查看“OutOfMemory”错误前是否有其 它异常或错误。
- 对代码进行走查和分析,找出可能发生内存溢出的位置。
内存管理包括:
- 变量无须事先声明
- 变量无须指定类型
- 不用关心内存管理
- 变量名会被"回收"
- del语句能够直接释放资源 变量定义 python中, 变量在第一次被赋值时自动声明, 和其它语言一样, 变量只有被创建和赋值后才能被使用 动态类型 变量名无须事先声明, 也无须类型声明 对象的类型和内存占用都是运行时确定的 内存分配 python解释器会自动进行内存管理, 不用开发人员去关心 引用计数
- 要保持追踪内存中的状态, python使用了引用计数, 就是python内部记录着所有使用中的对象各有多少引用.
- 一个内部跟踪变量, 称为一个引用计数器, 至于每个对象各有多少引用, 简称引用计数, 当对象被创建时, 就创建了一个引用计数, 当这个对象不再需要时, 也就是说, 这个对象的引用计数变为0时, 它被垃圾回收 增加引用计数
- 当对象被创建赋值给变量时, 该对象的引用计数就被设置为1
- 当同一个对象又被赋值给其他变量时, 或作为参数传递给函数, 方法或类实例时, 或者被赋值为一个窗口对象的成员时, 该对象的一个新的引用, 或者作为别名, 就被创建. 减少引用计数 当对象的引用被销毁时, 引用计数会减少, 明显的例子就是当引用离开其作用范围时, 这种情况最经常出现在函数运行结束时, 所有局部变量都被自动销毁, 对象的引用计数也就减少 垃圾收集 不再被使用的内存会被一种称为垃圾收集的机制释放 注: 解释器跟踪对象的引用计数, 垃圾回收机制负责释放内存, 垃圾收集器是一块独立代码, 它用来寻找引用计数为0的对象, 它也负责检查虽然引用计数大于0但是也应该被销毁的对象 引用语义: python中在变量里保存值(对象)的引用, 采用这种方式, 变量所需的存储空间大小一致, 因为其只需要保存一个引用 值语义变量的值直接保存在变量的存储区里, 这样一个整数类型的变量就需要保存一个整数所需的空间, 一个浮点数变量就需要足够的空间存储一个浮点数. C中就是值语义
-
内存管理机制:引用计数、垃圾回收、内存池。 引用计数: 引用计数是一种非常高效的内存管理手段,当一个python对象被引用时,它的引用计数增加1,当它不再被一个变量引用时则引用计数减1,当它的引用计数等于0时对象被删除 垃圾回收: 当Python的某个对象的引用计数降为0时,说明没有任何引用指向该对象,该对象就成为要被回收的垃圾。比如某个新建对象,被分配给某个引用,对象的引用计数变为1。如果引用被删除,对象的引用计数为0,那么该对象就可以被垃圾回收。 内存池: Python 的内存机制呈现金字塔形状,-1,-2 层主要有操作系统进行操作;
- 第 0 层是 C 中的 malloc,free 等内存分配和释放函数进行操作;
- 第 1 层和第 2 层是内存池,有 Python 的接口函数 PyMem_Malloc 函数实现,当对象小于256K 时有该层直接分配内存;
- 第 3 层是最上层,也就是我们对 Python 对象的直接操作;
Python 在运行期间会大量地执行 malloc 和 free 的操作,频繁地在用户态和核心态之间进行切换,这将严重影响 Python 的执行效率。为了加速 Python 的执行效率,Python 引入了一个内存池机制,用于管理对小块内存的申请和释放。
Python 内部默认的小块内存与大块内存的分界点定在 256 个字节,当申请的内存小于 256 字节时,PyObject_Malloc 会在内存池中申请内存;当申请的内存大于 256 字节时,PyObject_Malloc 的行为将蜕化为 malloc 的行为。当然,通过修改 Python 源代码,我们可以改变这个默认值,从而改变 Python 的默认内存管理行为。
-
调优手段:
- 手动垃圾回收
- 调高垃圾回收阈值
- 避免循环引用(手动解循环引用和使用弱引用)
- 高效
- 运行期没有停顿:一旦没有引用,内存就直接释放了。不用像其他机制等到特定时机。实时性还带来一个好处:处理回收内存的时间分摊到了平时。
- 对象有确定的生命周期
- 易于实现
- 维护引用计数消耗资源,维护引用计数的次数和引用赋值成正比,而不像mark and sweep等基本与回收的内存数量有关。
- 无法解决循环引用的问题。A和B相互引用而再没有外部引用A与B中的任何一个,它们的引用计数都为1,但显然应该被回收。
内存泄露指由于疏忽或错误造成程序未能释放已经不再使用内存的情况。内存泄露并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费,导致运行速度缓慢甚至系统崩溃等严重后果。
如何避免 有_del_()函数的对象间的循环引用是导致内存泄露的主凶。
- 不使用一个对象式用del object来删除一个对象的引用计数就可以有效防止内存泄露问题。
- 通过Python扩展模块gc来查看不能回收的对象的详细信息
- 可以通过sys.getrefcount(obj)来获取对象的引用计数,并根据返回值是否为0来判断是否内存泄露
read(): 一次性读取整个文件内容。推荐使用read(size)方法,size越大运行时间越长 readline(): 每次读取一行内容。内存不够时使用,一般不太用 readlines(): 一次性读取整个文件内容,并按行返回到list,方便我们遍历 一般小文件我们都采用read(),不确定大小你就定个size,大文件就用readlines()
哈希函数(Hash Function),也称为散列函数,给定一个输入x,它会算出相应的输出H(x)。哈希函数的主要特征是:
- 输入x可以是任意长度的字符串
- 输出结果即H(x)的长度是固定的
- 计算H(x)的过程是高效的(对于长度为n的字符串x, 计算出H(x)的时间复杂度应为O(n))
- 免碰撞:即不会出现输入x≠y,但是H(x)=H(y) 的情况,其实这个特点在理论上并不成立,比如目前比特币使用的 SHA256 算法,会有 2^256 种输出,如果我们进行 2^256 + 1 次输入,那么必然会产生一次碰撞,事实上,通过 理论证明 ,通过 2^130 次输入就会有99%的可能性发生一次碰撞,不过即使如此,即便是人类制造的所有计算机自宇宙诞生开始一直运算到今天,发生一次碰撞的几率也是极其微小的。
- 隐匿性:也就是说,对于一个给定的输出结果 H(x) ,想要逆推出输入 x ,在计算上是不可能的。如果想要得到 H(x) 的可能的原输入,不存在比穷举更好的方法。 hash 算法的原理是试图将一个空间的数据集映射到另外一个空间(通常比原空间要小),并利用质数将数据集能够均匀的映射。目前主流的 hash 算法有:md4、md5、sha系列。
通常不需要在Python中重载函数。Python是动态类型的,并支持函数的可选参数。
函数可以作为参数传递的语言,可以使用装饰器
import datetime
class TimeException(Exception):
def __init__(self, exception_info):
super().__init__()
self.info = exception_info
def __str__(self):
return self.info
def timecheck(func):
def wrapper(*args, **kwargs):
if datetime.datetime.now().year == 2019:
func(*args, **kwargs)
else:
raise TimeException("函数已过时")
return wrapper
@timecheck
def test(name):
print("Hello {}, 2019 Happy".format(name))
if __name__ == "__main__":
test("backbp")- 函数设计要尽量短小,嵌套层次不宜过深。避免过长函数,嵌套最好能控制在3层之内。
- 函数申明应该合理,简单,易于使用。除函数名能够够正确反映其大体功能外,参数的设计也应该简洁明了,参数个数不宜太多。
- 函数参数设计应该考虑向下兼容。可以通过加入默认参数来避免退化。
- 一个函数只做一件事,就要尽量保证抽象层级的一致性,所有语句尽量在一个粒度上。若在一个函数中处理多件事,不利于代码的重用。 Python中函数设计的好习惯还包括,不要在函数中定义可变对象作为默认值,使用异常替换返回错误,保证通过单元测试等。
Python中函数参数是引用传递(注意不是值传递)。对于不可变类型(数值型、字符串、元组),因变量不能修改,所以运算不会影响到变量自身;而对于可变类型(列表、字典)来说,函数体运算可能 C9BC 会更改传入的参数变量。
函数内部global声明 修改全局变量
缺省参数指在调用函数的时候没有传入参数的情况下,调用默认的参数,在调用函数的同时赋值时, 所传入的参数会替代默认参数。
args是不定长参数,他可以表示输入参数是不确定的,可以是任意多个。
kwargs是关键字参数,赋值的时候是以key=value的方式,参数是可以任意多对在定义函数的时候不确定会有多少参数会传入时,就可以使用两个参数。
函数可以作为参数传递的语言,可以使用装饰器
在实际使用中,我们有时希望将函数作为参数传递给另一个方法使用。 比如装饰器实际就是函数调用函数
如果要调用的方法的入参个数不确定,可以使用*args或**args。但是一定要把*args放到最后面
pass语句什么也不做,一般作为占位符或者创建占位程序,pass语句不会执行任何操作
map() 函数接收两个参数,一个是函数,一个是Iterable(可迭代对象),map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator(迭代器)返回。 reduce() 把一个函数作用在一个序列上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算
在计算机程序设计中,回调函数,或简称回调(Callback),是指通过函数参数传递到其它代码的,某一块可执行代码的引用。这一设计允许了底层代码调用在高层定义的子程序。
有两种类型的回调函数:即blocking callbacks (also known as synchronous callbacks or just callbacks) and deferred callbacks (also known as asynchronous callbacks).
那么,在python中如何实现回调函数呢,看代码
def my_callback(input):
print "function my_callback was called with %s input" % (input,)
def caller(input, func):
func(input)
for i in range(5):
caller(i, my_callback)来自https://www.cnblogs.com/berlin-sun/p/callbackinpython.html
int:整型; bool:布尔; str:字符串; list:列表; tuple:元组; dict:字典; float 浮点型小数
输出字符串"a"的内建方法。
hasattr(object, name)函数: 判断一个对象里面是否有name 属性或者name 方法,返回bool 值,有name 属性(方法)返回True, 否则返回 False。 getattr(object, name[,default]) 函数: 获取对象 object 的属性或者方法,如果存在则打印出来,如果不存在,打印默认值,默认值可选。注意:如果返回的是对象的方法,则打印结果是:方法的内存地址,如果需要运行这个方法,可以在后面添加括号()。 setattr(object,name,values)函数: 给对象的属性赋值,若属性不存在,先创建再赋值
def factorial(num):
j = 1
for i in range(1, num + 1):
j = j * i
print(j)
num = int(input("请输入阶乘数字:"))
factorial(num)
reduce(lambda x, i : x * i, range(1, 100))Python 递归深度可以用内置函数库中的sys.getrecursionlimit()查看。
因为无限递归会导致的C堆栈溢出和Python崩溃。
递归的终止条件一般定义在递归函数内部,在递归调用前要做一个条件判断,根据判断的结果选择是继续调用自身,还是return; 返回终止递归。 终止的条件:
- 判断递归的次数是否达到某一限定值
- 判断运算的结果是否达到某个范围等,根据设计的目的来选择
lambda函数是一个可以接收任意多个参数(包括可选参数)并且返回单个表达式值的匿名函数 好处:
- lambda 函数比较轻便,即用即删除,很适合需要完成一项功能,但是此功能只在此一处使用,连名字都很随意的情况下;
- 匿名函数,一般用来给filter、map这样的函数式编程服务;
- 作为回调函数,传递给某些应用,比如消息处理
from functools import reduce
reduce(lambda x, y : x + y, [2, 3])设计模式是经过总结,优化的,对我们经常会碰到的一些编程问题的可重用解决方案。一个设计模式并不像一个类或一个库那样能够直接作用于我们的代码,反之,设计模式更为高级,它是一种必须在特定情形下实现的一种方法模板。 常见的是工厂模式和单例模式
单例模式应用的场景一般发现在以下条件下:
- 资源共享的情况下,避免由于资源操作时导致的性能或损耗等,如日志文件,应用配置。
- 控制资源的情况下,方便资源之间的互相通信。如线程池等,1,网站的计数器 2,应用配置 3.多线程池 4数据库配置 数据库连接池 5.应用程序的日志应用...
装饰器本质上是一个callable object,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。
import time
from functools import wraps
def timeit(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.clock()
ret = func(*args, **kwargs)
end = time.clock()
print('used:',end-start)
return ret
return wrapper
@timeit
def foo():
print('in foo()' foo())在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包。
装饰器本质上是一个callable object,它可以在让其他函数在不需要做任何代码的变动的前提下增加额外的功能。装饰器的返回值也是一个函数的对象,它经常用于有切面需求的场景。比如:插入日志,性能测试,事务处理,缓存。权限的校验等场景,有了装饰器就可以抽离出大量的与函数功能本身无关的雷同代码并发并继续使用。 详细参考:https://manjusaka.itscoder.com/2018/02/23/something-about-decorator/
迭代器是遵循迭代协议的对象。用户可以使用iter()以从任何序列得到迭代器(如list、tuple、dictionary、set等)。另一个方法则是创建一个另一种形式的迭代器——generator。要获取下一个元素,则使用成员函数next()。当没有元素时,则引发StopIteration此例外。若要实现自己的迭代器,则只要实现 __next__。
生成器(Generator),只是在需要返回数据的时候使用yield语句。每次next()被调用时,生成器会返回它脱离的位置(它记忆语句最后一次执行的位置和所有的数据值)
区别: 生成器能做到迭代器能做的所有事,而且因为自动创建iter()和next()方法,生成器显得特别简洁,而且生成器也是高效的,使用生成器表达式取代列表解析可以同时节省内存。除了创建和保存程序状态的自动方法,当发生器终结时,还会自动抛出StopIteration异常。
官方介绍:https://docs.python.org/3/tutorial/classes.html#iterators
any(): 只要迭代器中有一个元素为真就为真
all(): 迭代器中所有的判断项返回都是真,结果才为真
python中什么元素为假?(0,空字符串,空列表、空字典、空元组、None, False)
X= (i for i in range(10)) X是generator类型
N =100
print([[x for x in range(1, 100)][i:i + 3] for i in range(0, 100, 3)])yield就是保存当前程序执行状态。你用for循环的时候,每次取一个元素的时候就会计算一次。用yield的函数叫generator,和iterator一样,它的好处是不用一次计算所有元素,而是用一次算一次,可以节省很多空间,generator每次计算需要上一次计算结果,所以用yield,否则一return,上次计算结果就没了
不可变对象: 数值型、字符串、元组 可变对象: 列表、字典
__init__:对象初始化方法
__new__:创建对象时候执行的方法,单列模式会用到
__str__:当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据
__del__:删除对象执行的方法
- __init__是初始化方法,创建对象后,就立刻被默认调用了,可接收参数
- __new__至少要有一个参数cls,代表当前类,此参数在实例化时由Python解释器自动识别
- __new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类(通过super(当前类名, cls))__new__出来的实例,或者直接是object的__new__出来的实例
- __init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值
- 如果__new__创建的是当前类的实例,会自动调用__init__函数,通过return语句里面调用的__new__函数的第一个参数是cls来保证是当前类实例,如果是其他类的类名,;那么实际创建返回的就是其他类的实例,其实就不会调用当前类的__init__函数,也不会调用其他类的__init__函数。
property装饰器把方法变成了类的属性
class Demo():
__name = "test"
@property
def name(self):
return self.__name面向对象是相对于面向过程而言的。面向过程语言是一种基于功能分析的、以算法为中心的程序设计方法;而面向对象是一种基于结构分析的、以数据为中心的程序设计思想。在面向对象语言中有一个有很重要东西,叫做类。
面向对象有三大特性:封装、继承、多态。
import re
a = "not 404 found 张三 99 深圳"
lists = a.split(' ')
print(lists)
res = re.findall('\d+|[a-zA-Z]+', a)
for i in res:
if i in lists:
lists.remove(i)
new_str = " ".join(res)
print(res)
print(new_str)import re
pattern = r'\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b'
regex = re.compile(pattern, re)
result = regex.findall(testString)import re
url=r'https://sycm.taobao.com/bda/tradinganaly/overview/get_summary.json?dateRange=2018-03-20%7C2018-03-20&dateType=recent1&device=1&token=ff25b109b&_=1521595613462'
res = re.findall(r'dateRange(.*?)%7C(.*?)&', url)
print(res)import re
strs = <div class="nam">中国</div>
res = re.findall(r'<idv class=".">(.*?)</div>', strs)
print(res).: 代表可有可无
*: 代表任意字符
(.*?): 提取文本
(.*): 是贪婪匹配,会把满足正则的尽可能多的往后匹配
(.*?): 是非贪婪匹配,会把满足正则的尽可能少匹配
import re a = "张明 98分" res = re.sub(r'\d+', '100', a) print(res)