P004_01_python列表和元组

列表

python里的列表(神似js里的数组)

1
2
names =['aa','bb','cc']
type(names) # list

遍历列表

1
2
3
4
5
6
7
8
9
infos = ['a','b','c','d']

for temp in infos:
print(temp)

i = 0
while i<len(infos):
print(infos[i])
i+=1

列表操作

  • append(obj) 向列表最后添加一个元素
1
2
3
a = [1,2,3]
a.append(4)
# [1,2,3,4]
  • extend 添加内容必须是一个可迭代对象
1
2
3
4
a = [1,2,3,4]
b = [100,200]
a.extend(b)
# [1,2,3,4,100,200]
  • insert(index,obj) 指定位置添加
1
2
3
b = [1,2,3,4]
b.insert(1,99)
# [1,99,2,3,4]

  • in
  • not in
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#判断列表里是否存在
# 笨方法
# 笨方法
inputName = 2
flg = 0
names = [1,2,3,4,5]
for name in names:
if name = inputName:
flg = 1
break

# 好方法
if inputName in names:
print('find')
else:
print('not find')
  • index
  • count
1
2
3
4
5
a = [1,1,2,2,3,3,4]
a.index(1,1,3) # 左闭右开[1,3)

a.count(2)
# 2

  • del 根据索引删 (也可以直接删除整个数组)
  • pop 删最后一个(也可以传递index参数删除指定位置的元素,不传递默认最后一个)
  • remove 根据值删
  • clear 清空
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
--------------------------------
# del
a = [1,2,3,4,5,6]
del a[0]
# [2,3,4,5,6]

del a
print(a) # 报错 在内存里把数组删除了
--------------------------------
a.pop()
# [2,3,4,5]

--------------------------------
# clear
b = ['a','b','c']
b.clear() # []
--------------------------------

> 删除部分(切片删除)

a = [1,2,3,4,5]
del a[0:2] # [3,4,5]

1
2


  • 按切片改如果内容是字符串就会把修改的内容迭代添加到该位置
1
2
3
4
5
a = ['aaa','bbb','ccc']
a[0:2] = 'ab'
print(a) # ['a','b','bbb','ccc']
a[0:2] = 'abcd'
print(a) # ['a','b','c','d','bbb','ccc']
  • 如果切换改的内容是数组也是迭代添加到指定位置
1
2
3
a = ['aaa','bbb','ccc']
a[0:3] = [1,2,3,'a','b']
print(a) # [1,2,3,'a','b','bbb','ccc']

排序

  • sort
  • reverse 逆序
1
2
3
4
5
6
7
8
a = [1,3,4,2]
a.reverse()
# [2,4,3,1]

a.sort() # 默认正序
# [1,2,3,4]
a.sort(reverse=True)
#[4,3,2,1]

元组

  • 元组被称为只读列表,即数据可以被查询,但不能被修改,所以,字符串的切片操作同样适用于元组。

    例:(1,2,3)(”a”,”b”,”c”)

  • 儿子不能改,孙子可能可以改###

元组和列表不同之处在于

  • 元组不能修改
  • 元组使用小括号,列表使用方括号
1
a = ('a',1,2,3)

元组的不一致性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
a = (1.0,2.0,3.0)
type(a)
#tuple

b = (1.0)
type(b)
# float
# 元组初始化的时候如果只有一个元素是不会初始化为元组的 会把括号里的值当作实际的类型处理

# 正确做法

c = (1.0,)
type(c)
# tuple

元组之修改孙子

1
2
3
4
a = ('a','b',[1,2,3],4)

a[2][0] = 'xxx'
# ('a','b',['xxx',2,3],4)

扩展内容

join

1
2
s = 'abcde'
s1 = '+'.join(s) # a+b+c+d+e

再看

1
2
li = [1,2,3,4,5,6]
''.join(li) # 123456

range

1
2
3
4
5
6
7
8
9
10
11
range() #就是一个元祖
for i in range(3,10):
print(i) #循环打印一次,3-9的数字。
for i in range(10):
print(i) #循环打印一次,0-9的数字。
for i in range(0,10,3):
print(i) #循环打印一次,0-9的数字,步长3,间接输出0-9所有的被3整除的数。
for i in range(10,0,-2):
print(i) #循环打印一次,10-1的数字,反向步长为2。
for i in range(10,-1,-2):
print(i) #循环打印一次,10-0的数字,反向步长为2。

恶心的面试题

执行结果是啥?

1
2
for i in range(0,10,-1):
print(i)

什么也不会执行。。。也不会报错。

P003_01_python基础数据类型

1. 数字int。

数字主要是用于计算用的,使用方法并不是很多,就记住一种就可以:

1
2
3
4
5
6
7
8
9
10
11
12
13
#bit_length() 当十进制用二进制表示时,最少使用的位数
v = 11
data = v.bit_length()
print(data)

'''
0000 0000 0 1
0000 0001 1 1
0000 0010 2 2
0000 0011 3 2
0000 0100 4 3
0000 0101 5 3
'''

2.布尔值bool

布尔值就两种:True,False。就是反应条件的正确与否。

  • 真 1 True。
  • 假 0 False。

与js的不同点 后四个也是False,但是在js里 只要是对象就是true

  • 0
  • ‘’
  • []
  • ()
  • {}
  • set()

int —-> str

1
2
i = 1
s = str(i)

str —> int

1
2
3
4
5
s = '123'
i = int(s)

s2 = '123a'
i2 = int(s2) #报错

int —–>bool 只要是0 —-》False 非0就是True

1
2
3
i = 3
b = bool(i)
print(b)

bool—-> int

1
2
3
#True   1
#False 0
'''

ps:大神的高端写法

1
2
3
4
while True:
pass
while 1: # 效率高
pass

str —>bool

1
2
3
4
5
6
7
8
#s = "" -----> False
#非空字符串都是True
#s = "0" -----> True
# s
# if s:
# print('你输入的为空,请重新输入')
# else:
# pass

3.字符串str

字符串的索引与切片。

索引即下标,就是字符串组成的元素从第一个开始,初始索引为0以此类推。

1
2
3
4
5
6
7
8
a = 'ABCDEFGHIJK'
print(a[0])
print(a[3])
print(a[5])
print(a[7])

#超过字符串长度咋办?
a[0:70] 'ABCDEFGHIJK'

切片就是通过索引(索引:索引:步长)截取字符串的一段,形成新的字符串(原则就是包头不包尾)。

1
2
3
4
5
6
7
a = 'ABCDEFGHIJK'
print(a[0:3]) # ABC
print(a[2:5]) # CDE
print(a[0:]) # 默认到最后 ABCDEFGHIJK
print(a[0:-1]) # -1就是最后一个 ABCDEFGHIJ
print(a[0:5:2]) #加步长 ACE
print(a[5:0:-2]) #反向加步长 FDB

索引

1
2
3
4
5
s = 'ABCDLSESRF'
s1 = s[0] # A
s2 = s[2] # C
s3 = s[-1] # F
s4 = s[-2] # R

ABCD 切片 :包头不包尾

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
s = 'ABCDLSESRF'
s5 = s[0:4] # ABCD
s6 = s[0:-1] # ABCDLSESR

s7 = s[:] # ABCDLSESRF
s8 = s[0:] #ABCDLSESRF

s9 = s[0:0] # ''空字符


s = 'ABCDLSESRF' # s[首:尾:步长]
s10 = s[0:5:2] # ACL
s11 = s[4:0:-1] # LDCB
s12 = s[3::-1] # DCBA
s13 = s[3::-2] # DB
s14 = s[-1::-1] # FRSESLDCBA
s15 = s[::-1] # FRSESLDCBA

简洁写法 都可以获取整个字符串

1
2
3
4
5
name[0:]
name[:]
name[::]

# name[]报错

字符串常用方法

也可以参考我之前写的python文章 《Python002字符串》

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#字符串的操作
s = 'alexWUsir'
s1 = s.capitalize() # 首字母大写

# 全大写,全小写
s2 = s.upper()
s21 = s.lower()

#大小写翻转
# s3 = s.swapcase()

# 每个隔开(特殊字符或者数字)的单词首字母大写
# s = 'alex*egon-wusir'
# s4 = s.title()

# s = 'fade,crazy*w4rri0r_songsong node_3'
# s4 = s.title()

#居中,空白填充
# s = 'alexWUsir'
# s5 = s.center(20,'~')

# s = 'alex\tsir'
# s6 = s.expandtabs()

# s = 'alex二哥'
# #公共方法
# l = len(s)

#以什么开头结尾 endswith
# s = 'alexWUsir'
# s7 =s.startswith('alex')
# s71 = s.startswith('e',2,5)

# find 通过元素找索引,找不到返回-1
#
# index通过元素找索引,找不到报错
# s = 'alexWUsir'
# s8 = s.find('A')
# s81 = s.index('A')

#strip rstrip lstrip
# s = 'alexWUsir%'
# s9 = s.strip('%')

# s = ' *a%lexWUsi* r%'
# s91 = s.strip(' %*')

# strip 默认删除前后空格

# username = input('请输入名字:').strip()
# if username =='春哥':
# print('恭喜春哥发财')

# s = 'alexaa wusirl'
# s10 = s.count('al')
# print(s10)

# split str ---->list
# s = ';alex;wusir;taibai'
# l = s.split('a')
# print(l)

# s = '来看待街坊邻居复合大师街坊法好的撒见客户'
# s11 = s.replace('街坊','老王',1)

# s = 'fhdsklfds'
# for i in s:
# print(i)
s = 'fdsa苍井空fdsalk'
if '苍井空' in s:
print('您的评论有敏感词...')

format的格式化输出

三种玩法

1
2
3
res='{} {} {}'.format('egon',18,'male')
res='{1} {0} {1}'.format('egon',18,'male')
res='{name} {age} {sex}'.format(sex='male',name='egon',age=18)

循环字符串

1
2
3
4
5
6
7
8
9
10
a = 'abcdefg'
for temp in a:
print(temp)


i = 0 ;
length = len(a)
while i<length:
print(a[i])
i+=1

P002_python编码问题和逻辑运算

1.知识点回顾

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#1、使用while循环输入 1 2 3 4 5 6 8 9 10
'''
count = 0
while count < 10:
count += 1 # count = count + 1
if count == 7:
print(' ')
else:
print(count)

count = 0
while count < 10:
count += 1 # count = count + 1
if count == 7:
continue
print(count)
'''
#3、输出 1-100 内的所有奇数
#方法一:
# count = 1
# while count < 101:
# print(count)
# count += 2
#方法二:
# count = 1
# while count < 101:
# if count % 2 == 1:
# print(count)
# count += 1

#5、求1-2+3-4+5 ... 99的所有数的和
# sum = 0
# count = 1
# while count < 100:
# if count % 2 == 0:
# sum = sum - count
# else:
# sum = sum + count
# count += 1
# print(sum)

#6、用户登陆(三次机会重试)
#input 心中有账号,密码 while

i = 0
while i < 3:
username = input('请输入账号:')
password = int(input('请输入密码:'))
if username == '咸鱼哥' and password == 123:
print('登录成功')
else:
print('登录失败请重新登录')
i += 1

2.格式化输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#格式化输出
# % s d
# name = input('请输入姓名')
# age = input('请输入年龄')
# height = input('请输入身高')
# msg = "我叫%s,今年%s 身高 %s" %(name,age,height)
# print(msg)

"""
name = input('请输入姓名:')
age = input('请输入年龄:')
job = input('请输入工作:')
hobbie = input('你的爱好:')

msg = '''------------ info of %s -----------
Name : %s
Age : %d
job : %s
Hobbie: %s
------------- end -----------------''' %(name,name,int(age),job,hobbie)
print(msg)
"""

name = input('请输入姓名')
age = input('请输入年龄')
height = input('请输入身高')
msg = "我叫%s,今年%s 身高 %s 学习进度为3%%s" %(name,age,height)
print(msg)

想格式化输出%就要 两个%%代表转义,否则报错

3. while else

与其它语言else 一般只与if 搭配不同,在Python 中还有个while …else 语句

while 后面的else 作用是指,当while 循环正常执行完,中间没有被break 中止的话,就会执行else后面的语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
count = 0
while count <= 5 :
count += 1
print("Loop",count)

else:
print("循环正常执行完啦")
print("-----out of while loop ------")

输出如下:

Loop 1
Loop 2
Loop 3
Loop 4
Loop 5
Loop 6
循环正常执行完啦
-----out of while loop ------

如果执行过程中被break啦,就不会执行else的语句啦

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
count = 0
while count <= 5 :
count += 1
if count == 3:break
print("Loop",count)

else:
print("循环正常执行完啦")
print("-----out of while loop ------")

输出如下:

Loop 1
Loop 2
-----out of while loop ------

4.初始编码

  • 最早的’密码本’ ascii 涵盖了英文字母大小写,特殊字符,数字。
    01010101
  • ascii 只能表示256种可能,太少,
  • 创办了万国码 unicode
    16表示一个字符不行,32位表示一个字符。
    A 01000001010000010100000101000001
    B 01000010010000100100001001000010
    我 01000010010000100100001001000010
  • Unicode 升级 utf-8 utf-16 utf-32
    8位 = 1字节bytes

    1. utf-8 一个字符最少用8位去表示,英文用8位 一个字节
      欧洲文字用16位去表示 两个字节
      中文用24 位去表示 三个字节
    2. utf-16 一个字符最少用16位去表示
  • gbk 中国人自己发明的,一个中文用两个字节 16位去表示。

5. 逻辑运算

  • and (JS里的 &&)
  • or (JS里的 ||)
  • not (JS里的 !)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    #and or not
    #优先级,()> not > and > or
    # print(2 > 1 and 1 < 4)
    # print(2 > 1 and 1 < 4 or 2 < 3 and 9 > 6 or 2 < 4 and 3 < 2)
    # T or T or F
    #T or F
    # print(3>4 or 4<3 and 1==1) # F
    # print(1 < 2 and 3 < 4 or 1>2) # T
    # print(2 > 1 and 3 < 4 or 4 > 5 and 2 < 1) # T
    # print(1 > 2 and 3 < 4 or 4 > 5 and 2 > 1 or 9 < 8) # F
    # print(1 > 1 and 3 < 4 or 4 > 5 and 2 > 1 and 9 > 8 or 7 < 6) # F
    # print(not 2 > 1 and 3 < 4 or 4 > 5 and 2 > 1 and 9 > 8 or 7 < 6) # F

    #ps int ----> bool 非零转换成bool True 0 转换成bool 是False
    # print(bool(2))
    # print(bool(-2))
    # print(bool(0))

    # #bool --->int
    # print(int(True)) # 1
    # print(int(False)) # 0


    '''x or y x True,则返回x'''
    # print(1 or 2) # 1
    # print(3 or 2) # 3
    # print(0 or 2) # 2
    # print(0 or 100) # 100


    # print(2 or 100 or 3 or 4) # 2

    # print(0 or 4 and 3 or 2)
    '''x and y x True,则返回y'''
    # print(1 and 2)
    # print(0 and 2)
    print(2 or 1 < 3)
    print(3 > 1 or 2 and 2)

P001_python基础

前言:自我学习总结python全栈的知识点,版本为3.4

题外话:最近《我不是药神》很火.我也客串的说《我不是大神》全栈知识点我将参考《路飞学院7天入门》赠送的 全栈9期视频。枯燥的部分我会尽量结合一些段子或者其他语言如js知识来加深理解!

1.计算机基础

我觉得这个只要你会开机关机就差不多了,如果不方便理解给你举个例子:

  1. 计算机主要就是二进制,二进制就是0/1 逢二进一
    (实在不好理解你就想现实中的电线插头 左零右火)
  2. 计算机通过电信号来判断是0还是1 比如电压低于50%就代表0 高于50%代表 1
  3. 于是这些 01组成的东西就被机器所认识也叫 机器语言
    但是这很反人类啊!多么复杂的大脑才能识别这个啊!
    于是出现了汇编,还是不够好,于是 C / C++ /JAVA等高级语言横空出世
  4. 8位 0、1组成的序列代表1字节
    • 1B(byte) = 8位(bit)
    • 1KB = 1024B
    • 1MB = 1024KB
    • 1GB = 1024MB
    • 1T = 1024GB

买手机可千万注意别被那些卖家忽悠了,老说啥机身内存大运行速度快啥的!大错特错 如果你买手机建议运行内存买高点

  • 电脑和手机这些设备分为 内存(RAM随机存储) 和 外存(ROM只读存储)
  • 内存就是 01这堆组成的电信号 没电了只要你编辑的word文档没保存就丢了
  • 外存就是 电脑上存的小说啊 mp3 短视频等 只要你不手动删除怎么开关机都在

如下是一些进制转换:

口诀:逢二进一 逢八进一 逢十进一 逢十六进一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
如:
二进制 十进制 八进制 十六进制
0000 0000 0 0 0
0000 0001 1 1 1
0000 0010 2 2 2
0000 0011 3 3 3
0000 0100 4 4 4
0000 0101 5 5 5
0000 0110 6 6 6
0000 0111 7 7 7
0000 1000 8 10 8
0000 1001 9 11 9
0000 1010 10 12 a
0000 1011 11 13 b
0000 1100 12 14 c
0000 1101 13 15 d
0000 1110 14 16 e
0000 1111 15 17 f

2.python历史

python的创始人为吉多·范罗苏姆(Guido van Rossum)

我们习惯叫他 龟叔(他俩个月写出了python)
js之父(Brendan Eich)也比较厉害10天创造了 javascript

宏观上:python2 与 python3 区别:

  • python2 源码不标准.混乱.重复代码太多.
  • python3 统一 标准.去除重复代码。

3.python的环境。

编译型:一次性将所有程序编译成二进制文件。

  • 缺点:开发效率低.不能跨平台。
  • 优点:运行速度快。C/C++等等。

解释型:当程序执行时.一行一行的解释。

  • 优点:开发效率高.可以跨平台。
  • 缺点:运行速度慢。python,js,php,等等。

4.python的发展。

传言未来十年是python的。个人觉得最主要的一个原因是纳入小学课本了。。。

听我一小段子:中国近5000年的重男轻女思想,让10年的房地产改变了,10年都难修改的教学课本都纳入python了。你说是不是该学习一下。最最主要的观点请参考阮一峰老师的 《未来世界幸存者》里的断言。机器学习的电脑真的可以打败围棋高手的事从不可能变成了可能。

5.python种类。

  • CPython
  • IPython
  • PyPy
  • Jython
  • IronPython

Python的解释器很多,但使用最广泛的还是CPython。如果要和Java或.Net平台交互,最好的办法不是用Jython或IronPython,而是通过网络调用来交互,确保各程序之间的独立性。

运行第一个py文件:

  • python3x :python 文件路径 回车
  • python2x :python2 文件路径 回车

    python2 python3 区别:

  • python2默认编码方式是ascii码
    解决方式:在文件的首行:#-- encoding:utf-8 --

  • python3 默认编码方式utf-8

理解为什么首行加入如下内容

1
#!/usr/bin/env python
  1. 在linux里代表查找系统环境变量的 python命令路径
  2. 但是linux里默认的是2.x版本 而你自己安装的3.x版本python在 usr/local/bin
    1
    2
    如果你这样写调用的默认安装的python
    #!/usr/bin/python

6.变量。

变量:就是将一些运算的中间结果暂存到内存中.以便后续代码调用。

变量名规则:

  1. 必须由数字.字母.下划线任意组合.且不能数字开头。
  2. 不能是python中的关键字。

    1
    2
    3
    4
    5
    ['and', 'as', 'assert', 'break', 'class', 'continue',
    'def', 'del', 'elif', 'else', 'except', 'exec',
    'finally', 'for', 'from', 'global', 'if', 'import',
    'in', 'is', 'lambda', 'not', 'or', 'pass', 'print',
    'raise', 'return', 'try', 'while', 'with', 'yield']
  3. 变量具有可描述性。

  4. 不能是中文。(python3变量名可以是中文)

但是毕竟编程语言不是中国制造,所以请务必尊重一下别人,而且你写中文会被别人笑话的!!!

7.常量。

1
2
3
4
5
一直不变的量。     π
BIR_OF_CHINA = 1949
```

> 在Python中没有一个专门的语法代表常量,程序员约定俗成用变量名全部大写代表常量

//JS的常量
const a = 1 //修改就报错哦!

1
2
     
### 8.注释。

方便自己方便他人理解代码。
单行注释:#
多行注释:’’’被注释内容’’’ “””被注释内容”””

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
### 9.用户交互。input

1. 等待输入.
2. 将你输入的内容赋值给了前面变量。
3. input出来的数据类型全部是str

### 10.基础数据类型初始。

#### 数字:int 12,3,45
+ - * / **
% 取余数
ps:type()
字符串转化成数字:int(str) 条件:str必须是数字组成的。
数字转化成字符串:str(int)

> 注意,自从Python2.2起,如果整数发生溢出,Python会自动将整数数据转换为长整数,所以如今在长整数数据后面不加字母L也不会导致严重后果了。

> #### 注意:在Python3里不再有long类型了,全都是int
#### 字符串:

> str.python当中凡是用引号引起来的都是字符串。
可相加:字符串的拼接。
可相乘:str * int

name = ‘abc’
print(name*3) # abcabcabc

1
2
3
4
5
6
7

#### bool:布尔值。
- True
- False


#### 11.if 分支语句

if 条件:
结果

1
2
 
### 12.while。

while 条件:
循环体
无限循环。
终止循环:1.改变条件.使其不成立。
2,break

continue

死循环

while True:
print(1)
`

MySQL007python连接数据库

python连接mysql

注意我是python3版本 所以数据库,如果你实在不知道咋配置就参考这个(问题检索是你该具备的能力)

如果安装好了 python3,可以用pip下载mysql工具包

1
2
pip install PyMySQL
# 有可能会提示你pip版本低,于是你按照命令升级,然后不小心ctrl c了,那就直接去python官网重新下载一个覆盖安装即可

windows下python连接数据库

待更新(我想更新个mac版)

Connection对象

  • 用于建立与数据库的连接
  • 创建对象:调用connect()方法

conn=connect(参数列表)

  • 参数host:连接的mysql主机,如果本机是’localhost’
  • 参数port:连接的mysql主机的端口,默认是3306
  • 参数db:数据库的名称
  • 参数user:连接的用户名
  • 参数password:连接的密码
  • 参数charset:通信采用的编码方式,默认是’gb2312’,要求与数据库创建时指定的编码一致,否则中文会乱码
对象的方法
  • close()关闭连接
  • commit()事务,所以需要提交才会生效
  • rollback()事务,放弃之前的操作
  • cursor()返回Cursor对象,用于执行sql语句并获得结果

Cursor对象

  • 执行sql语句
  • 创建对象:调用Connection对象的cursor()方法
1
cursor1=conn.cursor()

对象的方法

  • close()关闭
  • execute(operation [, parameters ])执行语句,返回受影响的行数
  • fetchone()执行查询语句时,获取查询结果集的第一个行数据,返回一个元组
  • next()执行查询语句时,获取当前行的下一行
  • fetchall()执行查询时,获取结果集的所有行,一行构成一个元组,再将这些元组装入一个元组返回
  • scroll(value[,mode])将行指针移动到某个位置
    1. mode表示移动的方式
    2. mode的默认值为relative,表示基于当前行移动到value,value为正则向下移动,value为负则向上移动
    3. mode的值为absolute,表示基于第一条数据的位置,第一条数据的位置为0
    

对象的属性

  • rowcount只读属性,表示最近一次execute()执行后受影响的行数
  • connection获得当前连接对象

CRUD

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import pymysql

try:
# 连接数据库
db = pymysql.connect(host="localhost",user="root",password="123456",db="test170910",port=3306,charset="utf8")
#创建游标对象
cursor = db.cursor()
# sql语句
sql = 'insert into students(name,gender,birthday) values("郭大侠",1,"2018-01-11")';
#执行SQL语句
cursor.execute(sql)
#提交
db.commit()
except Exception as e:
db.rollback()
print(e)
finally:
db.close()

更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import pymysql

try:
# 连接数据库
db = pymysql.connect(host="localhost",user="root",password="123456",db="test170910",port=3306,charset="utf8")
cursor = db.cursor() #创建游标对象
# sql语句
sql = 'update students set name="郭一一" where id >3';
#执行SQL语句
cursor.execute(sql)
#提交
db.commit()
print('ok')
except Exception as e:
db.rollback()
print(e)
finally:
db.close()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import pymysql

try:
# 连接数据库
db = pymysql.connect(host="localhost",user="root",password="123456",db="test170910",port=3306,charset="utf8")
cursor = db.cursor() #创建游标对象
# sql语句
sql = 'delete from students where id =3';
#执行SQL语句
cursor.execute(sql)
#提交
db.commit()
print('ok')
except Exception as e:
db.rollback()
print(e)
finally:
db.close()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import pymysql

try:
# 连接数据库
db = pymysql.connect(host="localhost",user="root",password="123456",db="test170910",port=3306,charset="utf8")
cursor = db.cursor() #创建游标对象
# sql语句
sql = 'select * from students';
#执行SQL语句
cursor.execute(sql)
#获取返回数据
print('--------------------')
data = cursor.fetchone()
print(data)
print('--------------------')
except Exception as e:
db.rollback()
print(e)
finally:
db.close()

其他语句

  • cursor对象的execute()方法,也可以用于执行create table等语句
  • 建议在开发之初,就创建好数据库表结构,不要在这里执行

参数化

保证数据库的安全性,解决sql注入

1
2
3
4
5
6
7
8
select * from students where name='a'

如果 'a' ===> 'a' or 1 = 1 就会导致全部被查出来 1=1为true

参数化
1. sql语句作为第一个参数
2. @name的值作为第二个参数(进行一系列的判断,来有效阻止sql注入)
select * from students where name=@name

实际使用

1
2
3
4
5
6
sname = '对应的一个值'
# 参数是一个列表的形式
params =[sname]
# 这里的%s不是 print()里的格式化输出 对应 params里的值
sql = 'insert into students(name) values(%s)'
count = cursor.execute(sql,params)

查询

查一条记录

1
2
3
cur.execute('select * from students where id=7')
result=cur.fetchone()
print(result)

查询多行数据

1
2
3
cur.execute('select * from students')
result=cur.fetchall()
print(result)

封装

1
 

MySQL006事务和索引

事务

保证一个业务逻辑的完整操作

事务可以完成回退的功能,保证业务逻辑的正确性

事务的四大特性

  • 原子性
  • 一致性(几个并行的事务,执行结果必须与按某一顺序串行执行的结果一致)
  • 隔离性(A向C转账,B向C转账,C不会因为AB的转账不知道现在有多少钱)
  • 持久性

使用事务的条件

  • 数据库引擎必须是innodb或bdb

使用事务的情况

  • insert
  • update
  • delete

事务的三个命令

  • begin
  • commit
  • rollback
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
数据库里有一条数据,进行更新操作
1 郭靖

step000 开启事务
begin;

step001_1 此句话会把 1 郭靖这条数据锁起来
step001_2 在临时的一个表里(内存级的临时表) 将数据改成 1 效果
update students set name='小郭' where id=1;


此时你有两种操作 一个是commit一个是rollback

commit操作
step002_0 如果你此时执行一个commit操作
step002_1 将临时表的操作更新到实际的表
step002_2 取消原表的锁定状态

rollback操作
step002_0 会将begin之后所有操作丢弃
step002_1 取消原表的锁定状态

索引

如何在英语字典里找 book单词? 查找b开头所在页码

  • 当数据库数据量很大的时候,查找数据就会变得很慢
  • 索引能提高数据访问性能
  • 主键和唯一索引,都是索引,可以提高查询速度
  • 索引的建立会占据一定的空间(物理开销)

默认所以以主键来存的,而且所以要占据一定的空间(物理开销),你可以建立索引,但是建立多了就会占据更多的空间

选择列的数据类型

  • 越小的数据类型越好
  • 简单的数据类型更好
  • 避免用null值

操作

  • 索引分为单列索引和组合索引

查看索引

1
show index from students;

建立索引

1
2
3
4
5
create index 索引名 on 表名(字段名(长度,如果是数组就不用指定))


多个字段索引
create index 索引名 on 表名(name,gender);

删除索引

1
drop index [索引名] on 表名

索引的缺点

  • 虽然提升了查询速度,同时降低了更新表的速度,如对表进行insert,update,delete(因为更新表的时候数据库不仅仅保存数据,还要保存索引信息)
  • 建立索引会占用磁盘空间的索引文件

MySQL005关系

关联

查询男生的姓名,总分

为啥不以姓名分组,因为有同名的情况

1
2
3
4
5
select name,sum(score)
from students
inner join scores on students.id=scores.stuid
where gender=1
group by students.id;

查询科目的名称,平均分

1
2
3
4
select subjects.title,avg(scores.score)
from scores
inner join subjects on scores.subid=subjects.id
group by subjects.title;

查询未删除科目的名称,最高分、平均分

1
2
3
4
5
select subjects.title,avg(scores.score),max(scores.score)
from scores
inner join subjects on scores.subid=subjects.id
where subjects.isdelete=0
group by subjects.title;

自关联

省市区

id id id
name name name
- pid省的引用 pid市的引用

我们知道中国36个省,但是这样就创建了一个表显然很浪费

我们假设

  • 省 36
  • 市 1万
  • 区 10万

没有必要建立三张表去存这些数据,如果我们能建立一张表把这些数据存起来

每建一张表对数据库的开销是很大的

  1. 我们能不能给省加一个pid
  2. 给省的pid为null
  3. 合成了一个表外键还是需要的引谁呢? 市引用省,区引用市
id name pid
1 河南省 null
2 郑州市 1

自引用,自关联

  • 不用增加新表的开销
1
2
3
4
5
6
create table areas(
aid int primary key auto_increment not null,
name varchar(20),
pid int,
foreign key(pid) references areas(id)
);

自关联查询山西省的市

1
2
3
4
5
6
select sheng.aid as sid,sheng.name as sname,
shi.aid as shiid,shi.name as shiname
from areas as sheng
inner join areas as shi on sheng.aid=shi.aid
where sheng.pid is null and sheng.name='山西省'
;

MySQL004关系

关系

  • 实体与实体之间有3种对应关系,这些关系也需要存储下来
  • 在开发中需要对存储的数据进行一些处理,用到内置的一些函数
  • 视图用于完成查询语句的封装
  • 事务可以保证复杂的增删改操作有

请看如下情况

学生表 成绩表 科目表
id id id
name score title
- 学生的引用 -
- 科目的引用 -

学生列的数据不是在scores表里建立的,而应该从学生表引用过来,关系也是一条数据;根据范式,应该存储学生的唯一编号(id),而不是学生的姓名或其他信息,同理科目表也是关系列

创建表如下

1
2
3
4
5
6
create table scores (
id int primary key auto_increment,
stuid int,
subid int,
score decimal(5,2)
);

外键约束

班级表 学生表
id id
name name
- 班级的引用

假如有班级表只有三个班

1
2
3
学生添加的时候如果添加班级4如何去验证班级是否存在?

此时就会有外键约束
  • 必须是班级表中存在的数据,可以通过外键约束进行数据的有效性验证
  • 为classid添加外键约束

为刚刚的分数表添加外键约束

此时插入或修改数据时,如果stuid的值在students表里不存在就会报错

1
2
3
4
5
6
7
8
create table scores (
id int primary key auto_increment,
stuid int,
subid int,
score decimal(5,2),
foreign key(stuid) references students(id),
foreign key(subid) references subjects(id),
);

已经建表了再进行添加约束

1
2
3
4
alter table scores add constraint stu_score foreign key(stuid) references students(id);


stu_score 代表约束名字(语法要求)

外键的级联操作

  • 在删除students表的数据时,如果这个id值在scores中已经存在,则会抛异常
  • 推荐使用逻辑删除,还可以解决这个问题
  • 可以创建表时指定级联操作,也可以在创建表后再修改外键的级联操作

语法

1
alter table scores add constraint stu_sco foreign key(stuid) references students(id) on delete cascade;

级联操作的类型包括:

  • restrict(限制):默认值,抛异常
  • cascade(级联):如果主表的记录删掉,则从表中相关联的记录都将被删除
  • set null:将外键设置为空
  • no action:什么都不做

连接查询

分数表查询后是如下结果

1
select * from scores;
id score stuid subid
0 100 1 1
1 99 1 2
2 78 2 1
3 60 2 2
4 30 3 1
5 78 3 2

但是这样根本看不出谁是谁啊

1
2
3
4
5
select students.name,subjects.title,scores.score    
from scores
inner join students on scores.stuid=students.id
inner join subjects on scores.subid=subjects.id
;
  • inner join 后的表先写谁后写谁没关系
  • 但是inner join subjects on之后的 scores.subid必须和subjects有关系

连接查询的分类

  • 内连接

连接表的数据都能对应才会出现(都匹配才出现,即如有学生黄药师但是他没有成绩,就不会查出来)

1
2
3
4
select * 
from scores
inner join students on students.id=scores.stuid
;
id score stuid subid name gender birthday isDelete
0 100 1 1 黄蓉 0 1990-02-11 00:00:00 0
1 99 1 2 黄蓉 0 1990-02-11 00:00:00 0
2 100 2 1 郭靖 1 1990-02-11 00:00:00 0
3 99 2 2 郭靖 1 1990-02-11 00:00:00 0
4 78 3 1 杨过 1 1990-02-11 00:00:00 0
5 78 3 2 杨过 1 1990-02-11 00:00:00 0
6 78 4 1 小龙女 0 1990-02-11 00:00:00 0
7 78 4 2 小龙女 0 1990-02-11 00:00:00 0
  • 左连接代表以 from后的 表名为准的数据全查出来 连接的表数据没有就用null填充
1
2
3
4
select * 
from students
left join scores on students.id=scores.stuid
;
id name gender birthday isDelete id1 score stuid subid
1 黄蓉 0 1990-02-11 00:00:00 0 0 100 1 1
1 黄蓉 0 1990-02-11 00:00:00 0 1 99 1 2
2 郭靖 1 1990-02-11 00:00:00 0 2 100 2 1
2 郭靖 1 1990-02-11 00:00:00 0 3 99 2 2
3 杨过 1 1990-02-11 00:00:00 0 4 78 3 1
3 杨过 1 1990-02-11 00:00:00 0 5 78 3 2
4 小龙女 0 1990-02-11 00:00:00 0 6 78 4 1
4 小龙女 0 1990-02-11 00:00:00 0 7 78 4 2
5 黄药师 1 1990-02-11 00:00:00 0 null null null null null
6 郭襄 0 1990-02-11 00:00:00 0 null null null null null
  • 右连接 跟左连接类似
1
2
3
4
select * 
from scores
left join students on students.id=scores.stuid
;
id1 score stuid subid id name gender birthday isDelete
0 100 1 1 1 黄蓉 0 1990-02-11 00:00:00 0
1 99 1 2 1 黄蓉 0 1990-02-11 00:00:00 0
2 100 2 1 2 郭靖 1 1990-02-11 00:00:00 0
3 99 2 2 2 郭靖 1 1990-02-11 00:00:00 0
4 78 3 1 3 杨过 1 1990-02-11 00:00:00 0
5 78 3 2 3 杨过 1 1990-02-11 00:00:00 0
6 78 4 1 4 小龙女 0 1990-02-11 00:00:00 0
7 78 4 2 4 小龙女 0 1990-02-11 00:00:00 0
null null null null 5 黄药师 1 1990-02-11 00:00:00 0
null null null null 6 郭襄 0 1990-02-11 00:00:00 0

查询平均分

1
2
3
4
select name,ave(scores) as avg1 from scores
inner join students on scores.stuid=students.id
group by stuid
order by avg1

MySQL003查询强化

查询

占据90%的业务

1
select * from 表名 ;
  • from关键字后面写表名,表示数据来源于是这张表
  • select后面写表中的列名,如果是*表示在结果中显示表中所有列
  • 在select后面的列名部分,可以使用as为列起别名,这个别名出现在结果集中
  • 如果要查询多个列,之间使用逗号分隔

查询所有

1
2
3
4
5
6
7
8
select * from students;
##########################################################
| id | name | birthday | gender | isDelete |
##########################################################
1 郭靖 2017-01-01 00:00:00 1
2 黄蓉 2017-01-01 00:00:00 0
3 郭芙 2017-01-01 00:00:00 0
4 杨过 2017-01-01 00:00:00 1

查询 id和name列

1
2
3
4
5
6
7
select id,name from students;
##########################################################
id name
1 郭靖
2 黄蓉
3 郭芙
4 杨过

查询gender

1
2
3
4
5
6
7
select gender from students;
##########################################################
gender
1
0
0
1

想看gender有多少种(去重复)

  • distinct消除重复的行
  • 如果是多列比较的整个一行的每列进行去重复(如果你查了id肯定没法去重)
1
2
3
4
5
select distinct gender from students;
##########################################################
gender
1
0

条件

1
select * from 表名 where 条件;

where之后的内容为条件,它是对行进行筛选

比较运算符
1
2
3
4
5
select * from students where id=3;
select * from students where id>3;
select * from students where id>=3;
select * from students where id<3;
select * from students where id<=3;

查询名字为「黄蓉」和的学生

1
select * from students where name='黄蓉';

查询名字不为「黄蓉」和的学生

1
select * from students where name!='黄蓉';
逻辑运算符
  • and
  • or
  • not

学号大于3的女同学

1
select * from students where id>3 and gender=0;

编号小于4或没被删除的学生

1
select * from students where id<4 or isdelete=0;
模糊查询
  • like
  • %任意个字符
  • _一个任意字符

查询姓黄的学生

1
select * from students where name like '黄%';

查询姓名为黄且总共两个字的学生

1
select * from students where name like '黄_';

查询姓名为黄且总共三个字的学生

1
select * from students where name like '黄__';

查询姓名为黄或者叫靖的学生

1
select * from students where name like '黄%' or name like '%靖';
范围查询
  • 连续的范围
  • 不连续的范围

in表示不连续的范围

查询编号是1,3,8的学生

1
select * from students where id in(1,3,8);

between … and …表示连续的范围

查询编号是3-8的学生

1
select * from students where id between 3 and 8;

查询编号是3-8的「男」学生

1
select * from students where id between 3 and 8 and gender=1;
空判断
  • null与’’是不同的
  • 判空is null

查询没写地址的学生

1
select * from students where address is null;

查询写了地址的学生

1
select * from students where address is not null;

查询写了地址的女学生

1
select * from students where address is not null and gender=0;
优先级
  • 小括号,not,比较运算符,逻辑运算符
  • and比or先运算,如果同时出现并希望先算or,需要使用()

聚合

将现有的多行数据进行统计,统计的结果是你看不到任何原始数据了,只看到结果

  • count
  • max
  • min
  • sum
  • avg

count(*)表示计算总行数,括号中写星与列名,结果是相同的

1
2
3
4
5
查询学生总数
select count(*) from students;

查询学生总数未被删除的
select count(*) from students where isdelete=0;

max(列)表示求此列的最大值

1
2
查询女生的编号最大值
select max(id) from students where gender=0;

min(列)表示求此列的最小值

1
2
查询未删除的学生最小编号
select min(id) from students where isdelete=0;

sum(列)表示求此列的和

1
2
查询男生的编号之后
select sum(id) from students where gender=1;

avg(列)表示求此列的平均值

1
2
查询未删除女生的编号平均值
select avg(id) from students where isdelete=0 and gender=0;

1
2
3
4
查询最小编号的学生信息  ————子查询
select * from students where id =(
select min(id) from students where isdelete=0
);

分组

  • 按照字段分组,表示此字段相同的数据会被放到一个组中
  • 分组后,只能查询出相同的数据列,对于有差异的数据列无法出现在结果集中
  • 可以对分组后的数据进行统计,做聚合运算

语法:

1
select 列1,列2,聚合... from 表名 group by 列1,列2,列3...

查询男女生总数

1
2
3
select gender as 性别,count(*)
from students
group by gender;

查询各城市人数

1
2
3
select hometown as 家乡,count(*)
from students
group by hometown;

分组后筛选

语法:

1
2
3
select 列1,列2,聚合... from 表名
group by 列1,列2,列3...
having 列1,...聚合...
  • having后面的条件运算符与where的相同

查询男生总人数

1
2
3
4
5
6
7
8
9
10
方案一
select count(*)
from students
where gender=1;
-----------------------------------
方案二:
select gender as 性别,count(*)
from students
group by gender
having gender=1;

对比where与having

  • where是对from后面指定的表进行数据筛选,属于对原始数据的筛选
  • having是对group by的结果进行筛选
1
原始集合——>where——>结果集——>分组>结果集——>having——>

排序

为了方便查看数据,可以对数据进行排序

语法:

1
2
select * from 表名
order by 列1 asc|desc,列2 asc|desc,...
  • 将行数据按照列1进行排序,如果某些行列1的值相同时,则按照列2排序,以此类推
  • 默认按照列值从小到大排列
  • asc从小到大排列,即升序
  • desc从大到小排序,即降序

查询未删除男生学生信息,按学号降序

1
2
3
select * from students
where gender=1 and isdelete=0
order by id desc;

查询未删除科目信息,按名称升序

1
2
3
select * from subject
where isdelete=0
order by stitle;

分页

获取部分行

当数据量过大时,在一页中查看数据是一件非常麻烦的事情

语法

1
select * from 表名 limit start,count;

  • 从start开始,获取count条数据
  • start索引从0开始
示例:分页

已知:每页显示m条数据,当前显示第n页

求总页数:此段逻辑后面会在python中实现

  • 查询总条数p1
  • 使用p1除以m得到p2
  • 如果整除则p2为总数页
  • 如果不整除则p2+1为总页数

求第n页的数据

1
2
3
select * from students
where isdelete=0
limit (n-1)*m,m

总结

完整的select语句

1
2
3
4
5
select * from 表名
where ...
group by ... having ...
order by ...
limit start,count

执行顺序

  • from 表名
  • where 条件
  • group by 列名
  • select distinct *
  • having …
  • order by …
  • limit start,count

MySQL002CRUD

CRUD

查所有

1
select * from 表名

增加

  • 全列插入 insert into 表名 values(…);
  • 缺省插入 insert into 表名(列1,列2) values(值1,值2);
  • 同时插入多条数据 insert into 表名 values(…),(…);
    或者 insert into 表名(列1,列2) values(值1,值2),(值1,值2),(值1,值2);
1
2
3
4
5
6
7
8
9
# 全列
insert into students values(0,'八戒',1,'1990-1-1',0);
# 缺省插入
insert into students(name) values('唐僧');

#批量
insert into students values(1,'aaa',1,'1990-1-1',0),(2,'bbb',1,'1990-1-1',0),(3,'ccc',1,'1990-1-1',0);

insert into students(name) values('唐僧'),('八戒'),('悟空');
  • 主键列是自动增长,但是在全列插入的时候要占位,通常使用0,插入成功后以实际数据为准

修改

1
2
3
4
5
6
7
8
9
# 对满足条件的行修改
update 表名 set 列1=值,... where条件


# 把id=2的 生日修改了
update students set birthday='1990-1-1' where id=2;

# 不写条件就是全部改
update students set gender=0,birthday='2018-6-23' where id=6;

删除

物理删除,数据真的没了

1
delete from 表名 where 条件

逻辑删除表里设计这样一个字段 isDelete 默认为0,当值为1时代表删除了,查询的时候只取isDelete=0的