Commit 20c93157 authored by jackfrued's avatar jackfrued

更新了文档和目录结构

parent 62d43afa
This diff is collapsed.
"""
实现查找功能的模块
"""
def seq_search(items, elem):
"""顺序查找"""
for index, item in enumerate(items):
if item == elem:
return index
return -1
def bin_search(items, elem):
"""折半查找(二分查找)"""
start, end = 0, len(items) - 1
while start <= end:
mid = (start + end) // 2
if elem < items[mid]:
end = mid - 1
elif elem > items[mid]:
start = mid + 1
else:
return mid
return -1
"""
排序 - 冒泡排序(简单O(N**2)) / 归并排序(高级O(N*log2N))
冒泡排序
34, 99, 52, 11, 47, 68, 50, 84
34, 52, 11, 47, 68, 50, 84, 99
34, 11, 47, 52, 50, 68, 84
11, 34, 47, 50, 52, 68
快速排序
34, 99, 52, 11, 47, 68, 50, 84
{34, 11, 47}, {50}, {99, 52, 68, 84}
{11}, {34}, {47}, {50}, {52, 68, 84}, {99}
{11}, {34}, {47}, {50}, {52}, {68, 84}, {99}
{11}, {34}, {47}, {50}, {52}, {68}, {84}, {99}
归并排序 - 分治法(divide-and-conquer)
34, 99, 52, 11, 47, 68, 50, 84
{34, 99, 52, 11}, {47, 68, 50, 84}
{34, 99}, {52, 11}, {47, 68}, {50, 84}
{34}, {99}, {52}, {11}, {47}, {68}, {50}, {84}
{34, 99}, {11, 52}, {47, 68}, {50, 84}
{11, 34, 52, 99}, {47, 50, 68, 84}
{11, 34, 47, 50, 52, 68, 84, 99}
在使用分治法的时候通常都会使用到递归调用这种编程手段
一个函数直接或间接的调用了自身就称之为递归调用
"""
# 9 1 2 3 4 5 6 7 8
# 2 3 4 5 6 7 8 9 1
# *前面的参数称为位置参数, *后面的参数称为命名关键字参数
# 所谓命名关键字参数就是调用函数时必须以"参数名=参数值"的形式传入参数
def bubble_sort(origin_items, *, comp=lambda x, y: x > y):
"""冒泡排序"""
items = origin_items[:]
length = len(items)
for i in range(1, length):
swapped = False
for j in range(0, length - i):
if comp(items[j], items[j + 1]):
items[j], items[j + 1] = items[j + 1], items[j]
swapped = True
if swapped:
swapped = False
for j in range(length - i - 1, i - 1, -1):
if comp(items[j - 1], items[j]):
items[j - 1], items[j] = items[j], items[j - 1]
swapped = True
if not swapped:
break
return items
def merge(list1, list2, comp=lambda x, y: x <= y):
""""有序合并(将两个有序的列表合并成一个新的有序的列表)"""
list3 = []
index1, index2 = 0, 0
while index1 < len(list1) and index2 < len(list2):
if comp(list1[index1], list2[index2]):
list3.append(list1[index1])
index1 += 1
else:
list3.append(list2[index2])
index2 += 1
list3 += list1[index1:]
list3 += list2[index2:]
return list3
def merge_sort(origin_items, comp=lambda x, y: x <= y):
"""归并排序"""
if len(origin_items) <= 1:
return origin_items[:]
mid = len(origin_items) // 2
left = merge_sort(origin_items[:mid], comp)
right = merge_sort(origin_items[mid:], comp)
return merge(left, right, comp)
class Person:
"""人"""
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f'{self.name}: {self.age}'
def main():
# list1 = [12, 35, 48, 87, 92]
# list2 = [39, 44, 50, 60, 77, 88]
# list3 = merge(list1, list2)
# print(list3)
items = [34, 99, 52, 11, 47, 50, 84]
print(items)
print(merge_sort(items))
# items = ['hi', 'hello', 'orange', 'watermelon', 'zoo', 'pitaya']
# items = [
# Person("LuoHao", 38), Person("Baiyuanfang", 25),
# Person("Zhangsanfeng", 120), Person("Lee", 18)
# ]
# new_items = bubble_sort(items, comp=lambda x, y: len(x) > len(y))
# new_items = bubble_sort(items, comp=lambda x, y: x.age > y.age)
# print(items)
# print(new_items)
if __name__ == '__main__':
main()
"""
递归(recursion)
"""
def fac(num):
"""求阶乘"""
if num in (0, 1):
return 1
return num * fac(num - 1)
# 动态规划 - 把求解问题的中间结果保存起来
# 这种算法适合求解有最优子结构的问题或子问题会重复求解的问题
def fib(num, temp={}):
"""计算斐波拉切数"""
# 递归的两个要素
# 收敛条件 - 什么时候结束递归
if num in (1, 2):
return 1
# 递归公式 - 降低问题的求解难度
try:
return temp[num]
except KeyError:
temp[num] = fib(num - 1) + fib(num - 2)
return temp[num]
def fib2(total):
"""斐波拉切数列生成器"""
num1, num2 = 0, 1
for _ in range(total):
num1, num2 = num2, num1 + num2
yield num1
def main():
"""主函数"""
for num in fib2(120):
print(num)
if __name__ == '__main__':
main()
"""
程序设计的范式(理念):
1. 指令式程序设计 - 汇编语言
2. 面向过程程序设计 - 把一组指令封装成一个过程,需要执行这组指令时调用这个过程即可 - C
3. 面向对象程序设计 - 将数据和操作数据的函数从逻辑上组织成了对象 - C++ / Java
4. 函数式程序设计 - 函数是一等对象(一等公民) - Haskell
面向对象程序设计步骤:
1. 定义类 - 抽象过程 - 数据抽象(静态特征-属性)/行为抽象(动态特征-方法)
2. 创建对象 - 构造器 - 初始化(__init__)
3. 给对象发消息 - 对象引用.对象方法(参数)
面向对象的三大支柱 - 封装 / 继承 / 多态
类与类(对象与对象)之间的关系:
1. is-a: 继承
2. has-a: 关联 / 聚合 / 合成
3. use-a: 依赖
面向对象的设计原则/SOLID原则:
1. 单一职责原则 - 类的设计要高内聚
2. 开闭原则 - 接受扩展不接受修改 - 抽象是关键/用继承封装可变性
3. 依赖倒转原则 - 面向抽象编程
4. 里氏替换原则 - 任何时候都可以使用子类型对象替换父类型对象
5. 接口隔离原则
6. 合成聚合复用原则 - 优先考虑用强关联而不是继承去复用代码
7. 最少知识原则(迪米特法则) - 不要跟陌生人讲话
GoF设计模式 - 23种场景(Python中有16中已经被弱化)
- 单例、工厂、原型、适配器、观察者、策略
"""
from enum import Enum
from enum import unique
import random
# 经验: 符号常量优于字面常量
# 枚举类型是定义符号常量的最佳选择
# 如果一个变量的值只有有限多个选项那么最好使用枚举
@unique
class Suite(Enum):
"""花色"""
SPADE = 0
HEART = 1
CLUB = 2
DIAMOND = 3
class Card():
"""牌"""
def __init__(self, suite, face):
self.suite = suite
self.face = face
def show(self):
"""显示牌的花色和点数"""
suites = ['♠️', '♥️', '♣️', '♦️']
faces = [
'', 'A', '2', '3', '4', '5', '6',
'7', '8', '9', '10', 'J', 'Q', 'K'
]
return f'{suites[self.suite.value]} {faces[self.face]}'
def __str__(self):
return self.show()
def __repr__(self):
return self.show()
class Poker():
"""扑克"""
def __init__(self):
self.index = 0
self.cards = [Card(suite, face)
for suite in Suite
for face in range(1, 14)]
def shuffle(self):
"""洗牌"""
random.shuffle(self.cards)
def deal(self):
"""发牌"""
temp = self.cards[self.index]
self.index += 1
return temp
@property
def has_more(self):
"""是否有牌可以发"""
return self.index < len(self.cards)
class Player():
"""玩家"""
def __init__(self, name):
self.name = name
self.cards = []
def get_one(self, card):
"""摸一张牌"""
self.cards.append(card)
def drop_one(self, index):
"""打出一张牌"""
return self.cards.remove(index)
def get_many(self, more_cards):
"""摸多张牌"""
self.cards += more_cards
def drop_cards(self):
"""扔掉所有牌"""
self.cards.clear()
def arrange(self):
"""整理手上的牌"""
self.cards.sort(key=lambda x: (x.suite.value, x.face))
def main():
"""主函数"""
poker = Poker()
poker.shuffle()
players = [
Player("东邪"), Player("西毒"),
Player("南帝"), Player("北丐")
]
for _ in range(3):
for player in players:
if poker.has_more:
player.get_one(poker.deal())
for player in players:
player.arrange()
print(player.name)
print(player.cards)
if __name__ == '__main__':
main()
"""
设计模式 - 策略模式(指定的策略不同执行的算法不同)
"""
from hashlib import md5
from hashlib import sha1
from hashlib import sha256
from hashlib import sha512
class StreamHasher():
"""哈希摘要生成器"""
def __init__(self, algorithm='md5', size=1024):
self.size = size
alg = algorithm.lower()
if alg == 'md5':
self.hasher = md5()
elif alg == 'sha1':
self.hasher = sha1()
elif alg == 'sha256':
self.hasher = sha256()
elif alg == 'sha512':
self.hasher = sha512()
else:
raise ValueError('不支持指定的摘要算法')
# 魔法方法: 让对象可以像函数一样被调用
def __call__(self, stream):
return self.to_digest(stream)
def to_digest(self, stream):
"""生成十六进制形式的哈希摘要字符串"""
for data in iter(lambda: stream.read(self.size), b''):
self.hasher.update(data)
return self.hasher.hexdigest()
def main():
"""主函数"""
hasher = StreamHasher('sha1', 4096)
with open('Python语言规范.pdf', 'rb') as stream:
# print(hasher.to_digest(stream))
print(hasher(stream))
if __name__ == '__main__':
main()
"""
抽象类 / 继承 / 多态
"""
from abc import ABCMeta, abstractmethod
class Employee(metaclass=ABCMeta):
"""员工"""
def __init__(self, name):
self.name = name
@abstractmethod
def get_salary(self):
"""结算月薪"""
pass
class Manager(Employee):
"""部门经理"""
def get_salary(self):
return 15000
class Programmer(Employee):
"""程序员"""
def __init__(self, name):
super().__init__(name)
self._working_hour = 0
@property
def working_hour(self):
return self._working_hour
@working_hour.setter
def working_hour(self, _working_hour):
self._working_hour = 0 if _working_hour < 0 \
else _working_hour
def get_salary(self):
return 200 * self.working_hour
class Salesman(Employee):
"""销售员"""
def __init__(self, name):
super().__init__(name)
self._sales = 0
@property
def sales(self):
return self._sales
@sales.setter
def sales(self, _sales):
self._sales = 0 if _sales < 0 else _sales
def get_salary(self):
return 1800 + 0.05 * self.sales
def main():
"""主函数"""
emps = [
Programmer("王大锤"), Manager("武则天"),
Programmer("狄仁杰"), Salesman("白洁"),
Programmer("白元芳"), Salesman("冷面")
]
for emp in emps:
if isinstance(emp, Programmer):
emp.working_hour = int(input(f'{emp.name}本月工作时间: '))
elif isinstance(emp, Salesman):
emp.sales = float(input(f'{emp.name}本月销售额: '))
print("%s本月工资为: ¥%.2f元" % (emp.name, emp.get_salary()))
if __name__ == '__main__':
main()
"""
元类 - 设计模式 - 单例模式(让一个类只能创建唯一的实例)
"""
class SingletonMeta(type):
"""单例类的元类(描述其他类的类)"""
def __init__(cls, *args, **kwargs):
cls.__instance = None
def __call__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = super().__call__(*args, **kwargs)
return cls.__instance
class President(metaclass=SingletonMeta):
"""总统(单例类)"""
def __init__(self, name):
self.name = name
def main():
p1 = President("王大锤")
p2 = President("奥巴马")
print(p1.name)
print(p2.name)
print(p1 == p2)
print(p1 is p2)
if __name__ == '__main__':
main()
"""
设计模式 - 单例模式(让一个类只能创建唯一的实例)
"""
from functools import wraps
def singleton(cls):
instances = {}
@wraps(cls)
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton
class President():
"""总统(单例类)"""
def __init__(self, name):
self.name = name
def main():
p1 = President("王大锤")
p2 = President("奥巴马")
print(p1.name)
print(p2.name)
print(p1 == p2)
print(p1 is p2)
print('-' * 30)
# 取消装饰器
President2 = President.__wrapped__
p2 = President2("奥巴马")
print(p1.name)
print(p2.name)
print(p1 == p2)
print(p1 is p2)
if __name__ == '__main__':
main()
"""
装饰器 - 背后的设计模式是代理模式(注意不是装饰器模式)
代理模式通常是让代理对象去执行被代理对象的行为并在这个过程中增加额外的操作
这种设计模式最适合处理代码中的横切关注功能(与正常业务没有必然联系但是又需要执行的功能)
"""
from functools import wraps
from time import time
def record(output=print):
def decorate(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time()
result = func(*args, **kwargs)
output(func.__name__, time() - start)
return result
return wrapper
return decorate
@record()
def some_task():
print(123 ** 100000)
if __name__ == '__main__':
some_task()
print(some_task.__name__)
# 取消装饰器
some_task = some_task.__wrapped__
some_task()
"""
混入 - Mix-in
限制字典只有在指定的key不存在时才能设置键值对
原则上能够不使用多重继承的地方都不要用多重继承
MRO - Method Resolution Order - 方法解析顺序
Python2 - 深度优先搜索
Python3 - 类似于广度优先搜索 - C3算法
类.__mro__ / 类.mro()
"""
class SetOnceMappingMixin():
"""混入类"""
__slots__ = ()
def __setitem__(self, key, value):
if key in self:
raise KeyError(f'键{str(key)}已经存在')
return super().__setitem__(key, value)
class SetOnceDict(SetOnceMappingMixin, dict):
"""自定义字典"""
pass
def main():
"""主函数"""
dict1 = SetOnceDict()
try:
dict1['username'] = 'jackfrued'
dict1['username'] = 'hellokitty'
dict1['username'] = 'wangdachui'
except KeyError as error:
print('Error:', error)
print(dict1)
if __name__ == '__main__':
main()
"""
自定义迭代器
"""
class Fibo:
"""斐波拉切数列迭代器"""
def __init__(self, num):
self.num = num
self.a, self.b = 0, 1
self.idx = 0
def __iter__(self):
return self
def __next__(self):
if self.idx < self.num:
self.a, self.b = self.b, self.a + self.b
self.idx += 1
return self.a
raise StopIteration()
def main():
"""主函数"""
for val in Fibo(10):
print(val)
print('-' * 10)
fibo_iter = Fibo(10)
for _ in range(10):
print(next(fibo_iter))
if __name__ == '__main__':
main()
"""
协程 - 可以通过yield来调用其它协程,yield将执行权转让给其他协程
协程之间不是调用者与被调用者的关系,而是彼此对称平等的
"""
def num_generator(start, end):
"""指定起始值的整数生成器"""
for num in range(start, end + 1):
yield num
def square_mapper(numbers):
"""将数值映射为其平方的协程"""
for num in numbers:
yield num ** 2
def prime_filter(numbers):
"""从数值中过滤出素数的协程"""
for num in numbers:
flag = True
for factor in range(2, int(num ** 0.5 + 1)):
if num % factor == 0:
flag = False
break
if flag:
yield num
def main():
tasks = []
tasks.append(square_mapper(num_generator(1, 100)))
tasks.append(prime_filter(num_generator(2, 100)))
for _ in range(100):
for task in tasks:
print(f'切换到任务{task.__name__} => ', end='')
try:
print(task.__next__())
except StopIteration as error:
print(error)
if __name__ == '__main__':
main()
"""
魔术方法 - 哈希存储 / 上下文语法
"""
from random import randint
class Student():
"""学生"""
def __init__(self, stuid, name, gender):
self.stuid = stuid
self.name = name
self.gender = gender
def __enter__(self):
return self
def __exit__(self, exception_type, exception_value, traceback):
pass
def __hash__(self):
return hash(self.stuid)
def __eq__(self, other):
return self.stuid == other.stuid
def __repr__(self):
return f'{self.stuid}: {self.name}'
def create_student():
return Student(randint(1001, 9999),
"无名氏",
"男" if randint(0, 1) == 1 else "女")
def main():
"""主函数"""
students = {
Student(1001, "王大锤", "男"),
Student(1001, "王小锤", "男"),
Student(1003, "王捶捶", "女")
}
print(len(students))
print(students)
with create_student() as stu:
print(stu.stuid)
print(stu.name)
print(stu.gender)
if __name__ == '__main__':
main()
......@@ -1240,12 +1240,3 @@ build environment:
vdb 0.00 0.01 0.00 2088 0
```
### Shell和Shell编程
#### 环境变量
1. HOME
2. SHELL
3. HISTSIZE
4. RANDOM
5. PATH
-- 创建人力资源管理系统数据库
drop database if exists HRS;
create database HRS default charset utf8;
-- 切换数据库上下文环境
use HRS;
-- 删除表
drop table if exists TbEmp;
drop table if exists TbDept;
-- 创建部门表
create table TbDept
drop database if exists hrs;
create database hrs default charset utf8;
use hrs;
drop table if exists tb_emp;
drop table if exists tb_dept;
create table tb_dept
(
deptno tinyint primary key, -- 部门编号
dname varchar(10) not null, -- 部门名称
dloc varchar(20) not null -- 部门所在地
dno int not null comment '编号',
dname varchar(10) not null comment '名称',
dloc varchar(20) not null comment '所在地',
primary key (dno)
);
-- 添加部门记录
insert into TbDept values (10, '会计部', '北京');
insert into TbDept values (20, '研发部', '成都');
insert into TbDept values (30, '销售部', '重庆');
insert into TbDept values (40, '运维部', '深圳');
-- 创建员工表
create table TbEmp
insert into tb_dept values
(10, '会计部', '北京'),
(20, '研发部', '成都'),
(30, '销售部', '重庆'),
(40, '运维部', '深圳');
create table tb_emp
(
empno int primary key, -- 员工编号
ename varchar(20) not null, -- 员工姓名
job varchar(20) not null, -- 员工职位
mgr int, -- 主管编号
sal int not null, -- 员工月薪
comm int, -- 每月补贴
dno tinyint -- 所在部门编号
eno int not null comment '员工编号',
ename varchar(20) not null comment '员工姓名',
job varchar(20) not null comment '员工职位',
mgr int comment '主管编号',
sal int not null comment '员工月薪',
comm int comment '每月补贴',
dno int comment '所在部门编号',
primary key (eno)
);
-- 添加外键约束
alter table TbEmp add constraint fk_dno foreign key (dno) references TbDept(deptno);
-- 添加员工记录
insert into TbEmp values (7800, '张三丰', '总裁', null, 9000, 1200, 20);
insert into TbEmp values (2056, '乔峰', '分析师', 7800, 5000, 1500, 20);
insert into TbEmp values (3088, '李莫愁', '设计师', 2056, 3500, 800, 20);
insert into TbEmp values (3211, '张无忌', '程序员', 2056, 3200, null, 20);
insert into TbEmp values (3233, '丘处机', '程序员', 2056, 3400, null, 20);
insert into TbEmp values (3251, '张翠山', '程序员', 2056, 4000, null, 20);
insert into TbEmp values (5566, '宋远桥', '会计师', 7800, 4000, 1000, 10);
insert into TbEmp values (5234, '郭靖', '出纳', 5566, 2000, null, 10);
insert into TbEmp values (3344, '黄蓉', '销售主管', 7800, 3000, 800, 30);
insert into TbEmp values (1359, '胡一刀', '销售员', 3344, 1800, 200, 30);
insert into TbEmp values (4466, '苗人凤', '销售员', 3344, 2500, null, 30);
insert into TbEmp values (3244, '欧阳锋', '程序员', 3088, 3200, null, 20);
insert into TbEmp values (3577, '杨过', '会计', 5566, 2200, null, 10);
insert into TbEmp values (3588, '朱九真', '会计', 5566, 2500, null, 10);
alter table tb_emp add constraint fk_emp_dno foreign key (dno) references tb_dept (dno);
insert into tb_emp values
(7800, '张三丰', '总裁', null, 9000, 1200, 20),
(2056, '乔峰', '分析师', 7800, 5000, 1500, 20),
(3088, '李莫愁', '设计师', 2056, 3500, 800, 20),
(3211, '张无忌', '程序员', 2056, 3200, null, 20),
(3233, '丘处机', '程序员', 2056, 3400, null, 20),
(3251, '张翠山', '程序员', 2056, 4000, null, 20),
(5566, '宋远桥', '会计师', 7800, 4000, 1000, 10),
(5234, '郭靖', '出纳', 5566, 2000, null, 10),
(3344, '黄蓉', '销售主管', 7800, 3000, 800, 30),
(1359, '胡一刀', '销售员', 3344, 1800, 200, 30),
(4466, '苗人凤', '销售员', 3344, 2500, null, 30),
(3244, '欧阳锋', '程序员', 3088, 3200, null, 20),
(3577, '杨过', '会计', 5566, 2200, null, 10),
(3588, '朱九真', '会计', 5566, 2500, null, 10);
-- 查询薪资最高的员工姓名和工资
......@@ -67,22 +71,22 @@ insert into TbEmp values (3588, '朱九真', '会计', 5566, 2500, null, 10);
-- 查询薪资排名4~6名的员工姓名和工资
use HRS;
-- use hrs;
drop procedure if exists sp_avg_sal_by_dept;
-- drop procedure if exists sp_avg_sal_by_dept;
create procedure sp_avg_sal_by_dept(deptno integer, out avg_sal float)
begin
select avg(sal) into avg_sal from TbEmp where dno=deptno;
end;
-- create procedure sp_avg_sal_by_dept(dno integer, out avg_sal float)
-- begin
-- select avg(sal) into avg_sal from tb_emp where dno=dno;
-- end;
call sp_avg_sal_by_dept(10, @avgSal);
-- call sp_avg_sal_by_dept(10, @avgSal);
select @avgSal;
-- select @avgSal;
......@@ -5,11 +5,11 @@
-- 创建SRS数据库
drop database if exists SRS;
create database SRS default charset utf8 collate utf8_bin;
drop database if exists srs;
create database srs default charset utf8 collate utf8_bin;
-- 切换到SRS数据库
use SRS;
-- 切换到srs数据库
use srs;
-- 创建学院表
create table tb_college
......
drop database if exists hrs;
create database hrs default charset utf8;
use hrs;
drop table if exists tb_emp;
drop table if exists tb_dept;
create table tb_dept
(
dno int not null comment '编号',
dname varchar(10) not null comment '名称',
dloc varchar(20) not null comment '所在地',
primary key (dno)
);
insert into tb_dept values
(10, '会计部', '北京'),
(20, '研发部', '成都'),
(30, '销售部', '重庆'),
(40, '运维部', '深圳');
create table tb_emp
(
eno int not null comment '员工编号',
ename varchar(20) not null comment '员工姓名',
job varchar(20) not null comment '员工职位',
mgr int comment '主管编号',
sal int not null comment '员工月薪',
comm int comment '每月补贴',
dno int comment '所在部门编号',
primary key (eno)
);
alter table tb_emp add constraint fk_emp_dno foreign key (dno) references tb_dept (dno);
insert into tb_emp values
(7800, '张三丰', '总裁', null, 9000, 1200, 20),
(2056, '乔峰', '分析师', 7800, 5000, 1500, 20),
(3088, '李莫愁', '设计师', 2056, 3500, 800, 20),
(3211, '张无忌', '程序员', 2056, 3200, null, 20),
(3233, '丘处机', '程序员', 2056, 3400, null, 20),
(3251, '张翠山', '程序员', 2056, 4000, null, 20),
(5566, '宋远桥', '会计师', 7800, 4000, 1000, 10),
(5234, '郭靖', '出纳', 5566, 2000, null, 10),
(3344, '黄蓉', '销售主管', 7800, 3000, 800, 30),
(1359, '胡一刀', '销售员', 3344, 1800, 200, 30),
(4466, '苗人凤', '销售员', 3344, 2500, null, 30),
(3244, '欧阳锋', '程序员', 3088, 3200, null, 20),
(3577, '杨过', '会计', 5566, 2200, null, 10),
(3588, '朱九真', '会计', 5566, 2500, null, 10);
-- 查询薪资最高的员工姓名和工资
-- 查询员工的姓名和年薪((月薪+补贴)*12)
-- 查询有员工的部门的编号和人数
-- 查询所有部门的名称和人数
-- 查询薪资最高的员工(Boss除外)的姓名和工资
-- 查询薪水超过平均薪水的员工的姓名和工资
-- 查询薪水超过其所在部门平均薪水的员工的姓名、部门编号和工资
-- 查询部门中薪水最高的人姓名、工资和所在部门名称
-- 查询主管的姓名和职位
-- 查询薪资排名4~6名的员工姓名和工资
-- use hrs;
-- drop procedure if exists sp_avg_sal_by_dept;
-- create procedure sp_avg_sal_by_dept(dno integer, out avg_sal float)
-- begin
-- select avg(sal) into avg_sal from tb_emp where dno=dno;
-- end;
-- call sp_avg_sal_by_dept(10, @avgSal);
-- select @avgSal;
-- 查看MySQL服务器所有数据库
show databases;
-- 删除SRS数据库
drop database if exists SRS;
-- 创建学生选课系统(SRS)数据库并指定默认字符集
create database SRS default charset utf8;
-- 切换至SRS数据库
use SRS;
-- 查看当前数据库中所有表
show tables;
-- 创建学生表
create table TbStudent
(
stuid integer not null,
stuname varchar(20) not null,
stusex bit default 1,
stubirth datetime not null,
stutel char(11),
stuaddr varchar(255),
stuphoto longblob,
primary key (stuid)
);
-- 修改学生表删除stutel列
alter table TbStudent drop column stutel;
-- 查看学生表结构
desc TbStudent;
-- 如果表TbCourse已经存在就删除它
drop table if exists TbCourse;
-- 创建课程表
create table TbCourse
(
cosid integer not null,
cosname varchar(50) not null,
coscredit tinyint not null,
cosintro varchar(255)
);
-- 给课程表指定主键
alter table TbCourse add constraint pk_course primary key (cosid);
-- 创建学生选课记录表
create table TbSC
(
scid integer primary key auto_increment,
sid integer not null,
cid integer,
scdate datetime not null,
score float
);
-- 给表TbSC添加外键约束
alter table TbSC add constraint fk_sid foreign key (sid) references TbStudent (stuid) on delete cascade on update cascade;
alter table TbSC add constraint fk_cid foreign key (cid) references TBCourse (cosid) on delete set null on update cascade;
-- 添加学生记录
insert into TbStudent values (1001, '张三丰', default, '1978-1-1', '成都市一环路西二段17号', null);
insert into TbStudent (stuid, stuname, stubirth) values (1002, '郭靖', '1980-2-2');
insert into TbStudent (stuid, stuname, stusex, stubirth, stuaddr) values (1003, '黄蓉', 0, '1982-3-3', '成都市二环路南四段123号');
insert into TbStudent values (1004, '张无忌', 1, '1990-4-4', null, null);
insert into TbStudent values
(1005, '丘处机', 1, '1983-5-5', '北京市海淀区宝盛北里西区28号', null),
(1006, '王处一', 1, '1985-6-6', '深圳市宝安区宝安大道5010号', null),
(1007, '刘处玄', 1, '1987-7-7', '郑州市金水区纬五路21号', null),
(1008, '孙不二', 0, '1989-8-8', '武汉市光谷大道61号', null),
(1009, '平一指', 1, '1992-9-9', '西安市雁塔区高新六路52号', null),
(1010, '老不死', 1, '1993-10-10', '广州市天河区元岗路310号', null),
(1011, '王大锤', 0, '1994-11-11', null, null),
(1012, '隔壁老王', 1, '1995-12-12', null, null),
(1013, '郭啸天', 1, '1977-10-25', null, null);
-- 删除学生记录
delete from TbStudent where stuid=1004;
-- 更新学生记录
update TbStudent set stubirth='1980-12-12', stuaddr='上海市宝山区同济支路199号' where stuid=1002;
-- 添加课程记录
insert into TbCourse values
(1111, 'C语言程序设计', 3, '大神级讲师授课需要抢座'),
(2222, 'Java程序设计', 3, null),
(3333, '数据库概论', 2, null),
(4444, '操作系统原理', 4, null);
-- 添加学生选课记录
insert into TbSC values
(default, 1001, 1111, '2016-9-1', 95),
(default, 1002, 1111, '2016-9-1', 94),
(default, 1001, 2222, now(), null),
(default, 1001, 3333, '2017-3-1', 85),
(default, 1001, 4444, now(), null),
(default, 1002, 4444, now(), null),
(default, 1003, 2222, now(), null),
(default, 1003, 3333, now(), null),
(default, 1005, 2222, now(), null),
(default, 1006, 1111, now(), null),
(default, 1006, 2222, '2017-3-1', 80),
(default, 1006, 3333, now(), null),
(default, 1006, 4444, now(), null),
(default, 1007, 1111, '2016-9-1', null),
(default, 1007, 3333, now(), null),
(default, 1007, 4444, now(), null),
(default, 1008, 2222, now(), null),
(default, 1010, 1111, now(), null);
-- 查询所有学生信息
select * from TbStudent;
-- 查询所有课程名称及学分(投影和别名)
select cosname as `课程名称`, coscredit as `学分` from TbCourse;
-- 查询所有女学生的姓名和出生日期(筛选)
select stuname, stubirth from TbStudent where stusex=0;
-- 查询所有80后学生的姓名、性别和出生日期(筛选)
select stuname as `姓名`, if(stusex, '男', '女') as `性别`, stubirth as `出生日期`
from TbStudent where stubirth between '1980-1-1' and '1989-12-31';
-- 查询姓王的学生姓名和性别(模糊)
select stuname, stusex from TbStudent where stuname like '王%';
-- 查询姓郭名字总共两个字的学生的姓名(模糊)
select stuname from TbStudent where stuname like '郭_';
-- 查询姓郭名字总共三个字的学生的姓名(模糊)
select stuname from TbStudent where stuname like '郭__';
-- 查询名字中有王字的学生的姓名(模糊)
select stuname from TbStudent where stuname like '%王%';
-- 查询没有录入家庭住址和照片的学生姓名(多条件筛选和空值处理)
select stuname from TbStudent where stuaddr is null and stuphoto is null;
-- 查询学生选课的所有日期(去重)
select distinct scdate from TbSC;
-- 查询学生的姓名和生日按年龄从大到小排列(排序)
select stuname, stubirth from TbStudent order by stubirth;
-- 查询所有录入了家庭住址的男学生的姓名、出生日期和家庭住址按年龄从小到大排列(多条件筛选和排序)
select stuname, stubirth, stuaddr from TbStudent where stusex=1 and stuaddr is not null order by stubirth desc;
-- 查询年龄最大的学生的出生日期(聚合函数)
select min(stubirth) from TbStudent;
-- 查询年龄最小的学生的出生日期(聚合函数)
select max(stubirth) from TbStudent;
-- 查询男女学生的人数(分组和聚合函数)
select if(stusex, '男', '女') as `性别`, count(stusex) as `人数` from TbStudent group by stusex;
-- 查询课程编号为1111的课程的平均成绩(筛选和聚合函数)
select avg(score) as `平均成绩` from TbSC where cid=1111;
-- 查询学号为1001的学生所有课程的总成绩(筛选和聚合函数)
select sum(score) as `总成绩` from TbSC where sid=1001;
-- 查询每个学生的学号和平均成绩, null值处理成0(分组和聚合函数)
select sid as `学号`, ifnull(avg(score), 0) as `平均成绩` from TbSC group by sid;
-- 查询平均成绩大于等于90分的学生的学号和平均成绩
select sid as `学号`, avg(score) as `平均成绩` from TbSC group by sid having avg(score)>=90;
-- 查询年龄最大的学生的姓名(子查询)
select stuname from TbStudent where stubirth=(select min(stubirth) from TbStudent);
-- 查询选了两门以上的课程的学生姓名(子查询/分组条件/集合运算)
select stuname from TbStudent where stuid in
(select sid from TbSC group by sid having count(sid)>2);
-- 查询选课学生的姓名和平均成绩(子查询和连接查询)
-- 写法1:
select stuname, avgscore from TbStudent t1 inner join
(select sid, avg(score) as avgscore from TbSC where score is not null group by sid) t2
on t1.stuid=t2.sid;
-- 写法2:
select stuname, avgscore from TbStudent t1,
(select sid, avg(score) as avgscore from TbSC where score is not null group by sid) t2
where t1.stuid=t2.sid;
-- 查询学生姓名、所选课程名称和成绩(连接查询)
-- 写法1:
select stuname, cosname, score from
TbStudent t1, TbCourse t2, TbSC t3
where t1.stuid=t3.sid and t2.cosid=t3.cid and t3.score is not null;
-- 写法2:
select stuname, cosname, score from TbStudent t1 inner join TbCourse t2
inner join (select sid, cid, score from TbSC where score is not null) t3
on t1.stuid=t3.sid and t2.cosid=t3.cid;
-- 查询每个学生的姓名和选课数量(左外连接和子查询)
select stuname as `姓名`, ifnull(coscount, 0) as `选课数` from TbStudent t1
left outer join (select sid, count(sid) as coscount from TbSC group by sid) t2
on t1.stuid=t2.sid;
-- 创建系统用户表(演示登录操作和SQL注入攻击)
create table TbUser
(
username varchar(20) primary key,
userpass varchar(20) not null
);
-- 插入用户数据
insert into TbUser values ('admin', 'admin');
insert into TbUser values ('hellokitty', '123123');
-- 创建根据学号查询课程平均成绩的存储过程
drop procedure if exists SpGetAvgScoreByStuId;
create procedure SpGetAvgScoreByStuId(stuId integer, out avgScore float)
begin
select avg(score) into avgScore from TbSC where sid=stuId;
end;
-- 调用上面的存储过程
-- set @stuId=1001;
call SpGetAvgScoreByStuId(1001, @avgScore);
select @avgScore as avgScore;
\ No newline at end of file
drop database if exists shiro;
create database shiro default charset utf8;
use shiro;
create table users (
id bigint auto_increment,
username varchar(100),
password varchar(100),
password_salt varchar(100),
constraint pk_users primary key(id)
) charset=utf8 ENGINE=InnoDB;
create unique index idx_users_username on users(username);
create table user_roles(
id bigint auto_increment,
username varchar(100),
role_name varchar(100),
constraint pk_user_roles primary key(id)
) charset=utf8 ENGINE=InnoDB;
create unique index idx_user_roles on user_roles(username, role_name);
create table roles_permissions(
id bigint auto_increment,
role_name varchar(100),
permission varchar(100),
constraint pk_roles_permissions primary key(id)
) charset=utf8 ENGINE=InnoDB;
create unique index idx_roles_permissions on roles_permissions(role_name, permission);
insert into users(username,password)values('zhang','123');
drop database if exists Bank;
drop database if exists bank;
create database Bank default charset utf8;
create database bank default charset utf8;
use Bank;
use bank;
create table TbAccount
create table tb_account
(
accid char(8) primary key,
accowner varchar(20) not null,
accbalance float not null default 0
);
insert into TbAccount values (11223344, '王大锤', 1000);
insert into TbAccount values (22334455, '李小龙', 1000);
\ No newline at end of file
insert into tb_account values (11223344, '王大锤', 1000);
insert into tb_account values (22334455, '李小龙', 1000);
\ No newline at end of file
use hrs;
create table `tb_district`
(
`distid` int not null,
......
......@@ -350,5 +350,230 @@
### Python数据库编程
#### 使用三方库PyMySQL
我们用如下所示的数据库来演示在Python中如何访问MySQL数据库。
```SQL
drop database if exists hrs;
create database hrs default charset utf8;
use hrs;
drop table if exists tb_emp;
drop table if exists tb_dept;
create table tb_dept
(
dno int not null comment '编号',
dname varchar(10) not null comment '名称',
dloc varchar(20) not null comment '所在地',
primary key (dno)
);
insert into tb_dept values
(10, '会计部', '北京'),
(20, '研发部', '成都'),
(30, '销售部', '重庆'),
(40, '运维部', '深圳');
create table tb_emp
(
eno int not null comment '员工编号',
ename varchar(20) not null comment '员工姓名',
job varchar(20) not null comment '员工职位',
mgr int comment '主管编号',
sal int not null comment '员工月薪',
comm int comment '每月补贴',
dno int comment '所在部门编号',
primary key (eno)
);
alter table tb_emp add constraint fk_emp_dno foreign key (dno) references tb_dept (dno);
insert into tb_emp values
(7800, '张三丰', '总裁', null, 9000, 1200, 20),
(2056, '乔峰', '分析师', 7800, 5000, 1500, 20),
(3088, '李莫愁', '设计师', 2056, 3500, 800, 20),
(3211, '张无忌', '程序员', 2056, 3200, null, 20),
(3233, '丘处机', '程序员', 2056, 3400, null, 20),
(3251, '张翠山', '程序员', 2056, 4000, null, 20),
(5566, '宋远桥', '会计师', 7800, 4000, 1000, 10),
(5234, '郭靖', '出纳', 5566, 2000, null, 10),
(3344, '黄蓉', '销售主管', 7800, 3000, 800, 30),
(1359, '胡一刀', '销售员', 3344, 1800, 200, 30),
(4466, '苗人凤', '销售员', 3344, 2500, null, 30),
(3244, '欧阳锋', '程序员', 3088, 3200, null, 20),
(3577, '杨过', '会计', 5566, 2200, null, 10),
(3588, '朱九真', '会计', 5566, 2500, null, 10);
```
在Python 3中,我们通常使用纯Python的三方库PyMySQL来访问MySQL数据库,它应该是目前最好的选择。
1. 安装PyMySQL。
```Shell
pip install pymysql
```
2. 添加一个部门。
```Python
import pymysql
def main():
no = int(input('编号: '))
name = input('名字: ')
loc = input('所在地: ')
# 1. 创建数据库连接对象
con = pymysql.connect(host='localhost', port=3306,
database='hrs', charset='utf8',
user='root', password='123456')
try:
# 2. 通过连接对象获取游标
with con.cursor() as cursor:
# 3. 通过游标执行SQL并获得执行结果
result = cursor.execute(
'insert into tb_dept values (%s, %s, %s)',
(no, name, loc)
)
if result == 1:
# 4. 操作成功提交事务
con.commit()
print('添加成功!')
finally:
# 5. 关闭连接释放资源
con.close()
if __name__ == '__main__':
main()
```
3. 删除一个部门。
```Python
import pymysql
def main():
no = int(input('编号: '))
con = pymysql.connect(host='localhost', port=3306,
database='hrs', charset='utf8',
user='root', password='123456',
autocommit=True)
try:
with con.cursor() as cursor:
result = cursor.execute(
'delete from tb_dept where dno=%s',
(no, )
)
if result == 1:
print('删除成功!')
finally:
con.close()
if __name__ == '__main__':
main()
```
4. 更新一个部门。
```Python
import pymysql
def main():
no = int(input('编号: '))
name = input('名字: ')
loc = input('所在地: ')
con = pymysql.connect(host='localhost', port=3306,
database='hrs', charset='utf8',
user='root', password='123456',
autocommit=True)
try:
with con.cursor() as cursor:
result = cursor.execute(
'update tb_dept set dname=%s, dloc=%s where dno=%s',
(name, loc, no)
)
if result == 1:
print('更新成功!')
finally:
con.close()
if __name__ == '__main__':
main()
```
5. 查询所有部门。
```Python
import pymysql
from pymysql.cursors import DictCursor
def main():
con = pymysql.connect(host='localhost', port=3306,
database='hrs', charset='utf8',
user='root', password='123456')
try:
with con.cursor(cursor=DictCursor) as cursor:
cursor.execute('select dno as no, dname as name, dloc as loc from tb_dept')
results = cursor.fetchall()
print(results)
print('编号\t名称\t\t所在地')
for dept in results:
print(dept['no'], end='\t')
print(dept['name'], end='\t')
print(dept['loc'])
finally:
con.close()
if __name__ == '__main__':
main()
```
6. 分页查询员工信息。
```Python
import pymysql
from pymysql.cursors import DictCursor
class Emp(object):
def __init__(self, no, name, job, sal):
self.no = no
self.name = name
self.job = job
self.sal = sal
def __str__(self):
return f'\n编号:{self.no}\n姓名:{self.name}\n职位:{self.job}\n月薪:{self.sal}\n'
def main():
page = int(input('页码: '))
size = int(input('大小: '))
con = pymysql.connect(host='localhost', port=3306,
database='hrs', charset='utf8',
user='root', password='123456')
try:
with con.cursor() as cursor:
cursor.execute(
'select eno as no, ename as name, job, sal from tb_emp limit %s,%s',
((page - 1) * size, size)
)
for emp_tuple in cursor.fetchall():
emp = Emp(*emp_tuple)
print(emp)
finally:
con.close()
if __name__ == '__main__':
main()
```
\ No newline at end of file
## Django 2.x实战(01) - 快速上手
## Django 2实战-01:快速上手
Web开发的早期阶段,开发者需要手动编写每个页面,例如一个新闻门户网站,每天都要修改它的HTML页面,这样随着网站规模和体量的增大,这种方式就变得极度糟糕。为了解决这个问题,开发人员想到了用外部程序来为Web服务器生成动态内容,也就是说HTML页面以及页面中的动态内容不再通过手动编写而是通过程序自动生成。最早的时候,这项技术被称为CGI(公共网关接口),当然随着时间的推移,CGI暴露出的问题也越来越多,例如大量重复的样板代码,总体性能较为低下等,因此在时代呼唤新英雄的背景下,PHP、ASP、JSP这类Web应用开发技术在上世纪90年代中后期如雨后春笋般涌现。通常我们说的Web应用是指通过浏览器来访问网络资源的应用程序,因为浏览器的普及性以及易用性,Web应用使用起来方便简单,免除了安装和更新应用程序带来的麻烦,而且也不用关心用户到底用的是什么操作系统,甚至不用区分是PC端还是移动端。
......@@ -52,12 +52,10 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
1. 检查Python环境:Django 1.11需要Python 2.7或Python 3.4以上的版本;Django 2.0需要Python 3.4以上的版本。
```Shell
$ python3 --version
```
```Shell
$ python3
>>> import sys
>>> sys.version
......@@ -67,7 +65,6 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
2. 创建项目文件夹并切换到该目录,例如我们要实例一个OA(办公自动化)项目。
```Shell
$ mkdir oa
$ cd oa
```
......@@ -75,7 +72,6 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
3. 创建并激活虚拟环境。
```Shell
$ python3 -m venv venv
$ source venv/bin/activate
```
......@@ -84,7 +80,6 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
4. 更新包管理工具pip。
```Shell
(venv)$ python -m pip install --upgrade pip
```
> 注意:请注意终端提示符发生的变化,前面的`(venv)`说明我们已经进入虚拟环境,而虚拟环境下的python和pip已经是Python 3的解释器和包管理工具了。
......@@ -92,27 +87,23 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
5. 安装Django。
```Shell
(venv)$ pip install django
```
或指定版本号来安装对应的Django的版本。
```Shell
(venv)$ pip install django==1.11
```
6. 检查Django的版本。
```Shell
(venv)$ python -m django --version
(venv)$ django-admin --version
```
```Shell
(venv)$ python
>>> import django
>>> django.get_version()
......@@ -131,7 +122,6 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
7. 使用`django-admin`创建项目,项目命名为oa。
```Shell
(venv)$ django-admin startproject oa .
```
......@@ -148,7 +138,6 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
8. 启动服务器运行项目。
```Shell
(venv)$ python manage.py runserver
```
......@@ -168,13 +157,11 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
9. 接下来我们进入项目目录oa并修改配置文件settings.py,Django是一个支持国际化和本地化的框架,因此刚才我们看到的默认首页也是支持国际化的,我们将默认语言修改为中文,时区设置为东八区。
```Shell
(venv)$ cd oa
(venv)$ vim settings.py
```
```Python
# 此处省略上面的内容
# 设置语言代码
......@@ -188,7 +175,6 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
10. 回到manage.py所在的目录,刷新刚才的页面。
```Shell
(venv)$ cd ..
(venv)$ python manage.py runserver
```
......@@ -200,7 +186,6 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
1. 创建名为hrs(人力资源系统)的应用(注:一个项目可以包含多个应用)。
```Shell
(venv)$ python manage.py startapp hrs
```
......@@ -218,31 +203,26 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
2. 进入应用目录修改视图文件views.py。
```Shell
(venv)$ cd hrs
(venv)$ vim views.py
```
```Python
from django.http import HttpResponse
def index(request):
return HttpResponse('<h1>Hello, Django!</h1>')
```
3. 在应用目录创建一个urls.py文件并映射URL。
```Shell
(venv)$ touch urls.py
(venv)$ vim urls.py
```
```Python
from django.urls import path
from hrs import views
......@@ -256,14 +236,12 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
4. 切换到项目目录,修改该目录下的urls.py文件,对应用中设定的URL进行合并。
```Shell
(venv) $ cd ..
(venv) $ cd oa
(venv) $ vim urls.py
```
```Python
from django.contrib import admin
from django.urls import path, include
......@@ -276,7 +254,6 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
5. 启动项目并访问应用。
```Shell
(venv)$ cd ..
(venv)$ python manage.py runserver
```
......@@ -288,13 +265,11 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
6. 修改views.py生成动态内容。
```Shell
(venv)$ cd hrs
(venv)$ vim views.py
```
```Python
from io import StringIO
from django.http import HttpResponse
......@@ -337,7 +312,6 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
7. 再次使用下面的命令来启动服务器并查看程序的运行结果。
```Shell
(venv)$ cd ..
(venv)$ python manage.py runserver
```
......@@ -352,7 +326,6 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
1. 先回到manage.py文件所在的目录创建一个templates文件夹。
```Shell
(venv)$ cd ..
(venv)$ mkdir templates
(venv)$ cd templates
......@@ -361,12 +334,10 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
2. 创建模板页index.html。
```Shell
(venv)$ touch index.html
(venv)$ vim index.html
```
```HTML
<!DOCTYPE html>
<html lang="en">
<head>
......@@ -398,14 +369,12 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
3. 回到应用目录,修改views.py文件。
```Shell
(venv)$ cd ..
(venv)$ cd hrs
(venv)$ vim views.py
```
```Python
from django.shortcuts import render
depts_list = [
......@@ -424,14 +393,12 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
4. 切换到项目目录修改settings.py文件。
```Shell
(venv)$ cd ..
(venv)$ cd oa
(venv)$ vim settings.py
```
```Python
# 此处省略上面的内容
TEMPLATES = [
......@@ -456,7 +423,6 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
5. 重新运行项目并查看结果。
```Shell
(venv)$ cd ..
(venv)$ python manage.py runserver
```
......
## Django 2.x实战(02) - 深入模型
## Django 2实战-02:深入模型
在上一个章节中,我们提到了Django是基于MVC架构的Web框架,MVC架构追求的是“模型”和“视图的解耦合。所谓“模型”说得更直白一些就是数据,所以通常也被称作“数据模型”。在实际的项目中,数据模型通常通过数据库实现持久化操作,而关系型数据库在很长一段时间都是持久化的首选方案,下面我们以MySQL为例来说明如何使用关系型数据库来实现持久化操作。
......@@ -9,13 +9,11 @@
1. 进入oa文件夹,修改项目的settings.py文件,首先将我们之前创建的应用hrs添加已安装的项目中,然后配置MySQL作为持久化方案。
```Shell
(venv)$ cd oa
(venv)$ vim settings.py
```
```Python
# 此处省略上面的代码
INSTALLED_APPS = [
......@@ -56,14 +54,12 @@
2. 安装MySQL客户端工具,Python 3中使用PyMySQL,Python 2中用MySQLdb。
```Shell
(venv)$ pip install pymysql
```
如果使用Python 3需要修改**项目**的`__init__.py`文件并加入如下所示的代码,这段代码的作用是将PyMySQL视为MySQLdb来使用,从而避免Django找不到连接MySQL的客户端工具而询问你:“Did you install mysqlclient? ”(你安装了mysqlclient吗?)。
```Python
import pymysql
pymysql.install_as_MySQLdb()
......@@ -72,13 +68,11 @@
3. 运行manage.py并指定migrate参数实现数据库迁移,为应用程序创建对应的数据表,当然在此之前需要**先启动MySQL数据库服务器并创建名为oa的数据库**,在MySQL中创建数据库的语句如下所示。
```SQL
drop database if exists oa;
create database oa default charset utf8;
```
```Shell
(venv)$ cd ..
(venv)$ python manage.py migrate
Operations to perform:
......@@ -103,13 +97,11 @@
4. 可以看到,Django帮助我们创建了10张表,这些都是使用Django框架需要的东西,稍后我们就会用到这些表。除此之外,我们还应该为我们自己的应用创建数据模型。如果要在hrs应用中实现对部门和员工的管理,我们可以创建如下所示的数据模型。
```Shell
(venv)$ cd hrs
(venv)$ vim models.py
```
```Python
from django.db import models
......@@ -145,7 +137,6 @@
5. 通过模型创建数据表。
```Shell
(venv)$ cd ..
(venv)$ python manage.py makemigrations hrs
Migrations for 'hrs':
......@@ -168,7 +159,6 @@
1. 创建超级管理员账号。
```Shell
(venv)$ python manage.py createsuperuser
Username (leave blank to use 'hao'): jackfrued
Email address: jackfrued@126.com
......@@ -180,7 +170,6 @@
2. 启动Web服务器,登录后台管理系统。
```Shell
(venv)$ python manage.py runserver
```
......@@ -197,13 +186,11 @@
3. 注册模型类。
```Shell
(venv)$ cd hrs
(venv)$ vim admin.py
```
```Python
from django.contrib import admin
from hrs.models import Emp, Dept
......@@ -237,7 +224,6 @@
再次修改admin.py文件,通过注册模型管理类,可以在后台管理系统中更好的管理模型。
```Python
from django.contrib import admin
from hrs.models import Emp, Dept
......@@ -266,7 +252,6 @@
为了更好的查看模型数据,可以为Dept和Emp两个模型类添加`__str__`魔法方法。
```Python
from django.db import models
......@@ -308,7 +293,6 @@
在了解了Django提供的模型管理平台之后,我们来看看如何从代码层面完成对模型的CRUD(Create / Read / Update / Delete)操作。我们可以通过manage.py开启Shell交互式环境,然后使用Django内置的ORM框架对模型进行CRUD操作。
```Shell
(venv)$ cd ..
(venv)$ python manage.py shell
Python 3.6.4 (v3.6.4:d48ecebad5, Dec 18 2017, 21:07:28)
......@@ -321,8 +305,6 @@ Type "help", "copyright", "credits" or "license" for more information.
#### 新增
```Shell
>>>
>>> from hrs.models import Dept, Emp
>>> dept = Dept(40, '研发2部', '深圳')
>>> dept.save()
......@@ -331,8 +313,6 @@ Type "help", "copyright", "credits" or "license" for more information.
#### 更新
```Shell
>>>
>>> dept.name = '研发3部'
>>> dept.save()
```
......@@ -342,8 +322,6 @@ Type "help", "copyright", "credits" or "license" for more information.
查询所有对象。
```Shell
>>>
>>> Dept.objects.all()
<QuerySet [<Dept: 研发1>, <Dept: 销售1>, <Dept: 运维1>, <Dept: 研发3>]>
```
......@@ -351,8 +329,6 @@ Type "help", "copyright", "credits" or "license" for more information.
过滤数据。
```Shell
>>>
>>> Dept.objects.filter(name='研发3部') # 查询部门名称为“研发3部”的部门
<QuerySet [<Dept: 研发3>]>
>>>
......@@ -369,8 +345,6 @@ Type "help", "copyright", "credits" or "license" for more information.
查询单个对象。
```Shell
>>>
>>> Dept.objects.get(pk=10)
<Dept: 研发1>
>>>
......@@ -384,8 +358,6 @@ Type "help", "copyright", "credits" or "license" for more information.
排序数据。
```Shell
>>>
>>> Dept.objects.order_by('no') # 查询所有部门按部门编号升序排列
<QuerySet [<Dept: 研发1>, <Dept: 销售1>, <Dept: 运维1>, <Dept: 研发3>]>
>>>
......@@ -396,8 +368,6 @@ Type "help", "copyright", "credits" or "license" for more information.
切片数据。
```Shell
>>>
>>> Dept.objects.order_by('no')[0:2] # 按部门编号排序查询1~2部门
<QuerySet [<Dept: 研发1>, <Dept: 销售1>]>
>>>
......@@ -408,8 +378,6 @@ Type "help", "copyright", "credits" or "license" for more information.
高级查询。
```Shell
>>>
>>> Emp.objects.filter(dept__no=10) # 根据部门编号查询该部门的员工
<QuerySet [<Emp: 乔峰>, <Emp: 张无忌>, <Emp: 张三丰>]>
>>>
......@@ -429,8 +397,6 @@ Type "help", "copyright", "credits" or "license" for more information.
#### 删除
```Shell
>>>
>>> Dept.objects.get(pk=40).delete()
(1, {'hrs.Dept': 1})
```
......@@ -567,8 +533,6 @@ ManyToManyField属性
Q对象(用于执行复杂查询)的使用:
```Shell
>>>
>>> from django.db.models import Q
>>> Emp.objects.filter(
... Q(name__startswith='张'),
......
This diff is collapsed.
## Django 2.x实战(04) - 表单的应用
## Django 2实战-04:表单的应用
我们继续来完成上一章节中的项目,实现“用户注册”和“用户登录”的功能。Django框架中提供了对表单的封装,而且提供了多种不同的使用方式。
## Django 2.x实战(05) - Cookie和会话
## Django 2实战-05:Cookie和会话
## Django 2.x实战(06) - 中间件的应用
## Django 2实战06:中间件的应用
## Django 2.x实战(07) - 日志和缓存
## Django 2实战-07:日志和调试
## Django 2.x实战(08) - 文件上传
## Django 2实战08:文件上传和富文本编辑
## Django 2.x实战(09-10) - RESTful架构和应用
## Django 2实战08:文件下载和报表
## Django 2实战10:RESTful架构和DRF入门
## Django 2.x实战(11-15) - 项目实战
## Django 2实战11:RESTful架构和DRF进阶
## Django 2实战12:使用缓存
## Django 2实战13:短信和邮件
## Django 2实战14:异步任务和定时任务
## Django 2实战15:测试和部署
## Matplotlib和数据可视化
数据的处理、分析和可视化已经成为Python近年来最为重要的应用领域之一,其中数据的可视化指的是将数据呈现为漂亮的统计图表,然后进一步发现数据中包含的规律以及隐藏的信息。数据可视化又跟数据挖掘和大数据分析紧密相关,而这些领域以及当下被热议的“深度学习”其最终的目标都是为了实现从过去的数据去对未来的状况进行预测。Python在实现数据可视化方面是非常棒的,即便是使用个人电脑也能够实现对百万级甚至更大体量的数据进行探索的工作,而这些工作都可以在现有的第三方库的基础上来完成(无需“重复的发明轮子”)。[Matplotlib](https://matplotlib.org/)就是Python绘图库中的佼佼者,它包含了大量的工具,你可以使用这些工具创建各种图形(包括散点图、折线图、直方图、饼图、雷达图等),Python科学计算社区也经常使用它来完成数据可视化的工作。
### 安装matplotlib
可以使用pip来安装matplotlib,命令如下所示。
```Shell
pip install matplotlib
```
### 绘制折线图
```Python
# coding: utf-8
import matplotlib.pyplot as plt
def main():
# 保存x轴数据的列表
x_values = [x for x in range(1, 11)]
# 保存y轴数据的列表
y_values = [x ** 2 for x in range(1, 11)]
# 设置图表的标题以及x和y轴的说明
plt.title('Square Numbers')
plt.xlabel('Value', fontsize=18)
plt.ylabel('Square', fontsize=18)
# 设置刻度标记的文字大小
plt.tick_params(axis='both', labelsize=16)
# 绘制折线图
plt.plot(x_values, y_values)
plt.show()
if __name__ == '__main__':
main()
```
运行程序,效果如下图所示。
![](./res/result1.png)
如果使用jupyter的notebook,需要使用魔法指令`%matplotlib inresline`来设置在页面中显示图表,效果如下所示。
![](./res/result-in-jupyter.png)
### 绘制散点图
可以将上面代码中的的`plot`函数换成`scatter`函数来绘制散点图,效果如下图所示。
![](./res/result2.png)
当然,也可以直接通过`plot`函数设置绘图的颜色和线条的形状将折线图改造为散点图,对应的代码如下所示,其中参数'xr'表示每个点的记号是‘x’图形,颜色是红色(<u>r</u>ed)。
```Python
plt.plot(x_values, y_values, 'xr')
```
重新运行程序,效果如下图所示。
![](./res/result3.png)
可能大家已经注意到了,1和10对应的‘x’记号在图形边角的位置不太明显,要解决这个问题可以通过添加下面的代码调整x轴和y轴的坐标范围。
```Python
plt.axis([0, 12, 0, 120])
```
调整后的效果如下图所示。
![](./res/result4.png)
### 绘制正弦曲线
在下面的程序中,我们使用了名为[NumPy](http://www.numpy.org/)的第三方库来产生样本并计算正弦值。NumPy是一个运行速度非常快的数学库,主要用于数组计算。它可以让你在Python中使用向量和数学矩阵,以及许多用C语言实现的底层函数。如果想通过Python学习数据科学或者机器学习相关的内容,那么就得先学会使用NumPy。
```Python
# coding: utf-8
import matplotlib.pyplot as plt
import numpy as np
def main():
# 指定采样的范围以及样本的数量
x_values = np.linspace(0, 2 * np.pi, 1000)
# 计算每个样本对应的正弦值
y_values = np.sin(x_values)
# 绘制折线图(线条形状为--, 颜色为蓝色)
plt.plot(x_values, y_values, '--b')
plt.show()
if __name__ == '__main__':
main()
```
运行程序,效果如下图所示。
![](./res/result5.png)
如果要在一个坐标系上绘制多个图像,可以按照如下的方式修改代码。
```Python
# coding: utf-8
import matplotlib.pyplot as plt
import numpy as np
def main():
x_values = np.linspace(0, 2 * np.pi, 1000)
plt.plot(x_values, np.sin(x_values), '--b')
plt.plot(x_values, np.sin(2 * x_values), '--r')
plt.show()
if __name__ == '__main__':
main()
```
修改后的代码运行效果如下图所示。
![](./res/result6.png)
如果需要分别在两个坐标系上绘制出两条曲线,可以按照如下的方式操作。
```Python
# coding: utf-8
import matplotlib.pyplot as plt
import numpy as np
def main():
# 将样本数量减少为50个
x_values = np.linspace(0, 2 * np.pi, 50)
# 设置绘图为2行1列活跃区为1区(第一个图)
plt.subplot(2, 1, 1)
plt.plot(x_values, np.sin(x_values), 'o-b')
# 设置绘图为2行1列活跃区为2区(第二个图)
plt.subplot(2, 1, 2)
plt.plot(x_values, np.sin(2 * x_values), '.-r')
plt.show()
if __name__ == '__main__':
main()
```
效果如下图所示。
![](./res/result7.png)
### 绘制直方图
我们可以通过NumPy的random模块的normal函数来生成[正态分布](https://zh.wikipedia.org/wiki/%E6%AD%A3%E6%80%81%E5%88%86%E5%B8%83)的采样数据,其中的三个参数分别表示期望、标准差和样本数量,然后绘制成直方图,代码如下所示。
```Python
# coding: utf-8
import matplotlib.pyplot as plt
import numpy as np
def main():
# 通过random模块的normal函数产生1000个正态分布的样本
data = np.random.normal(10.0, 5.0, 1000)
# 绘制直方图(直方的数量为10个)
plt.hist(data, 10)
plt.show()
if __name__ == '__main__':
main()
```
运行效果如下图所示。
![](./res/result8.png)
### 使用Pygal绘制矢量图
矢量图(SVG)是[计算机图形学](https://zh.wikipedia.org/wiki/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9B%BE%E5%BD%A2%E5%AD%A6)中用点、直线或者多边形等基于数学方程的几何图元表示的图像,也是目前应用得非常多的一种图像文件格式,全称是“Scalable Vector Graphics”。和使用像素表示图像的位图不同,SVG基于XML存储图像数据,它是W3C定义的一种开放标准的矢量图形语言,可以用来设计更为清晰的Web图像,因为SVG与分辨率无关,在任意放大时不会丢失细节或影响清晰度。SVG可以直接用代码来描绘图像,也可以用任何文字处理工具来打开它,通过改变SVG的代码我们可以让图像具备交互功能。
Python中可以使用Pygal来生成SVG,可以通过pip来安装它。
```Python
from random import randint
import pygal
def roll_dice(n=1):
total = 0
for _ in range(n):
total += randint(1, 6)
return total
def main():
results = []
# 将两颗色子摇10000次记录点数
for _ in range(10000):
face = roll_dice(2)
results.append(face)
freqs = []
# 统计2~12点各出现了多少次
for value in range(2, 13):
freq = results.count(value)
freqs.append(freq)
# 绘制柱状图
hist = pygal.Bar()
hist.title = 'Result of rolling two dice'
hist.x_labels = [x for x in range(2, 13)]
hist.add('Frequency', freqs)
# 保存矢量图
hist.render_to_file('result.svg')
if __name__ == '__main__':
main()
```
运行上面的程序,效果如下图所示。
![](./res/result9.png)
### 后记
Matplotlib和NumPy的强大我们在这里也只是窥视了其冰山一角,我们在后续的内容里面还会使用到这两个第三方库,到时候我们再续点为大家介绍其他的功能。
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment