可变对象:list dict set
不可变对象:int float bool string tuple
文章链接: https://www.jianshu.com/p/c5582e23b26c — 仔细看
文章链接: https://www.cnblogs.com/kumata/p/9099134.html
或者看我自己的博客
文章链接: https://blog.csdn.net/yangnianjinxin/article/details/79025768
文章链接: https://blog.csdn.net/qq_42166308/article/details/103356606
装饰器本质上是一个Python函数,它可以让其它函数在不作任何变动的情况下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景。比如:插入日志、性能测试、事务处理、缓存、权限校验等。有了装饰器我们就可以抽离出大量的与函数功能无关的雷同代码进行重用。
视频链接: https://www.bilibili.com/video/av18586448?from=search&seid=10638981423280212097
文章链接: https://blog.csdn.net/leviopku/article/details/83580138
文章链接: https://blog.csdn.net/G_SANGSK/article/details/80867629
print("\n".join("\t".join("%s*%s=%s" %(x,y,x*y) for y in range(1, x+1)) for x in range(1, 10)))
import copy
a = [1, 2, 3, 4, ['a', 'b']] #原始对象
b = a #赋值,传对象的引用
c = copy.copy(a) #对象拷贝,浅拷贝
d = copy.deepcopy(a) #对象拷贝,深拷贝
a.append(5) #修改对象a
a[4].append('c') #修改对象a中的['a', 'b']数组对象
print 'a = ', a
print 'b = ', b
print 'c = ', c
print 'd = ', d
输出结果:
a = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c = [1, 2, 3, 4, ['a', 'b', 'c']]
d = [1, 2, 3, 4, ['a', 'b']]
新式类是采用广度优先搜索,旧式类采用深度优先搜索。
sun(range(1,101))
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aetKMR7v-1584576197094)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1577689875331.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yewGs1Rs-1584576197096)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1577696916198.png)]
https://www.cnblogs.com/nxf-rabbit75/p/10660317.html
sorted(d.items(),key=lambda x :x[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
#第二种 重点!!! t.split(':'),加了逗号就可以 相当于解包以为求出来需要[]取出,这里直接就可以加逗号解包
print({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)
https://www.cnblogs.com/huchong/p/8244279.html
第一种方法:使用装饰器
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._instance
# Python2
class Foo(object):
__metaclass__ = Singleton
# Python3
class Foo(metaclass=Singleton):
pass
foo1 = Foo()
foo2 = Foo()
print(foo1 is foo2) # True
class 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 #2^31-1
if __name__ == '__main__':
s = Solution()
reverse_int = s.reverse(-120)
print(reverse_int)
import os
#os.walk()方法
#参考https://blog.csdn.net/bagboy_taobao_com/article/details/8938126
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')
函数作用域的LEGB顺序
1.什么是LEGB?
L: local 函数内部作用域
E: enclosing 函数内部与内嵌函数之间
G: global 全局作用域
B: build-in 内置作用
python在函数里面的查找分为4种,称之为LEGB,也正是按照这是顺序来查找的
"123"
转换成 123
,不使用内置api,例如 int()
#1.str函数
def get_value(s):
num = 0
for i in s:
for j in range(10):
if i == str(j):
num = num * 10 +j
return num
#2.巧妙利用ord()函数
def get_value(s):
num = 0
for i in s:
num = num * 10 +ord(i) - ord('0')
return num
#3.使用reduce方法
#参考https://www.runoob.com/python/python-func-reduce.html
from functools import reduce
def get_value(s):
return reduce(lambda num, i: num * 10 + ord(i) - ord('0'), s, 0)
#这里第三个参数是初始化num=0定义为整数,你可以自己试一试修改这个值
def get_value(s):
return reduce(lambda num, i: num * 10 + ord(i) - ord('0'), s, 1)
#答案为1123
def func1(nums,target):
for i in range(len(nums)):
num = target - nums[i]
if num in nums:
return [i, nums.index(num,i+1)] #从i+1之后开始找
#这里是让掌握.index()函数
#list.index(x[, start[, end]])
#x-- 查找的对象。
#start-- 可选,查找的起始位置。
#end-- 可选,查找的结束位置。
# 使用 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)))
def loop_merge_sort(l1,l2):
tmp = []
while len(l1)>0 and len(l2)>0:
if l1[0] <l2[0]:
tmp.append(l1[0])
del l1[0]
else:
tmp.append(l2[0])
del l2[0]
while len(l1)>0:
tmp.append(l1[0])
del l1[0]
while len(l2)>0:
tmp.append(l2[0])
del l2[0]
return tmp
#第一种方法
l1 = sorted([x for x in s if int(x) % 2 == 0],reverse=True)
l2 = sorted([x for x in s if int(x) % 2 != 0])
out = l2 + l1
#第二种方法!!!(重点)
print("".join(sorted(l, key=lambda x: int(x) % 2 == 0 and 20 - int(x) or int(x))))
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]
#1.条件 x % 2 == 0
发现新大陆 偶数和1做与运算为0 奇数为1
#2.条件 x & 1 != 0(奇数) 3&1输出1 4&1输出0
文章链接: https://www.jianshu.com/p/44981aba7b1c
其中有个发现点:
>>> list1 = [11,22,33]
>>> map(None,list1)
[11, 22, 33]
>>> list1 = [11,22,33]
>>> list2 = [44,55,66]
>>> list3 = [77,88,99]
>>> map(None,list1,list2,list3)
[(11, 44, 77), (22, 55, 88), (33, 66, 99)]
#和zip(list1,list2,list3)使用一样
文章链接: https://blog.csdn.net/lihao21/article/details/79762681
文章链接: https://www.zhihu.com/question/24695645
if hasattr(Parent, 'x'):
print(getattr(Parent, 'x'))
setattr(Parent, 'x',3)
print(getattr(Parent,'x'))
文章链接: https://www.cnblogs.com/xybaby/p/7491656.html 很全面,认真看!!
Python的参数传递有:位置参数、默认参数、可变参数、关键字参数。
函数的传值到底是值传递还是引用传递、要分情况:
不可变参数用值传递:像整数和字符串这样的不可变对象,是通过拷贝进行传递的,因为你无论如何都不可能在原处改变不可变对象。
可变参数是引用传递:比如像列表,字典这样的对象是通过引用传递、和C语言里面的用指针传递数组很相似,可变对象能在函数内部改变。
reduce(lambda x,y : x*y,range(1,n+1))
N =100
print ([[x for x in range(1,100)] [i:i+3] for i in range(0,N,3)])
将对象私有化,通过共有方法提供一个读取数据的接口
class person:
def __init__(self, x):
self.__age = 10
def age(self):
return self.__age
t = person(22)
# t.__age =100
print(t.age())
最好的方法
class MyCls(object):
__weight = 50
@property
def weight(self):
return self.__weight
面向对象是相当于面向过程而言的,面向过程语言是一种基于功能分析的,以算法为中心的程序设计方法,而面向对象是一种基于结构分析的,以数据为中心的程序设计思想。在面向对象语言中有一个很重要的东西,叫做类。面向对象有三大特性:封装、继承、多态。
知乎: 把一组数据结构和处理它们的方法组成对象(object), 把相同行为的对象归纳为类(class), 通过类的封装(encapsulation)隐藏内部细节, 通过继承(inheritance)实现类的特化(specialization)/泛化(generalization), ,通过多态(polymorphism)实现基于对象类型的动态分派(dynamic dispatch)。
#思路:不管有多少个b替换成一个
re.sub(r'b+', 'b', a)
#re.sub()补充看这个文章https://blog.csdn.net/lovemianmian/article/details/8867613
贪婪模式:
定义:正则表达式去匹配时,会尽量多的匹配符合条件的内容
标识符:+,?,*,{n},{n,},{n,m}
匹配时,如果遇到上述标识符,代表是贪婪匹配,会尽可能多的去匹配内容
非贪婪模式:
定义:正则表达式去匹配时,会尽量少的匹配符合条件的内容 也就是说,一旦发现匹配符合要求,立马就匹配成功,而不会继续匹配下去(除非有g,开启下一组匹配)
标识符:+?,??,*?,{n}?,{n,}?,{n,m}?
可以看到,非贪婪模式的标识符很有规律,就是贪婪模式的标识符后面加上一个?
进程:程序运行在操作系统上的一个实例,就称之为进程。进程需要相应的系统资源:内存、时间片、pid。 创建进程: 首先要导入multiprocessing中的Process: 创建一个Process对象; 创建Process对象时,可以传递参数;
p = Process(target=XXX,args=(tuple,),kwargs={key:value})
#target = XXX 指定的任务函数,不用加(),
#args=(tuple,)kwargs={key:value}给任务函数传递的参数
在初始化Queue()对象时(例如q=Queue(),若在括号中没有指定最大可接受的消息数量,获数量为负值时,那么就代表可接受的消息数量没有上限一直到内存尽头)
Queue.qsize():返回当前队列包含的消息数量
Queue.empty():如果队列为空,返回True,反之False
Queue.full():如果队列满了,返回True,反之False
Queue.get([block[,timeout]]):获取队列中的一条消息,然后将其从队列中移除,
block默认值为True。
如果block使用默认值,且没有设置timeout(单位秒),消息队列如果为空,此时程序将被阻塞(停在读中状态),直到消息队列读到消息为止,如果设置了timeout,则会等待timeout秒,若还没读取到任何消息,则抛出“Queue.Empty"异常:
Queue.get_nowait()相当于Queue.get(False)
Queue.put(item,[block[,timeout]]):将item消息写入队列,block默认值为True; 如果block使用默认值,且没有设置timeout(单位秒),消息队列如果已经没有空间可写入,此时程序将被阻塞(停在写入状态),直到从消息队列腾出空间为止,如果设置了timeout,则会等待timeout秒,若还没空间,则抛出”Queue.Full"异常 如果block值为False,消息队列如果没有空间可写入,则会立刻抛出"Queue.Full"异常; Queue.put_nowait(item):相当Queue.put(item,False)
from multiprocessing import Process,Queue
import os,time,random
#写数据进程执行的代码:
def write(q):
for value in ['A','B','C']:
print("Put %s to queue..."%(value))
q.put(value)
time.sleep(random.random())
#读数据进程执行的代码
def read(q):
while True:
if not q.empty():
value = q.get(True)
print("Get %s from queue."%(value))
time.sleep(random.random())
else:
break
if __name__=='__main__':
#父进程创建Queue,并传给各个子进程
q = Queue()
pw = Process(target=write,args=(q,))
pr = Process(target=read,args=(q,))
#启动子进程pw ,写入:
pw.start()
#等待pw结束
pw.join()
#启动子进程pr,读取:
pr.start()
pr.join()
#pr 进程里是死循环,无法等待其结束,只能强行终止:
print('所有数据都写入并且读完')
进程池:
from multiprocessing import Pool
import os,time,random
def worker(msg):
t_start = time.time()
print("%s 开始执行,进程号为%d"%(msg,os.getpid()))
# random.random()随机生成0-1之间的浮点数
time.sleep(random.random()*2)
t_stop = time.time()
print(msg,"执行完毕,耗时%0.2f”%(t_stop-t_start))
po = Pool(3)#定义一个进程池,最大进程数3
for i in range(0,10):
po.apply_async(worker,(i,))
print("---start----")
po.close()
po.join()
print("----end----")
如果要使用Pool创建进程,就需要使用multiprocessing.Manager()中的Queue(),而不是multiprocessing.Queue(),否则会得到如下的错误信息:
RuntimeError: Queue objects should only be shared between processs through inheritance
from multiprocessing import Manager,Pool
import os,time,random
def reader(q):
print("reader 启动(%s),父进程为(%s)"%(os.getpid(),os.getpid()))
for i in range(q.qsize()):
print("reader 从Queue获取到消息:%s"%q.get(True))
def writer(q):
print("writer 启动(%s),父进程为(%s)"%(os.getpid(),os.getpid()))
for i ini "itcast":
q.put(i)
if __name__ == "__main__":
print("(%s)start"%os.getpid())
q = Manager().Queue()#使用Manager中的Queue
po = Pool()
po.apply_async(wrtier,(q,))
time.sleep(1)
po.apply_async(reader,(q,))
po.close()
po.join()
print("(%s)End"%os.getpid())
这个问题被问的概念相当之大, 进程:一个运行的程序(代码)就是一个进程,没有运行的代码叫程序,进程是系统资源分配的最小单位,进程拥有自己独立的内存空间,所有进程间数据不共享,开销大。
线程: cpu调度执行的最小单位,也叫执行路径,不能独立存在,依赖进程存在,一个进程至少有一个线程,叫主线程,而多个线程共享内存(数据共享,共享全局变量),从而极大地提高了程序的运行效率。
协程: 是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操中栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。
import threading
import time
class MyThread(threading.Thread):
def run(self):
global num
time.sleep(1)
if mutex.acquire(1):
num +=1
msg = self.name + 'set num to ' +str(num)
print(msg)
mutex.release()
num = 0
mutex = threading.Lock()
def test():
for i in range(5):
t = MyThread()
t.start()
if __name__=="__main__":
test()
线程是非独立的,同一个进程里线程是数据共享的,当各个线程访问数据资源时会出现竞争状态即:数据几乎同步会被多个线程占用,造成数据混乱,即所谓的线程不安全
那么怎么解决多线程竞争问题?—锁
锁的好处: 确保了某段关键代码(共享数据资源)只能由一个线程从头到尾完整地执行能解决多线程资源竞争下的原子操作问题。
锁的坏处: 阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了
锁的致命问题: 死锁
一、 setDaemon(False) 当一个进程启动之后,会默认产生一个主线程,因为线程是程序执行的最小单位,当设置多线程时,主线程会创建多个子线程,在Python中,默认情况下就是setDaemon(False),主线程执行完自己的任务以后,就退出了,此时子线程会继续执行自己的任务,直到自己的任务结束。
例子
import threading
import time
def thread():
time.sleep(2)
print('---子线程结束---')
def main():
t1 = threading.Thread(target=thread)
t1.start()
print('---主线程--结束')
if __name__ =='__main__':
main()
#执行结果
---主线程--结束
---子线程结束---
二、 setDaemon(True) 当我们使用setDaemon(True)时,这是子线程为守护线程,主线程一旦执行结束,则全部子线程被强制终止
例子
import threading
import time
def thread():
time.sleep(2)
print(’---子线程结束---')
def main():
t1 = threading.Thread(target=thread)
t1.setDaemon(True)#设置子线程守护主线程
t1.start()
print('---主线程结束---')
if __name__ =='__main__':
main()
#执行结果
---主线程结束--- #只有主线程结束,子线程来不及执行就被强制结束
三、 join(线程同步) join 所完成的工作就是线程同步,即主线程任务结束以后,进入堵塞状态,一直等待所有的子线程结束以后,主线程再终止。
当设置守护线程时,含义是主线程对于子线程等待timeout的时间将会杀死该子线程,最后退出程序,所以说,如果有10个子线程,全部的等待时间就是每个timeout的累加和,简单的来说,就是给每个子线程一个timeou的时间,让他去执行,时间一到,不管任务有没有完成,直接杀死。
没有设置守护线程时,主线程将会等待timeout的累加和这样的一段时间,时间一到,主线程结束,但是并没有杀死子线程,子线程依然可以继续执行,直到子线程全部结束,程序退出。
例子
import threading
import time
def thread():
time.sleep(2)
print('---子线程结束---')
def main():
t1 = threading.Thread(target=thread)
t1.setDaemon(True)
t1.start()
t1.join(timeout=1)#1 线程同步,主线程堵塞1s 然后主线程结束,子线程继续执行
#2 如果不设置timeout参数就等子线程结束主线程再结束
#3 如果设置了setDaemon=True和timeout=1主线程等待1s后会强制杀死子线程,然后主线程结束
print('---主线程结束---')
if __name__=='__main___':
main()
死锁是指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
原因和解决方案: https://baike.baidu.com/item/%E6%AD%BB%E9%94%81
扩展:GIL锁 全局解释器锁
作用: 限制多线程同时执行,保证同一时间只有一个线程执行,所以cython里的多线程其实是伪多线程!
所以python里常常使用协程技术来代替多线程,协程是一种更轻量级的线程。
进程和线程的切换时由系统决定,而协程由我们程序员自己决定,而模块gevent下切换是遇到了耗时操作时才会切换
三者的关系:进程里有线程,线程里有协程。
同步: 多个任务之间有先后顺序执行,一个执行完下个才能执行。
异步: 多个任务之间没有先后顺序,可以同时执行,有时候一个任务可能要在必要的时候获取另一个同时执行的任务的结果,这个就叫回调!
阻塞: 如果卡住了调用者,调用者不能继续往下执行,就是说调用者阻塞了。
非阻塞: 如果不会卡住,可以继续执行,就是说非阻塞的。
同步异步相对于多任务而言,阻塞非阻塞相对于代码执行而言。
多进程适合在CPU密集操作(cpu操作指令比较多,如位多的的浮点运算)。
多线程适合在IO密性型操作(读写数据操作比多的的,比如爬虫)
并行: 同一时刻多个任务同时在运行
并发:不会在同一时刻同时运行,存在交替执行的情况。
实现并行的库有:multiprocessing
实现并发的库有: threading
程序需要执行较多的读写、请求和回复任务的需要大量的IO操作,IO密集型操作使用并发更好。
CPU运算量大的程序,使用并行会更好
所以:线程是并发,进程是并行;
进程之间互相独立,是系统分配资源的最小单位,同一个线程中的所有线程共享资源。
第一范式:要求有主键,并且要求每一个字段原子性不可再分
第二范式:要求所有非主键字段完全依赖主键,不能产生部分依赖
第三范式:所有非主键字段和主键字段之间不能产生传递依赖
文章链接: https://blog.csdn.net/moxigandashu/article/details/63254901
了解:视图是虚拟的表,与包含数据的表不一样,视图只包含使用时动态检索数据的查询;不包含任何列或数据。使用视图可以简化复杂的sql操作,隐藏具体的细节,保护数据;视图创建后,可以使用与表相同的方式利用它们。
视图不能被索引,也不能有关联的触发器或默认值,如果视图本身内有order by则对视图再次order by将被覆盖。
创建视图: create view xxx as xxxxxx
对于某些视图比如未使用联结子查询分组聚集函数Distinct Union等,是可以对其更新的,对视图的更新将对基表进行更新;但是视图主要用于简化检索,保护数据,并不用于更新,而且大部分视图都不可以更新。
文章链接:https://blog.csdn.net/qq_36145093/article/details/88327148
文章链接: https://www.cnblogs.com/LILi666/p/10930309.html
文章链接: https://www.cnblogs.com/jasontec/p/9699242.html
一只青蛙要跳上n层高的台阶,一次能跳一级,也可以跳两级,请问这只青蛙有多少种跳上这个n层台阶的方法?
方法1:递归
设青蛙跳上n级台阶有f(n)种方法,把这n种方法分为两大类,第一种最后一次跳了一级台阶,这类共有f(n-1)种,第二种最后一次跳了两级台阶,这种方法共有f(n-2)种,则得出递推公式f(n)=f(n-1) + f(n-2),显然f(1)=1,f(2)=2,这种方法虽然代码简单,但效率低,会超出时间上限
class Solution:
def climbStairs(self,n):
if n ==1:
return 1
elif n==2:
return 2
else:
return self.climbStairs(n-1) + self.climbStairs(n-2)
方法2:用循环来代替递归
class Solution:
def climbStairs(self,n):
if n==1 or n==2:
return n
a,b,c = 1,2,3
for i in range(3,n+1):
c = a+b
a = b
b = c
return c
文章链接: https://www.cnblogs.com/yyds/p/6563608.html
注意:
Python dict中的非字符串key被转换成JSON字符串时都会被转换为小写字符串;
Python中的tuple,在序列化时会被转换为array,但是反序列化时,array会被转化为list;
由以上两点可知,当Python对象中包含tuple数据或者包含dict,且dict中存在非字符串的key时,反序列化后得到的结果与原来的Python对象是不一致的;
对于Python内置的数据类型(如:str, unicode, int, float, bool, None, list, tuple, dict)
json模块可以直接进行序列化/反序列化处理;对于自定义类的对象进行序列化和反序列化时,需要我们自己定义一个方法来完成定义object和dict之间进行转化
#第一种 非递归方法
def binary_search(alist,item):
n = len(alist)
start = 0
end = len(alist) - 1
while start <= end:
mid = (start + end) // 2
if alist[mid] == item:
return mid
elif item < alist[mid]:
end = mid - 1
else:
start = mid + 1
return False
print(binary_search([1,2,3,34,56,57,78,87],3))
#第二种 递归方法
def binary_search(alist,item):
n = len(alist)
if 0 == n:
return False
mid = n // 2
if alist[mid] == item:
return mid
elif item < alist[mid]:
return binary_search(alist[:mid], item)
else:
return binary_search(alist[mid + 1:], item)
print(binary_search([1,2,3,34,56,57,78,87],3))
一、实现栈的方法:
class Stack():
def __init__(self, size):
self.size = size
self.stack = []
self.top = -1
def push(self, x):
if self.isfull():
raise Exception('stack is full')
else:
self.stack.append(x)
self.top += 1
def pop(self):
if self.isempty():
raise Exception('stack is empty')
else:
self.top -= 1
self.stack.pop()
def isfull(self):
return self.top + 1 == self.size
def isempty(self):
return self.top == -1
def showstack(self):
print(self.stack)
s = Stack(10)
for i in range(6):
s.push(i)
s.showstack()
for i in range(3):
s.pop()
s.showstack()
二、实现单向队列:【day22数据结构视频!!】
class Queue():
def __init__(self, size):
self.size = size
self.queue = []
self.rear = -1
self.front = -1
def enqueue(self, ele):
if self.isfull():
raise Exception('queue is full')
else:
self.queue.append(ele)
self.rear += 1
def denqueue(self):
if self.isempty():
raise Exception('queue is empty')
else:
self.queue.pop(0)
self.front += 1
def isfull(self):
return self.rear - self.front + 1 == self.size
def isempty(self):
return self.front == self.rear
def showenqueue(self):
print(self.queue)
queue = Queue(10)
for i in range(5):
queue.enqueue(i)
queue.showenqueue()
for i in range(3):
queue.denqueue()
queue.showenqueue()
三、实现双向队列:
'''
双端队列:(deque,全名double-ended queue),是一种具有队列和栈的性质的数据结构。
双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行。双端队列可以在队列任意一端入队和出队。
'''
from collections import deque
class Deque:
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def add_front(self, item):
# 从头部添加
self.items.insert(0, item)
def add_rear(self, item):
self.items.append(item)
def remove_front(self):
return self.items.pop(0)
def remove_rear(self):
return self.items.pop()
def size(self):
return len(self.items)
def print_all(self):
for item in self.items:
print(item)
if __name__ == '__main__':
dq = Deque()
dq.add_front(8)
dq.add_front(9)
dq.add_front(0)
dq.print_all()
dq.add_rear(6)
dq.print_all()
print('-----------remove---------')
dq.remove_front()
dq.print_all()
四、实现单链表 【对应day21数据结构视频】
class Node:
def __init__(self, data):
self.data = data
self.next = None
def __str__(self):
return str(self.data)
class SingleList:
def __init__(self, node=None):
self._head = node
def isEmpty(self):
return self._head == None
def append(self, item):
# 尾部添加
node = Node(item)
if self.isEmpty():
self._head = node
else:
cur = self._head
while cur.next != None:
cur = cur.next
cur.next = node
# 求长度
def len(self):
cur = self._head
count = 0
while cur != None:
count += 1
cur = cur.next
return count
# 遍历
def print_all(self):
cur = self._head
while cur != None:
print(cur)
cur = cur.next
def pop(self, index):
if index < 0 or index >= self.len():
raise IndexError('index Error')
if index == 0:
self._head = self._head.next
else:
cur = self._head
# 找到当前下标的前一个元素!!
while index - 1:
cur = cur.next
index -= 1
# 修改的next的指向位置
cur.next = cur.next.next
def insert(self, index, item):
if index < 0 or index >= self.len():
raise IndexError('index Error')
if isinstance(item, Node):
raise TypeError('不能是Node类型')
else:
node = Node(item)
if index == 0:
node.next = self._head
self._head = node
else:
cur = self._head
while index - 1:
cur = cur.next
index -= 1
node.next = cur.next
cur.next = node
def update(self, index, new_item):
pass
def remove(self, item):
pass
if __name__ == '__main__':
slist = SingleList()
print(slist.isEmpty()) # True
print(slist.len())
slist.append(5)
print(slist.isEmpty()) # False
print(slist.len()) # 1
slist.append(8)
slist.append(6)
slist.append(3)
slist.append(1)
print(slist.isEmpty()) # True
print(slist.len())
print('---------------------')
slist.print_all()
print('----------pop-------------')
slist.pop(2)
slist.print_all()
print('--------insert-------')
slist.insert(1, 19)
slist.print_all()
五、实现双向链表
class Node:
def __init__(self, data):
self.data = data
self.next = None
self.prev = None
def __str__(self):
return str(self.data)
class DoubleList:
def __init__(self):
self._head = None
def isEmpty(self):
return self._head == None
def append(self, item):
# 尾部添加
node = Node(item)
if self.isEmpty():
self._head = node
else:
cur = self._head
while cur.next != None:
cur = cur.next
cur.next = node
# 求长度
def add(self, item):
node = Node(item)
if self.isEmpty():
self._head = node
else:
node.next = self._head
self._head.prev = node
self._head = node
def len(self):
cur = self._head
count = 0
while cur != None:
count += 1
cur = cur.next
return count
def print_all(self):
cur = self._head
while cur != None:
print(cur)
cur = cur.next
def insert(self, index, item):
if index < 0 or index >= self.len():
raise IndexError('Index Error')
if index == 0:
node = Node(item)
node.next = self._head
self._head.prev = node
self._head = node
else:
node = Node(item)
cur = self._head
# 也是找到前一个元素
while index - 1:
cur = cur.next
index -= 1
# 下面这四句顺序无所谓
node.prev = cur
node.next = cur.next
# 因为是双向的,所以反方向也得写
cur.next.prev = node
cur.next = node
def remove(self, item):
if self.isEmpty():
raise ValueError('item not in doublelinklist')
else:
cur = self._head
if cur.data == item:
# 删除的是头结点
if cur.next == None:
# 只有头部节点
self._head = None
else:
# 还有其他节点
cur.next.prev = None
self._head = cur.next
else:
while cur != None:
if cur.data == item:
cur.prev.next = cur.next
cur.next.prev = cur.prev
break
cur = cur.next
def update(self, index, item):
pass
if __name__ == '__main__':
dlist = DoubleList()
print(dlist.len())
print(dlist.isEmpty())
# dlist.append(6)
# dlist.append(9)
# dlist.append(5)
# print(dlist.len())
# print(dlist.isEmpty())
# dlist.print_all()
dlist.add(6)
dlist.add(9)
dlist.add(5)
dlist.print_all()
六、实现树结构:
class Node:
def __init__(self, data):
self.data = data
self.lchild = None
self.rchild = None
class Tree:
def __init__(self):
self.root = None
def add(self, data):
node = Node(data)
if self.root is None:
self.root = node
return
queue = [self.root]
while queue:
cur = queue.pop(0)
if cur.lchild is None:
cur.lchild = node
return
else:
queue.append(cur.lchild)
if cur.rchild is None:
cur.rchild = node
return
else:
queue.append(cur.rchild)
# 广度优先
def breadth_travel(self):
if self.root is None:
return
queue = [self.root]
while queue:
cur = queue.pop(0)
print(cur.data, sep=' ', end="")
if cur.lchild is not None:
queue.append(cur.lchild)
if cur.rchild is not None:
queue.append(cur.rchild)
# 先序遍历
def front_travel(self, node):
if node is None:
return
print(node.data, end=' ')
self.front_travel(node.lchild)
self.front_travel(node.rchild)
# 中序遍历
def mid_travel(self, node):
if node is None:
return
self.mid_travel(node.lchild)
print(node.data, end=' ')
self.mid_travel(node.rchild)
def rear_travel(self, node):
if node is None:
return
self.rear_travel(node.lchild)
self.rear_travel(node.rchild)
print(node.data, end=' ')
if __name__ == '__main__':
t = Tree()
for i in range(10):
t.add(i)
t.breadth_travel()
print()
# 执行先序遍历
t.front_travel(t.root)
print()
# 中序遍历
t.mid_travel(t.root)
print()
# 后序遍历
t.rear_travel(t.root)
文章链接: https://blog.csdn.net/u011452172/article/details/78127836
这个也是python彪悍的特性.
自省就是面向对象的语言所写的程序在运行时,所能知道对象的类型.简单一句就是运行时能够获得对象的类型.比如type(),dir(),getattr(),hasattr(),isinstance().
这里有个关于生成器的创建问题面试官有考: 问: 将列表生成式中[]改成() 之后数据结构是否改变? 答案:是,从列表变为生成器
>>> L = [x*x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x*x for x in range(10))
>>> g
<generator object <genexpr> at 0x0000028F8B774200>
通过列表生成式,可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含百万元素的列表,不仅是占用很大的内存空间,如:我们只需要访问前面的几个元素,后面大部分元素所占的空间都是浪费的。因此,没有必要创建完整的列表(节省大量内存空间)。在Python中,我们可以采用生成器:边循环,边计算的机制—>generator
>>> def print_three_things(a, b, c):
... print 'a = {0}, b = {1}, c = {2}'.format(a,b,c)
...
>>> mylist = ['aardvark', 'baboon', 'cat']
>>> print_three_things(*mylist)
a = aardvark, b = baboon, c = cat
文章链接: https://blog.csdn.net/handsomekang/article/details/40270009
class Duck:
def quack(self):
print "这鸭子正在嘎嘎叫"
def feathers(self):
print "这鸭子拥有白色和灰色的羽毛"
class Person:
def quack(self):
print "这人正在模仿鸭子"
def feathers(self):
print "这人在地上拿起1根羽毛然后给其他人看"
def in_the_forest(duck):
duck.quack()
duck.feathers()
def game():
donald = Duck()
john = Person()
in_the_forest(donald)
in_the_forest(john)
game()
文章链接: https://www.zhihu.com/question/20053359
文章链接: https://www.cnblogs.com/aspirant/p/9166944.html
文章链接: https://blog.csdn.net/v123411739/article/details/86652806?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
其中还涉及到bitmap算法、hashmap算法。
https://juejin.im/post/5c4fd2af51882525da267385
文章链接: https://blog.csdn.net/tayanxunhua/article/details/20528389
文章链接: https://www.zhihu.com/question/19853605
协同过滤简单来说是利用某兴趣相投、拥有共同经验之群体的喜好来推荐用户感兴趣的信息,个人通过合作的机制给予信息相当程度的回应(如评分)并记录下来以达到过滤的目的进而帮助别人筛选信息,回应不一定局限于特别感兴趣的,特别不感兴趣信息的纪录也相当重要。
协同过滤又可分为评比(rating)或者群体过滤(social filtering)协同过滤以其出色的速度和健壮性,在全球互联网领域炙手可热。
文章链接: https://blog.csdn.net/yimingsilence/article/details/54934302
https://www.jianshu.com/p/5463ab162a58
文章链接: https://www.nowcoder.com/discuss/100521?type=2
文章链接: https://juejin.im/entry/5c565fb7f265da2d84105958
https://blog.csdn.net/luochoudan/article/details/53736752
视频链接: https://space.bilibili.com/24014925/channel/detail?cid=44716
23411739/article/details/86652806?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
其中还涉及到bitmap算法、hashmap算法。
https://juejin.im/post/5c4fd2af51882525da267385
文章链接: https://blog.csdn.net/tayanxunhua/article/details/20528389
文章链接: https://www.zhihu.com/question/19853605
协同过滤简单来说是利用某兴趣相投、拥有共同经验之群体的喜好来推荐用户感兴趣的信息,个人通过合作的机制给予信息相当程度的回应(如评分)并记录下来以达到过滤的目的进而帮助别人筛选信息,回应不一定局限于特别感兴趣的,特别不感兴趣信息的纪录也相当重要。
协同过滤又可分为评比(rating)或者群体过滤(social filtering)协同过滤以其出色的速度和健壮性,在全球互联网领域炙手可热。
文章链接: https://blog.csdn.net/yimingsilence/article/details/54934302
https://www.jianshu.com/p/5463ab162a58
文章链接: https://www.nowcoder.com/discuss/100521?type=2
文章链接: https://juejin.im/entry/5c565fb7f265da2d84105958
https://blog.csdn.net/luochoudan/article/details/53736752
视频链接: https://space.bilibili.com/24014925/channel/detail?cid=44716
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wX75QSNX-1584576197101)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1583136797062.png)]