目录
面向对象
# 1.什么是对象?
对象其实就是数据和功能的结合体
# 2.为什么要用对象
面向对象编程就是要造出一个个的对象,把原本分散开的相关数据与功能整合到一个个的对象里,这么做既方便使用,也可以提高程序的解耦合程度,进而提升了程序的可扩展性
类的概念
"""类其实就是对象公共的数据和功能的结合体"""
我们可以把同一类对象相同的数据与功能存放到类里,而无需每个对象都重复存一份,这样每个对象里只需存自己独有的数据即可,极大地节省了空间。所以,如果说对象是用来存放数据与功能的容器,那么类则是用来存放多个对象相同的数据与功能的容器。
类与对象的关系
在程序中必须要先有类
然后才能利用类产生对象
类的定义与实例化
# 以开发清华大学选课系统
1.先分析学生角色
# 学生的数据有
学校
名字
年龄
性别
# 学生的功能有
选课
2.模拟出多个学生
# 学生1:
数据:
学校=清华大学
姓名=李建刚
性别=男
年龄=28
功能:
选课
# 学生2:
数据:
学校=清华大学
姓名=王大力
性别=女
年龄=18
功能:
选课
# 学生3:
数据:
学校=清华大学
姓名=牛嗷嗷
性别=男
年龄=38
功能:
选课
3.抽取多个学生公共的数据和功能
数据:
学校=清华大学
功能:
选课
类的定义
1.定义函数需要用到关键字def
2.定义类需要用到关键字class
在类中定义的函数不叫函数 叫方法
class Student: # 1.类的命名(首字母必须大写)
school='清华大学' # 数据
def choose(self): # 功能
print('%s is choosing a course' %self.name)
print(Student.__dict__) # 查看类名称空间中的名字
对象的创建
# 类产生对象只需要类名加括号调用(实例化)即可产生对象
class Student:
school = '清华大学'
def choose(self):
print('正在选课')
# print(Student.__dict__) # 查看类名称空间中的名字
obj1 = Student()
obj2 = Student()
obj3 = Student()
# print(id(obj1),id(obj2),id(obj3)) #1938230058120 1938230182688 1938230182800
# 访问数据和方法统一采用句点符
print(obj1.school)
print(obj2.school)
print(obj3.school)
print(obj1.choose)
print(obj2.choose)
print(obj3.choose)
"""
类名只要加括号就会生成对象 并且每一次生成的都不一样
都是不同的对象
类产生的所有的对象都可以访问到类里面的数据和方法
统一采用句点符访问
"""
# 每个对象除了可以有公共的属性和方法还应该彼此都用于彼此独有的数据和方法
class Student:
school = '清华大学'
# 该方法会在对象产生之后自动执行,专门为对象进行初始化操作(让对象拥有自己独有的属性)
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
def choose(self):
print('正在选课')
obj1 = Student('jason',18,'male')
obj2 = Student('frank',73,'female')
obj3 = Student('haoda',35,'male')
# print(obj1.school)
# print(obj2.school)
# print(obj3.school) # 访问公共的属性和方法
# print(obj1.__dict__)
# print(obj2.__dict__)
# print(obj3.__dict__)
print(obj1.name,obj1.age,obj1.gender) # 访问自己独有的属性jason 18 male
print(obj2.name,obj2.age,obj2.gender) # 访问自己独有的属性frank 73 female
print(obj3.name,obj3.age,obj3.gender) # 访问自己独有的属性haoda 35 male
属性查找
class Student:
school = '清华大学'
def __init__(self,name,school):
self.name = name
self.school = school
obj1 = Student('jason','家里蹲大学')
obj2 = Student('frank','没钱上大学')
# print(Student.__dict__)
# print(obj1.__dict__)
# print(obj2.__dict__)
print(obj1.school) # 家里蹲大学
'''当对象和类里面都有一个相同的属性的时候 对象在查找的时候优先用自己'''
# print(obj1.choose)
# print(obj2.choose)
print(Student.choose()) # 需要自己传
# obj1.choose() # jason is choosing course 不需要自己传choose(obj1)
# obj2.choose() # frank is choosing course choose(obj2)
"""
定义在类里面的函数默认都是绑定给对象的(即对象来调用会自动将对象当做第一个参数传入)
而类在调用的时候则需要自己手动传入参数
"""
Python中一切皆为对象
s = 'hello world'
s.split()
l = [1,2,3,4]
l.append()
d = {'username':'jason'}
d.get()
...
面向对象三大特性
封装
继承
多态
# 封装
封装指的就是把数据与功能都整合到一起
并且针对封装了的数据和功能我还可以控制他们被访问的方式
# 隐藏属性
class Student:
school = '清华大学'
__info = '我没考上'
def index(self):
print('from index')
def __func(self):
print('from __func')
obj = Student()
print(obj._Student__info)
print(obj._Student__func)
# print(obj.school)
# print(obj.__info)
# print(obj.index)
# print(obj.__func)
# print(Student.__dict__)
"""
在类中以双下划綫开头的变量名和方法名 都会被隐藏起来无法直接访问
__info 自动变形 _Student__info _类名__变量名
__func 自动变形 _Student__func
"""
隐藏的目的是为了让用户不能直接访问而是需要通过我们提供的接口间接访问
我们可以在接口之上加上一些额外的操作
class Teacher:
def __init__(self,name,age): #将名字和年纪都隐藏起来
self.__name=name
self.__age=age
def tell_info(self): #对外提供访问老师信息的接口
print('姓名:%s,年龄:%s' %(self.__name,self.__age))
def set_info(self,name,age): #对外提供设置老师信息的接口,并附加类型检查的逻辑
if not isinstance(name,str):
raise TypeError('姓名必须是字符串类型')
if not isinstance(age,int):
raise TypeError('年龄必须是整型')
self.__name=name
self.__age=age
obj = Teacher('jason',18)
# obj.tell_info()
"""
访问对象的属性 用对象.属性
修改对写的属性
对象.属性 = 新的值
obj1.name = 'frank'
"""
# obj.name = 'frank' # 无效
# obj.set_info('frank',40)
obj.set_info(40,'hahaha')
obj.tell_info()
class People:
def __init__(self, name, weight, height):
self.name = name
self.weight = weight
self.height = height
@property # 将方法伪装成一个属性 用户在访问的时候不需要加括号
def bmi(self):
return self.weight / (self.height ** 2)
# obj1 = People('jason',75,1.83)
obj1 = People('frank',80,1.73)
# res = obj1.bmi()
# print(res)
print(obj1.bmi)
print(obj1.name)
继承
在python中一个类可以继承单个或者多个类
1.继承的类称之为子类
2.被继承的类称之为父类、基类、超类
class ParentClass1: #定义父类
pass
class ParentClass2: #定义父类
pass
class SubClass1(ParentClass1): #单继承
pass
class SubClass2(ParentClass1,ParentClass2): #多继承
pass
# 如何查看类的父类?
print(SubClass1.__bases__) # (<class '__main__.ParentClass1'>,)
print(SubClass2.__bases__) # (<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
print(ParentClass1.__bases__) # (<class 'object'>,)
print(ParentClass2.__bases__) # (<class 'object'>,)
"""
在python3中
如果一个类没有继承任何的父类 那么默认都是继承object
在python2中
如果一个类没有继承任何的父类 那么就是什么都不继承
经典类
不继承任何的类 只有在python2中才有
新式类
继承object或者其子类的类 在python3中只有新式类
"""
# 在定义类的时候为了兼容python2和python3
class MyClass(object):
pass
父类的概念
对象是数据和功能的结合体
类是对象公共的数据和功能的结合体
父类是类的公共的数据和功能的结合体
class People:
school = '清华大学'
def __init__(self, name, sex, age):
self.name = name
self.sex = sex
self.age = age
class Student(People):
def choose(self):
print('%s is choosing a course' % self.name)
class Teacher(People):
def teach(self):
print('%s is teaching' % self.name)
# print(Student.choose)
# print(Teacher.teach)
print(Student.school)
print(Teacher.school)
属性查找固定规律
1.先从对象自身找
2.再去产生对象的类中找
3.再去类的父类中找
class P:
# name = 'jason'
pass
class S(P):
# name = 'frank'
pass
obj = S()
# obj.name = 'haoda'
print(obj.name)
调用父类的方法
class People:
school = '清华大学'
def __init__(self, name, sex, age):
self.name = name
self.sex = sex
self.age = age
class Student(People):
# 继承了父类的方法之后 还想再扩展
def __init__(self,name,age,sex,hobby):
super().__init__(name,age,sex) # 调用父类的方法
self.hobby = hobby
def choose(self):
print('%s is choosing a course' % self.name)
class Teacher(People):
# 继承了父类的方法之后 还想再扩展
def __init__(self, name, age, sex, level):
super().__init__(name, age, sex) # 调用父类的方法
self.level = level
def teach(self):
print('%s is teaching' % self.name)
stu = Student('frank','female',40,'read')
tea = Teacher('jason','male',18,'金牌讲师')
print(stu.name,stu.hobby)
print(tea.name,tea.level)
多态
一种事物的多种形态
只要是一种事物那么你就可以不需要考虑该事物到底那种形态
直接调用统一的方法
比如
无论是猫、狗、猪都有叫的功能
talk()
len('jason')
len([1,2,3,4])
len({'username':'jason'})
多态性的好处在于增强了程序的灵活性和可扩展性,比如通过继承Animal类创建了一个新的类,实例化得到的对象obj,可以使用相同的方式使用obj.talk()
鸭子类型
只要你看上去像鸭子、走路像鸭子、说话像鸭子那么你就是鸭子
class Txt: #Txt类有两个与文件类型同名的方法,即read和write
def read(self):
pass
def write(self):
pass
class Disk: #Disk类也有两个与文件类型同名的方法:read和write
def read(self):
pass
def write(self):
pass
绑定方法与非绑定方法
在类中定义的函数默认是绑定给对象的(对象来调会自动将对象当做第一个参数传入)
class MyClass(object):
# 绑定给对象的
def index(self):
print('from index',self)
# 普普通通的函数
@staticmethod
def func(name):
print('from func',name)
# 绑定给类的
@classmethod
def bar(cls):
print('from bar',cls)
# obj = MyClass()
# obj.index() # from index <__main__.MyClass object at 0x000001C1DB4FC2E8>
# print(obj) # <__main__.MyClass object at 0x000001C1DB4FC2E8>
# obj.func()
# MyClass.func()
# obj.func('jason') # 都需要传参数
# MyClass.func('egon')
'''
绑定给类的方法 类来调自动将类传入
类的对象来调则会将产生对象的类传入
'''
# MyClass.bar()
# print(MyClass)
obj = MyClass()
obj.bar()
反射
'''利用字符串来操作对象的属性或方法'''
class MyClass(object):
province = '上海'
name = 'jason'
def index(self):
pass
# 你手上只有一个字符串的'province'判断类里面有没有对应的属性或者方法
# res = hasattr(MyClass,'province')
# print(res)
# res1 = hasattr(MyClass,'age')
# print(res1)
# res2 = hasattr(MyClass,'index')
# print(res2)
# 获取对象中的值
# ret = getattr(MyClass,'province')
# print(ret)
# ret1 = getattr(MyClass,'index')
# print(ret1)
# ret2 = getattr(MyClass,'gender')
# print(ret2)
# 猜属性和方法的小游戏
# while True:
# cai = input('>>>:')
# if hasattr(MyClass,cai):
# res = getattr(MyClass,cai)
# print(res)
# else:
# print('没有该属性或者方法')
import myfile
print(hasattr(myfile,'name'))
print(hasattr(myfile,'heihei'))
print(getattr(myfile,'name'))
异常处理
1.语法错误
不能被允许
2.逻辑错误
可以被允许
try:
被检测的代码块
except 异常类型:
检测到异常,就执行这个位置的逻辑
# try:
# # name
# l = [1,23]
# l[100]
# except IndexError as e:
# print(e) # 内部自动定义的报错信息
# print('索引超出范围') # 自己自定制的报错信息
# except NameError:
# print('名字错误')
# except TypeError:
# print('类型错误')
# 万能异常
try:
# name
# 1+'2'
l = [1,3,4]
l[100]
except Exception as e: # 能够接受任意类型的错误并处理
print(e)
"""
异常处理虽然好用,但是我们要尽可能少的使用它
try代码块里面的被监控的代码应该越少越好
"""
网络编程
1.OSI七层
应用层
表示层
会话层
传输层
网络层
数据链路层
物理连接层
2.精简为五层
应用层
传输层
网络层
数据链路层
物理连接层
1.滚筒式电话
2.大屁股电脑
3.笔记本电脑
"""
要想远程通信有一个必备前提条件
必须要有一个物理连接介质
电话线
网线
网卡
"""
讲解自己的笔记、博客
套接字通信
# c/s架构的程序
'''需要你掌握的代码'''
import socket
"""
服务端需要满足的三个条件
1.必须得有固定的ip和port
2.24小时不间断提供服务
3.支持高并发
"""
# 生成一个通信对象
server = socket.socket() # 默认走的是TCP协议
# 要给服务端绑定ip和port
server.bind(('127.0.0.1',8080))
# 半连接池
server.listen(5)
# 监听
conn, addr = server.accept()
# 跟客户端交互
res = conn.recv(1024) # 接收客户端发来的消息
print(res.decode('utf-8'))
# 关闭连接
conn.close()
客户端
import socket
client = socket.socket()
# 连接服务端
client.connect(('127.0.0.1',8080))
client.send('快点 等不及了'.encode('utf-8'))
client.close()
聊天功能
服务端
import socket
server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)
while True:
conn, addr = server.accept()
while True:
res = conn.recv(1204)
print(res.decode('utf-8'))
cmd = input('>>>:')
conn.send(cmd.encode('utf-8'))
客户端
import socket
client = socket.socket()
client.connect(('127.0.0.1', 8080))
while True:
res = input('>>>:')
client.send(res.encode('utf-8'))
data = client.recv(1024)
print(data.decode('utf-8'))
并发编程
"""
研究并发编程其实就是研究计算机的发展史及计算机硬件
"""
进程
重要概念介绍
并发与并行
1.并发 切换+保存状态
看起来像同时在运行就可以称之为是并发
只有一个cpu多个任务的情况下也可以实现并发效果
当一个任务进入IO操作之后操作系统会自动将cpu拿走给其他任务用,单个cpu在多个任务之间快速切换
2.并行
多个任务同时执行(必须有多个cpu)
同步与异步
1.同步
提交任务之后原地等待任务的返回结果期间不做任何事情
2.异步
提交任务之后不愿地等待任务的返回结果直接执行下一行代码
进程的三状态图
1.任何程序要想被执行 都必须先结果就绪态
2.处于运行态的程序一旦遇到IO操作会立刻丧失CPU的控制权进入阻塞态
阻塞
阻塞态
非阻塞
就绪态、运行态
如何开启进程
1.鼠标双击一个应用图标
2.代码来创建进程
from multiprocessing import Process
import time
def index(name):
print('%s is running'%name)
time.sleep(3)
print('%s is over'%name)
# 在windows中创建进程的代码必须放到__main__下面
if __name__ == '__main__':
p = Process(target=index,args=('frank',))
p.start() # 告诉操作系统创建一个进程
print('主')
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self,name):
super().__init__() # 这句话不能少
self.name = name
def run(self):
print('%s is running'%self.name)
time.sleep(3)
print('%s is over'%self.name)
if __name__ == '__main__':
obj = MyProcess('frank')
obj.start()
print('主')
线程
"""
进程其实是资源单位
线程才是真正的执行单位
每个进程下默认都会自带一个线程
如果将内存比喻成工厂
那么进程就是类似于工厂里面的一个个车间
线程就类似于是车间里面的流水线
同一个车间内多个流水线可以共享资源即
同一个进程下的多个线程数据是共享的
多个进程之间数据默认是不共享的
创建进程的开销要远远大于创建线程的开销
创建进程
1.需要申请内存空间
2.拷贝代码
创建线程
上述两部都可以省略
"""
from threading import Thread
import time
def index(name):
print('%s is running'%name)
time.sleep(3)
print('%s is over'%name)
t1 = Thread(target=index,args=('frank',))
t1.start()
print('主')
from threading import Thread
import time
class MyThread(Thread):
def run(self):
print('running')
time.sleep(3)
print('over')
obj = MyThread()
obj.start()
print('主')
多进程还是多线程好
"""
一般情况下我们都是
开设多进程然后在每个进程内再开设多线程
实现效率的最大化
"""
MySQL数据库
navicat简单使用
表与表之间关系
一对多
多对多
一对一
一对多关系
员工表和部门表
参考群内截图
多对多关系
图书表和作者表
参考群内截图
一对一关系
参考群内截图
MySQL查询练习题
-- 1、查询所有的课程的名称以及对应的任课老师姓名
-- SELECT
-- course.cname,
-- teacher.tname
-- FROM
-- course
-- INNER JOIN teacher ON course.teacher_id = teacher.tid;
-- 4、查询平均成绩大于八十分的同学的姓名和平均成绩
-- 先去score表中求出平均成绩大于80分的学生的id号
-- 再去学生表中根据获取到的id号筛选出学生的姓名
-- SELECT
-- student.sname,
-- t1.avg_num
-- FROM
-- student
-- INNER JOIN (
-- SELECT
-- score.student_id,
-- avg( score.num ) AS avg_num
-- FROM
-- score
-- GROUP BY
-- score.student_id
-- HAVING
-- avg( score.num ) > 80
-- ) AS t1 ON student.sid = t1.student_id;
-- 7、 查询没有报李平老师课的学生姓名
-- 整体思路 查询报了李平老师课程的学生id 然后取反
-- 1.先获取李平老师教授的课程id号
-- 2.根据课程id号去分数表里面获取学生id号
-- 3.最后去学生表里面取反获取没有报李平老师课程的学生姓名
-- SELECT
-- student.sname
-- FROM
-- student
-- WHERE
-- student.sid NOT IN (
-- SELECT DISTINCT
-- score.student_id
-- FROM
-- score
-- WHERE
-- score.course_id IN ( SELECT course.cid FROM course INNER JOIN teacher ON course.teacher_id = teacher.tid WHERE teacher.tname = '李平老师' )
-- );
--
-- 8、 查询没有同时选修物理课程和体育课程的学生姓名
-- 整体思路 先拿到所有报了物理或者体育的学生id
-- 1.先获取物理课程和体育课程id号
-- 2.去分数表里面过滤出所有选了id号的学生id
-- 3.按照学生id分组 筛选掉报了两门的数据
-- SELECT
-- student.sname
-- FROM
-- student
-- WHERE
-- student.sid IN (
-- SELECT
-- score.student_id
-- FROM
-- score
-- WHERE
-- score.course_id IN ( SELECT course.cid FROM course WHERE course.cname IN ( '物理', '体育' ) )
-- GROUP BY
-- score.student_id
-- HAVING
-- count( score.course_id ) = 1
-- );
--
-- 9、查询挂科超过两门(包括两门)的学生姓名和班级
-- 1.先找出所有小于60分的数据
-- 2.根据学生id分组 利用count筛选
SELECT
student.sname,
class.caption
FROM
class
INNER JOIN student ON class.cid = student.class_id
WHERE
student.sid IN (
SELECT
score.student_id
FROM
score
WHERE
score.num < 60 GROUP BY score.student_id HAVING count( score.course_id ) >= 2
);