实训day03
1.list列表的作用
- 存放数据,并且list存放数据是安全的,但是不能存放大数据的东西,例如:音频、视频、图片等。
- list可以便利数据库的结果集,后续我们讲解MySQL、Oracle和python操作会讲解。 ----重点内容
- list的底层原理是一个bean容器。 -----重点
2.定义List列表 [ ]
my_list1 = [ ] //空列表,[ ]其实就是一个内存空间,所以list可以在[ ]里面存放数据!
my_list2 = [10] //10表示的是给list列表开盘大小为10的空间内存!
my_list3 = ['王老师','李老师','张老师','赵老师'] //直接给列表赋值,表示内存里面有4个字符串值
※拓展:String str = new String(‘abc’) //思考?产生几个对象 ----2个 ----研究堆栈内存的原理
※重点----列表里面可以存放任意类型的东西------list其实也是面向对象
my_list4 = ['hello',12,12.0,True,'范冰冰']
3.如何操作列表
如果后面或者大家去企业拿到一个新技术,此技术只要是可以存放数据,那么这个技术的核心就是CRUD增加、删除、修改、查询)
①List列表通过小标index获取值
②下标的工作原理
i:下标是可以被改变的!更改下表对list的内存空间没有任何的影响
ii:主键primary key id = 1 删除,列入:银行卡,id可以删除,但是会影响数据的性能,数据不
my_list5 = ['郭祎凡','黄晓明','guoyifan','123',121,12.0 ]
print(my_list5[0])
print(my_list5[3])
print(my_list5[7]) //list超出内存空间,报异常
print(my_list5[-1]) //-1表示按照倒序获取值
print(my_list5[-7]) //list超出内存空间,报异常:IndexError:list index out of range
4.len属性函数 len方法
如何区别属性和方法
len(0) //0表示的是list里面存放的对象
print('my_list5的长度:',len(my_list5))
print('my_list5的长度:',len(0))
5.列表切片
①什么是切片------例如:一个西瓜可以切成很多“块”----“块“指的就是“数据块”
②list切片就是通过index将一个完整的字符串或者list进行划分不同的值!
stus = [‘孙悟空’,‘猪八戒’,‘沙和尚’,‘唐僧’,‘蜘蛛精’,‘白骨精’]
stus = ['孙悟空','猪八戒','沙和尚','唐僧','蜘蛛精','白骨精']
print('切片以后的值为:',stus[1]) //并不是切片
print('切片以后的值为:',stus[1:1]) //内存空间,切片必须保存数据的完整性
print('切片以后的值为:',stus[1:2])
print('切片以后的值为:',stus[1:3])
print('切片以后的值为:',stus[1:6])
print('切片以后的值为:',stus[1:8]) //在数据切片操作过程当中,如果切片的次数大于 list里面的数据,程序不会报错,因为有内存无限大
print('切片以后的值为:',stus[-1:8])
※在list切片操作过程里面,[1:1]会将数据进行破坏,违背数据的:原理性、离子性
③通过切片获取元素时,会包括起始位置的元素,不会包括结束位置的元素
④做切片操作时,总会返回一个新的列表,不会影响原来的列表
⑤起始和结束位置的索引都可以省略不写,如果省略结束位置,则会一直截取到最后;如果省略起始位置,则会从第一个元素开始截取;如果起始位置和结束位置全部省略,则相当于创建了一个列表的副本。
print('省略切片结束以后的值为:',stus[1:])
print('省略切片结束以后的值为:',stus[:5])
print('省略切片结束以后的值为:',stus[:6])
print('省略切片结束以后的值为:',stus[:7])
print('起始位置和结束位置全部省略的值为:',stus[:]) //此操作在工作里面尽量不要出现
表示的是一个内存呢,如果没有起始位置和结束位置的定义,这个内存默认就是无穷大,这样会导致大量内存空间限制,最后会导致程序、数据的空闲例程。
※总结列表的核心特性:只包含开始索引位置,不包含结束索引位置
⑥list列表里面传三个参数,例如:my_list = [1:1:1]
①语法:列表[起始:结束:步长]
② 步长表示,每次获取元素的间隔,默认值是1
③ 步长不能是0,但是可以是负数
stus = ['孙悟空','猪八戒','沙和尚','唐僧','蜘蛛精','白骨精']
print('步长操作1:',stus[1:2:1]) //表示步长为1
print('步长操作1:',stus[1:3:1]) //表示步长为2
print('步长操作1:',stus[1:4:1]) //表示步长为1
print('步长操作1:',stus[1:4:-1]) //表示步长为1 ,步长的负数不建议使用
※1.步长表示的是一个间隔,用于间隔数据,如果步长为负,对于数据来讲,读写数据的操作很慢,因为不确定数据大小,即没有最大值和最小值!数据不好维护;并且会产生数据的垃圾碎片—最终导致数据的脏读----脏数据!例如:1 2 3 4 5 6 7 8 9 10
※2.列表的 +、 *
list的拼接原理
①数据其实是从左边的数据列表(主列表)到右边的数据列表(子列表)。
②列表拼接之后就是一个完整的list,将值默认存放到堆内存里面。
③列表遵循数据的先进后出,后进先出原理。
④判断列表里的元素是否存在
my_list6 = ['赵雅芝','陈龙','李连杰','赵本山']+['郭祎凡']
print('list拼接之后的值:',type(my_list6))
print('list拼接之后的值:',my_list6)
在list里面通过 *(其实就是在进行数据复制操作),但是在内存里面相同的数据不可能替换或者覆盖,程序还在工作当中,不建议使用!----数据的批处理Bath
my_list7 = ['赵雅芝','陈龙','李连杰','赵本山']*2
print('list*之后的值:',type(my_list7))
print('list*之后的值:',my_list7)
stus = ['孙悟空','猪八戒','沙和尚','唐僧','蜘蛛精','白骨精']
print('猪八戒' in stus) //in在列表里面表示判断列元素的存在性,如果存在返回true,不存在返回false
print('猪八' in stus)
print('猪八戒' not in stus)
print('猪八' not in stus)
①in和not in-----经擦很难过使用,就是对数据的筛选操作,只要以后提到数据的筛选操作几乎都是安全的,建议使用
②in和not in和数据库的in和not in一样!
③where和having的区别?
i:浅谈where;表示一个条件判断,会在数据操作过程里面降低数据库的性能问题!
II:浅谈having;表示的是数据的‘筛选’操作!和Python的列表操作很相似,建议使用having!
stus1 = ['孙悟空','猪八戒','沙和尚','唐僧','蜘蛛精','白骨精']
print(‘max最大值’:,max(stus1))
print(‘min最小值’:,min(stus1))
print(‘max和min最大/小值’:,max(stus1),min(stus1))
//字符串在函数max、min,、sum、avg等具有计算函数的操作里面,不能继续函数功能的实现,不能参与运算,所以字符串是不可以
被随意更改,并且字符串有len长度。
stus3 = [12,1212,444,23,33]
print(‘max和min最大/小值’:,max(stus3),min(stus3))
总结:最大的幕后黑手boss就是Python解释器,自动判断是什么type类型
print(stus3.index(12))
index表示通过具体的值获取到list的下标位置!
说明:传统的大数据可以利用execl表格,现在不行,现在利用互联网技术hadoop、spark、hive、Hbase
print(stus3.index(1)) //没有找到list里面的元素抛异常:ValueError:1 is not in list
stu5 = [12,1212,444,23,33,12,12,12]
count函数的讲解
①count表示统计,并非计算函数!
②统计的原理? 数据出现的‘次数’,不是‘多少条数据
③java里面
print(‘count统计list里面元素的个数是:’,stus5.count(12))
select count(*) from emp; //假设DB有100 data DB有100000 data
传统的网站:访问量利用count;现在京东、阿里 -----插件开发:计数器
6.list列表元素的操作
1.修改元素
stus5 = ['孙悟空','猪八戒','沙和尚','唐僧','蜘蛛精','白骨精']
print(‘修改之前的列表元素值为:’,stus5)//通过index下标修改元素的值
stus5[0] = ‘sunwukong’
print('修改完之后的list元素值为:',stus5)
※重点强调:
1.通过index索引修改的数据只是在控制台给客户打印输出,不能将原始数据库数据进行修改!
2.通过index修改元素并不影响原属数据的性能、数据完整性、也不会造成数据的脏读、脏写操作!
3.企业开发获取参数的值、获取数据库表字段建议使用index!操作安全、方便、快捷!
总结:(重点)在数据库操作数据的时候,什么时候可以利用索引?什么时候不可以利用索引操作数据?
如果一行数据经常被修改、访问、更新操作,不能使用索引操作此数据
后果:①内存溢出②会造成数据的缺失—数据的完整性③给内存里面造成负载均衡
tomcat+ngix集群+hadoop(分析大数据)+slor(全文检索)+redis(缓存数据库)—非“关系”型数据库
2.删除元素
stus6 = ['孙悟空','猪八戒','沙和尚','唐僧','蜘蛛精','白骨精']
print(‘通过del删除list列表的元素之前值为:’,stus6)
del stus6[2]
print(‘通过del删除之后:’,stus6)
通过index的下标删除数据,注意:利用del删除元素,只会删除元素内存里面的内容,并不会将数据内存的地址彻底删除
3.添加新元素
stus7 = ['孙悟空','猪八戒','沙和尚','唐僧','蜘蛛精','白骨精']
print(‘通过append给列表添加新元素--添加之前:’,stus7)
stus7.append('杨紫')
print('通过append给列表添加新元素--添加之后:',stus7)
4.insert
stus8 = ['孙悟空','猪八戒','沙和尚','唐僧','蜘蛛精','白骨精']
stus8.insert(3,‘范爷’)
print(‘insert的之后的值:’stus8)
5.extend
stus9 = ['孙悟空','猪八戒','沙和尚','唐僧','蜘蛛精','白骨精']
stus9.extend(['唐僧','白骨精']) //将list列表以菜蔬的身份传递给extend
print(stus9)
stus9 = stus9+(['唐僧','白骨精']) //拼接
print(stus9)
1.extend这个是动态参数的形式去获取列表元素------冬天太直接操作数据
2.拼接列表是通过 + 表示的是静态操作 ------静态不操作数据
6.clear
stus10 = ['孙悟空','猪八戒','沙和尚','唐僧','蜘蛛精','白骨精']
stus10.clear()
print(‘通过clear方法清除元素之后的结果:’,stus10)
7.pop
stus11 = ['孙悟空','猪八戒','沙和尚','唐僧','蜘蛛精','白骨精']
result = stus11.pop(2)
print(‘通过pop删除之后的元素:’,stus11)
pop原理(类似于:主库----保持数据的同步就ok-----从库)
8.reverse
stus12 = ['孙悟空','猪八戒','沙和尚','唐僧','蜘蛛精','白骨精']
stus12.reverse()
print('通过reverse反转之后的值:',stus12)
9.sort
用来对列表中的元素进行排序,默认是升序排列
如果需要降序排列,则需要传递一个reverse=True作为参数
stus13 = [10,1,20,3,4,5,0,-2]
stus13.sort(reverse=True) //reverse=True 和sort()结合使用排序
stus13.sort()
print(“修改后”,stus13)
列表list:其实就是一个存放数据的集合 ------数据肯定需要循环遍历结果----输出给客户端
※遍历数据的结果集有那几种方法?
1.for循环 ----加强for循环 for(参数1:参数2)
main方法:public static void 卖弄(String args[]){}
2.迭代器
3.for—each
备注:list里面的元素利用[ ]定义 ------便利结果也可以利用…(表示无穷大);python里面利用:后面根可执行的代码体
stus14 = ['孙悟空','猪八戒','沙和尚','唐僧','蜘蛛精','白骨精']
print(‘遍历stus14结果集’,stus14[0]
print(‘遍历stus14结果集’,stus14[2])
print(‘遍历stus14结果集’,stus14[3])
print(‘遍历stus14结果集’,stus14[4])
//以上遍历结果集等价于java的get、set、new 对象。----效率不高,企业不会利用这种方式
python语言通过:写代码的执行部分, :和java的{ }等价
while(变量名称,变量类型)
j = 0
while j < len(stus13):
print(stus13[j])
j = j + 1
for k in stus13:
print(k)
通过以上操作发现,python语言叫胶水语言
二、面试知识点
1.什么是线程安全和线程不安全
①线程安全:指的是多个线程在操作过程当中,一个线程在执行的时候,另一个线程不能执行,采用了加锁机制,来保证数据的安全性,直到线程1结束释放CPU资源,线程2才可以执行。
②线程不安全:指的是多个线程在执行的过程当中,大家都在抢夺CPU资源,最后导致服务器崩溃,数据泄露,线程死锁
2.什么是死锁?如何解决死锁?
死锁(Deadlock)的形成
打个比方,假设有P1和P2两个进程,都需要A和B两个资源,现在P1持有A等待B资源,而P2持有B等待A资源,两个都等待另一个资源而不肯释放资源,就这样无限等待中,这就形成死锁,这也是死锁的一种情况。给死锁下个定义,如果一组进程中每一个进程都在等待仅由该组进程中的其他进程才能引发的事件,那么该组进程是死锁的。
竞争不可抢占资源引起死锁
也就是我们说的第一种情况,而这都在等待对方占有的不可抢占的资源。
竞争可消耗资源引起死锁
有p1,p2,p3三个进程,p1向p2发送消息并接受p3发送的消息,p2向p3发送消息并接受p2的消息,p3向p1发送消息并接受p2的消息,如果设置是先接到消息后发送消息,则所有的消息都不能发送,这就造成死锁。
进程推进顺序不当引起死锁
有进程p1,p2,都需要资源A,B,本来可以p1运行A --> p1运行B --> p2运行A --> p2运行B,但是顺序换了,p1运行A时p2运行B,容易发生第一种死锁。互相抢占资源。
处理死锁的思路如下:
预防死锁:破坏四个必要条件中的一个或多个来预防死锁
避免死锁:在资源动态分配的过程中,用某种方式防止系统进入不安全的状态。
检测死锁:运行时产生死锁,及时发现思索,将程序解脱出来。
解除死锁:发生死锁后,撤销进程,回收资源,分配给正在阻塞状态的进程。
3.如何优化SQL?
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
select id from t where num=0
3.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
4.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num=10 or num=20
可以这样查询:
select id from t where num=10
union all
select id from t where num=20
5.in 和 not in 也要慎用,否则会导致全表扫描,如:
select id from t where num in(1,2,3)
对于连续的数值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
6.下面的查询也将导致全表扫描:
select id from t where name like '%abc%'
7.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where num/2=100
应改为:
select id from t where num=100*2
8.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:
select id from t where substring(name,1,3)='abc'--name以abc开头的id
应改为:
select id from t where name like 'abc%'
9.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
10.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引, 否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
11.不要写一些没有意义的查询,如需要生成一个空表结构:
select col1,col2 into #t from t where 1=0
这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:
create table #t(...)
12.很多时候用 exists 代替 in 是一个好的选择:
select num from a where num in(select num from b)
用下面的语句替换:
select num from a where exists(select 1 from b where num=a.num)
13.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,
如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。
14.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,
因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。
一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。
15.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。
这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
16.尽可能的使用 varchar 代替 char
因为首先变长字段存储空间小,可以节省存储空间, 其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
17.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
18.避免频繁创建和删除临时表,以减少系统表资源的消耗。
19.临时表并不是不可使用,适当地使用它们可以使某些例程更有效
例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。
20.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,
以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。
21.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。
22.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。
23.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。
24.与临时表一样,游标并不是不可使用。
对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。