今日内容
序列化模块
json模块
json是一种通用的数据传输格式,本质就是一个字符串.
序列化(dump/dumps)和反序列化(load/loads)
import json
dic = {'北京':{'朝阳':{},'海淀':{}}}
text= json.dumps(dic,ensure_ascii=False) # 序列化的过程 把字典/其它数据类型转换成字符串
# 如果字典中有中文,希望写入文件的数据也显示为中文,就需要添加参数ensure_ascii=False
print(text)
with open('city',mode = 'w',encoding='utf-8') as f:
f.write(text)
with open('city',encoding='utf-8') as f:
str_d = f.read()
print(str_d)
dic = json.loads(str_d)
print(dic)
//和文件操作时dump和load方法可简化步骤
import json
lst = ['alex',1,2,3]
with open('file','w',encoding='utf-8') as f:
json.dump(lst,f)
import json
with open('file',encoding='utf-8') as f:
ret = json.load(f)
print(ret)
pickle模块
pickle和json的区别
pickle 支持python中的几乎所有数据类型,但是只能python一种语言中使用
json 支持所有的语言,但只支持有限的数据类型
import pickle
dic = {'北京':{'朝阳','昌平'},('天津','河北'):[1,2,3]}
ret = pickle.dumps(dic)
print(ret)
d = pickle.loads(ret)
print(d)
with open('pickle_file','wb') as f:
pickle.dump(dic,f)
with open('pickle_file', 'rb') as f:
ret = pickle.load(f)
print(ret)
面向对象
初识面向对象
什么是类? 一系列具有相同属性和相似方法的事物的抽象
什么是对象? 一个带有具体属性值的类的实例
什么是实例化? 通过类创造对象的过程
面向对象语法
class Person: # Person是类
def __init__(self,name,hp,ad,sex,job):
self.username = name
self.hp = hp
self.ad = ad
self.sex = sex
self.job = job
alex = Person('alex',100,5,'不详','乞丐') # alex是对象 这是实例化的过程
class Person:
def __init__(self,name,hp,ad,sex,job):
self.username = name
self.hp = hp
self.ad = ad
self.sex = sex
self.job = job
class Dog:
def __init__(self,name,kind,hp,ad): # 初始化方法
self.name = name
self.kind = kind
self.hp = hp
self.ad = ad
def bite(self,person):
person.hp -= self.ad
print('%s咬了%s,%s掉了%s点血'%(self.name,person.username,person.username,self.ad))
# 谁在类的外部调用了这个方法,方法中的第一个self参数就是谁
alex = Person('alex',100,5,'不详','乞丐')
旺财 = Dog('旺财','teddy',2000,300)
二饼 = Dog('二饼','哈士奇',10000,500)
二饼.bite(alex) # Dog.bite(二饼,alex)
print(alex.hp)
class Fruits:
discount = 0.8 # 折扣 # 类变量 静态变量
def __init__(self,name,price): # 实例方法 初始化方法
self.name = name # 实例变量 属性
self.pri = price
self.price = Fruits.discount * self.pri
def attack(self):pass # 自定义实例方法
def bite(self):pass # 自定义实例方法
apple = Fruits('苹果',5)
banana = Fruits('香蕉',7)
栗子 = Fruits('栗子',4)
李子 = Fruits('李子',10)
pear = Fruits('梨',2)
print(apple.price)
print(李子.price)
print(apple.pri * Fruits.discount)
print(pear.pri * Fruits.discount)
# 类名一共有三个作用:
# 可以调用类中的变量 Fruits.discount
# 实例化创建一个对象 Fruits('苹果',5)
# 调用一个方法(现在不常用):类名.方法名()
# 对象名
# 查看对象的属性 对象名.属性
# 调用对象的方法 对象名.方法名()
# 类和对象和实例和实例化
# 什么是类 ? Dog Person Fruits
# 什么是对象 ? alex 二饼 旺财 苹果 李子
# 什么是实例 ? 对象就是实例
# 实例化 是一个动词 类创造实例的过程叫做实例化
# 对象 = 类名() 实例化
class A:
# 静态变量 = '值'
def __init__(self,属性):
self.属性名 = 属性
def show(self):
print('展示一下所有的属性')
a = A('参数') # 对象a\
print(a.静态变量) # 对象可以引用类的命名空间中的内容 包括方法和静态变量
# 类的命名空间中
# 静态变量
# 方法
# 对象的命名空间中
# 对象指针
# 实例变量/对象的属性
class Person:
sum = 0 # 全家人的工资总和为0
def __init__(self):
self.salary = 1000
# 一家人
father = Person()
mother = Person()
mother.age = 18
print(mother.age)
# print(mother.sum)
# print(mother.salary)
Person.sum += mother.salary # 用对象修改静态变量只要用到赋值,相当于在自己的空间中新建
print('-->',mother.sum)
print('person -->',Person.sum)
Person.sum += father.salary
print('-->',father.sum)
print('-->',mother.sum)
print('person -->',Person.sum)
例题:
写一个类 ,统计一共实例化了多少个变量?
class Person:
count = 0
def __init__(self):
Person.count +=1
alex = Person()
print(alex.count,Person.count)
wusir = Person()
print(alex.count)
print(wusir.count)
print(Person.count) # 2
class A:
num = 0
def __init__(self):
self.num += 1
a1 = A()
a2 = A()
a3 = A()
print(A.num) # 0
print(a1.num,a2.num,a3.num) # 1
class A:
lst = []
def __init__(self):
self.lst.append(1)
a1 = A()
a2 = A()
a3 = A()
print(A.lst)
print(a1.lst)
print(a2.lst)
print(a3.lst)
class A:
lst = []
def __init__(self):
self.lst = [1]
a1 = A()
a2 = A()
a3 = A()
print(A.lst)
print(a1.lst)
print(a2.lst)
print(a3.lst)
class A:
lst = [0]
def __init__(self):
self.lst[0] += 1
a1 = A() # [1]
print(A.lst)
a2 = A() # [2]
print(A.lst)
a3 = A() # [3]
print(A.lst)
print(a1.lst)
print(a2.lst)
print(a3.lst)
# 操作静态变量的时候
# 如果是查看用类或者对象都可以
# 如果是修改 只用类名进行修改
# 不要在对象的空间中创建一个和类变量同名的实例变量
class Student:
'''
这是一个学生类,描述了学生的选课和查看分数的行为
'''
def __init__(self,id,name,sex,phone):
self.id = id
self.name = name
self.sex = sex
self.phone = phone
self.course_lst = []
def choose_course(self):
print('选择课程')
def show_score(self):
print('查看分数')
print(Student.__dict__) # __dict__ 内置的属性 可以查看类或者对象的命名空间中存储了什么
老王 = Student(1,'老王','male','110119120999')
print(老王.__dict__)
组合
from math import pi
class Circle:
def __init__(self,r):
self.r = r
def area(self):
return self.r**2*pi
def perimeter(self):
return 2*self.r*pi
# 圆环类型
# 属性 :大圆半径 小圆半径
# 实现计算面积
# 计算周长
class Ring:
def __init__(self,outer_r,inner_r):
c1 = Circle(outer_r)
c2 = Circle(inner_r)
self.outer = c1 # 如果一个属性和一个对象联系在一起 组合
self.inner = c2
def area(self):
return self.outer.area() - self.inner.area()
def perimeter(self):
return self.outer.perimeter() + self.inner.perimeter()
# r1 = Ring(10,5)
# print(r1.area())
# print(r1.perimeter())
class Ring:
def __init__(self,outer_r,inner_r):
self.outer_r = outer_r
self.inner_r = inner_r
def area(self):
o_area = self.outer_r**2 * 3.14
i_area = self.inner_r**2 * 3.14
return o_area - i_area
def perimeter(self):
return self.outer_r*2*3.14 + self.inner_r*2*3.14
组合练习
# 学生 : 姓名 性别 年龄 所学习的课程
class Student:
def __init__(self,name,sex,age,course):
self.name = name
self.sex = sex
self.age = age
self.course = course
class Course:
def __init__(self,cname,period,price):
self.name = cname
self.period = period
self.price = price
php = Course('php','5 months',18000)
python = Course('python','6 months',19800)
go = Course('go','5 months',8999)
tang = Student('汤青松','不详',80,python)
print(python.price)
print(tang.course.price)
wang = Student('老王','不详',80,'php')
tang.course = python
wang.course = python
print(tang.course.price)
print(wang.course.price)
python.price = 21800
print(tang.course.price)
print(wang.course.price)
class Student:
def __init__(self,name,sex,age,course_price,course_period,course_name):
self.name = name
self.sex = sex
self.age = age
self.course_price = course_price
self.course_period = course_period
self.course_name = course_name
tang = Student('汤青松','不详',80,19800,'5 months','python')
wang = Student('老王','不详',80,19800,'5 months','python')
print(tang.course_name)
print(wang.course_name)
wang.course_price = 21800
tang.course_price = 21800
class A:
def __init__(self,name):
self.name = name
a = A('alex Li')
# a是对象,是A的对象
a.name # 是对象a的属性
# a.name是个字符串'alex Li'
# 'alex Li'是str的对象
'alex Li'.split(' ')
a.name.split(' ')
继承
class Animal:
def __init__(self,hp,ad,name):
self.hp = hp
self.ad = ad
self.name = name
def eat(self):
print('%s执行我啦'%self.name)
self.hp += 5
class Person(Animal):
def __init__(self,name,hp,ad,sex,job):
self.sex = sex # 人特有的
self.job = job # 人特有的
Animal.__init__(self, hp, ad, name)
def attack(self,dog):
dog.hp -= self.ad
print('%s攻击了%s,%s掉了%s点血'%(self.name,dog.name,dog.name,self.ad))
class Dog(Animal):
def __init__(self,name,kind,hp,ad): # 初始化方法
Animal.__init__(self,hp,ad,name)
self.kind = kind # kind是狗特有的
def bite(self,person):
person.hp -= self.ad
print('%s咬了%s,%s掉了%s点血'%(self.name,person.name,person.name,self.ad))
二饼 = Dog('二饼','哈士奇',3000,150)
print(二饼.__dict__)
alex = Person('alex',100,5,'不详','乞丐')
print(alex.__dict__)
# A和B类都需要调用相同的方法
# 创建父类C,把相同的方法放到C类中
# A和B继承C A(C) B(C)
# A的对象和B的对象就可以直接调用C中的方法了
# A和B中有相同的方法,一部分功能相同,还有不同的部分
# 创建父类C, 把相同的部分放到C类的方法中
# 在A\B中保留不同的部分,
# 然后分别在A\B中调用C类的方法即可
# 序列化
# json
# json类型 : '{"key":[1,2,3]}'
# 所有语言通用的\支持的数据类型有限
# 序列化的结果是字符串 : 可视化
# json不支持多次dump
# pickle
# python自己用\支持python中几乎所有的数据类型
# 结果是二进制 :看不懂的
# pickle天生支持多次dump和load
# 面向对象
# 类 class 类型
# 类变量
# 实例方法 __init__ attack bite
# 类指针 - 指向父类
# 对象
# 对象指针
# 实例变量 self.name slef.age
# 组合
# 一个对象作为一个属性
# self.course = python
# 继承
# class Foo:pass
# class Son(Foo):pass
# Son是子类\派生类 Foo是父类\超类\基类
# 继承的特点:
# 如果多个类都用到了相同的方法\属性
# 我们应该把这些共用的方法抽象到他们的父类中去
# 减少代码的冗余
# 先写子类的功能,发现重复才创建父类
# 子类自己没有某一个方法或者属性的时候用父类的
# 如果自己有 还像用父类的 在子类中直接调用父类的方法就可以了
super 语法
class Course:
course_lst = []
def __init__(self,name,period,price):
self.name = name
self.period = period
self.price = price
class Role:
def __init__(self,name):
self.name = name
def show_course(self):
for item in Course.course_lst:
print(item.name,item.period,item.price)
class Student(Role):
def __init__(self,name):
# Role.__init__(self,name)
# super(Student, self).__init__(name)
super().__init__(name) # super也可以帮助我们找到父类
self.courses = []
class Manager(Role):pass
python = Course('python','6 months',19800)
linux = Course('linux','5 months',17800)
Course.course_lst = [python,linux] # 所有的可选课程
m = Student('alex')
print(m.name)
m.show_course()
多继承
class A:
pass
def func(self):
print('in A')
class C(A):
pass
# def func(self):
# print('in C')
class B(A):
pass
# def func(self):
# print('in B')
class D(B):
pass
# def func(self):
# print('in D')
class E(C):
pass
# def func(self):
# print('in E')
class F(D,E):
pass
# def func(self):
# print('in F')
# f = F()
# f.func()
print(F.mro()) # 查看多继承中的继承顺序
# 顺序 遵循C3算法
# 重新认识super
# class D:
# def func(self):print('D')
# class C(D):
# def func(self):
# super().func()
# print('C')
# class B(D):
# def func(self):
# super().func()
# print('B')
# class A(B,C):
# def func(self):
# super().func()
# print('A')
# a = A()
# a.func()
# b = B()
# b.func()
# 在单继承中 super的作用就是找父类
# 在多继承中 super是找mro顺序的下一个类
object
# object类
# 在python3.x的所有类都是object的子类
# 所以对于一些内置的方法会写在object类中
# 如果子类不定义,在调用的时候最终会调用object类中的方法
# 就不会让程序出现不必要的错误了
# __init__方法就是其中的一个例子
# 所有继承了object类的类 ---- 新式类
# 在python2中 不继承object类的都是 经典类
# class A(object):
# pass # 新式类
# class A:
# pass # 经典类 :在多继承中遵循深度优先
# 经典类中没有super和mro方法
# 把面向对象的基础知识掌握之后才来深入的了解复杂的继承关系
# 所有的py3中 的类都继承object 是新式类
# 在继承中 遵循 广度优先的 C3算法
# 也可以使用mro来查看继承顺序
# super这个方法 可以帮助我们查找到mro顺序中的下一个类
封装
# 三大特定 : 继承 封装 多态
# 封装
# 人狗大战
# 规范的创建对象
# 创建的所有人的属性名都能一致
# 把所有的方法装进一个角色中
# 广义上的封装 : 把方法和变量都封装在类中
# 在类的外部就不能直接调用了
# 狭义上的封装 : 在类的外部干脆不能调用了
class Student:
def __init__(self,name):
self.__name = name # 把name这个属性私有化了
def get_name(self):
return self.__name
def set_name(self,value):
if type(value) is str:
self.__name = value
老王 = Student('老王')
print(老王.get_name())
老王.set_name(1010101010100010)
print(老王.get_name())
print(老王.__name)
class Person:
def __init__(self,username,password):
self.username = username
self.__password = password
p = Person('alex','alex3714')
print(p.username)
class A:
__val = []
def __init__(self):
print(A.__val)
A()
print(A.__val)
class A:
def func(self):
self.__aaa()
def __aaa(self):
print('aaa')
a = A()
a.func()
# 在类的内部 ,实例变量(对象属性)可以变成私有的,类变量可以变成私有的,实例方法也可以变成私有的
# 一旦变成私有的就只能在类的内部使用,而不能在类的外部使用了
# 私有化到底是怎么做到的 :只是在类内部使用的时候对名字进行了包装 变成了_类名xxxx
# class B:
# __abc = 123 # _类名xxxx
# print(__abc) # 使用 都会由这个类进行一个变形 _类名xxxx
# print(B.__dict__)
# print(B.__abc)
# 私有的变量不能被继承
class A:
def __func(self): # _A__func
print('in A')
class B(A):
def wahaha(self):
self.__func() # _B__func
b = B()
b.wahaha()
# 毕业练习题
class A:
def __init__(self):
self.__func() # self._A__func
def __func(self): # _A__func
print('in A')
class B(A):
def __func(self): # _B__func
print('in B')
b = B()
# 在哪个类中调用方法,就在这个私有方法之前加上这个类中的变形
# 和self本身是谁的对象都没有关系
面向对象的装饰器
class Student:
def __init__(self,name,birth):
self.name = name
self.birth = birth
@property # 将一个方法伪装成属性
def age(self):
import time
return time.localtime().tm_year - self.birth
alex = Student('alex',1930)
print(alex.age) # 名词
class Circle:
def __init__(self,r):
self.r = r
@property
def area(self):
return 3.14*self.r**2
@property
def perimeter(self):
return 2*3.14*self.r
c = Circle(10)
print(c.area)
print(c.perimeter)
classmethod和staticmethod
class Student:
def __init__(self,name):
self.name = name
@staticmethod # 声名login方法是一个静态方法 ,不必传任何默认的参数
def login(flag):
print('登录程序',flag)
username = input('>>>')
stu = Student(username)
return stu
# 要想调用login 必须先有对象
# 要想创建对象 必须用户先输入名字
# 得调用登录之后才开始input
# 不必实例化就可以调用的login方法 不需要传递对象作为参数,就定义这个方法为静态方法
obj = Student.login(flag = True) # 用类名可以直接调用这个方法了
print(obj.__dict__)
class Manager:
def __init__(self,name):
self.name = name
@classmethod # 装饰当前这个方法为一个类方法,默认传参数cls,表示当前所在的类名
def login(cls):
username = input('>>>')
stu = cls(username)
return stu
obj = Manager.login() # 用类名可以直接调用这个方法了
print(obj.__dict__)
class A:
def func(self): pass # 实例方法 self作为默认参数,需要用对象来调用
@classmethod
def func1(cls): pass # 类方法 cls作为默认参数,可以用类名来调用
@staticmethod
def func1(): pass # 静态方法方法 没有默认参数,可以用用类名来调用
内置方法
# 凡是数据类型 都会或多或少带有一些 双下方法
# __xxxx__ 魔术方法 内置方法
# 调用的时候总是不好好调用
# 'abc'.split('b') # 正经调用str类型的split方法
# ret = 'abc'.__add__('efg')
# print(ret)
# print('abc' + 'edf')
# __str__
class Course:
course_lst = []
def __init__(self,name,period,price):
self.name = name
self.period = period
self.price = price
def __str__(self):
return '%s,%s,%s'%(self.name,self.period,self.price)
# python = Course('python','6 months',19800)
# linux = Course('linux','5 months',17800)
# Course.course_lst = [python,linux]
# for course in Course.course_lst:
# print(course) # 打印一个对象总是打印内存地址,这个数据对我们来说没有用
# 打印这个对象的时候查看这个对象的相关信息
# print(obj) 打印一个对象 总是调用obj.__str__(),打印的是这个方法的返回值
__new__
class A(object):
def __new__(cls, *args, **kwargs): # 构造方法 开辟空间 构造对象的方法
obj = object.__new__(cls)
return obj
def __init__(self): # 初始化方法
print('init : ',self)
self.name = 'alex'
# 1.创建一块空间 : __new__
# 2.调用init
# A()
# 算法导论 - 微观
# 23个设计模式 - 宏观
# java语言
# 单例模式 - 只创建一个实例
# class A:
# pass
#
# a1 = A()
# a2 = A()
# print(a1)
# print(a2)
class Singleton:
__instance = None
def __new__(cls, *args, **kwargs):
if not cls.__instance:
obj = object.__new__(cls)
cls.__instance = obj
return cls.__instance
def __init__(self,name):
self.name = name
obj1 = Singleton('alex')
obj2 = Singleton('wusir')
print(obj1.name,obj2.name)
# 什么是单例模式?
# 怎么实现
# 用new实现
# new做什么用 在什么时候执行
反射
# 什么是反射
# 通过字符串使用变量(包括 类 函数 方法 各种变量)
# 如果有一个变量名 是字符串数据类型的 你能获取到这个变量的值么?
class Student:
def __init__(self):
self.name = 'alex'
self.age = 80
self.gender = 'male'
def show_info(self):
print('%s,%s'%(self.name,self.age))
stu = Student()
content = input('>>>')b
if hasattr(stu,content):
name = getattr(stu,content) # stu.show_info name=showinfo的地址
if callable(name):
name()
else:
print(name)
if content == 'name':
print(stu.name)
elif content == 'age':
print(stu.age)
elif content == 'gender':
print(stu.gender)
# 对象的反射
# hasattr(对象,'属性名') 判断对象是否有这个属性,有返回True
# getattr(对象,'属性名') 返回对象中属性名对应的值
# 反射属性
# val = getattr(对象,'属性名')
# val就是属性的值
# 反射方法
# val = getattr('对象','方法名')
# val就是方法的地址
# val() ==> 调用方法
# 类的反射
class A:
role = 'China'
print(getattr(A,'role')) # 用类获取类的变量
# 模块的反射
import time
print(time.time())
print(getattr(time,'time')())
# 反射
a.b ===== getattr(a,'b')
name = 'alex'
age = 84
def func(*args):
print('wahaha')
class Student:pass
import sys
print(getattr(sys.modules[__name__],'name'))
print(getattr(sys.modules[__name__],'age'))
getattr(sys.modules[__name__],'func')(1,2,3)
print(getattr(sys.modules[__name__],'Student'))
反射的作用
class Studnet:
opt_lst = [('查看可选课程', 'show_courses'),
('选择课程', 'choose_course'), ('查看已选课程', 'show_selected_course')
, ('退出', 'quit')]
def __init__(self,name):
self.name = name
self.courses = []
def show_courses(self):
print('查看一共有多少门课程')
def choose_course(self):
print('选择课程')
def show_selected_course(self):
print('查看已经选择的课程')
def quit(self):
print('退出')
stu = Studnet('alex')
for index,opt in enumerate(Studnet.opt_lst,1):
print(index,opt[0])
num = int(input('请输入您要选择的操作序号:'))
if hasattr(stu,Studnet.opt_lst[num-1][1]):
getattr(stu,Studnet.opt_lst[num-1][1])()
# 选课系统
# 改进 反射
# classmethod/staticmethod装饰器
模块和包
# 模块
# 什么是模块?
# py文件
# 自定义模块 把多行代码拆成多个文件 使得代码更加严谨清楚
# 导入模块的话
# from 模块 import 变量
# import 模块
# 模块.变量访问变量的值
# 导入包
# from 包.包.包 import 模块
# 模块.xxx直接获取值
# import 包.包.模块
# 包.包.模块,xxx获取值
# 无论是导入模块还是包,必须要保证被导入的模块和包所在路径在sys.path的列表中
logging模块
# import logging
# fh = logging.FileHandler(filename='xxx.log',encoding='utf-8')
# fh1 = logging.FileHandler(filename='xxx2.log',encoding='utf-8')
# sh = logging.StreamHandler()
# logging.basicConfig(level=logging.INFO,
# handlers=[fh,sh,fh1],
# datefmt='%Y-%m-%d %H:%M:%S',
# format='%(asctime)s - %(name)s[%(lineno)d] - %(levelname)s -%(module)s: %(message)s')
# logging.debug('debug message') # 情况越轻
# logging.info('info message') # 信息类的日志
# logging.warning('warning message')
# logging.error('error message')
# logging.critical('critical message')
# logging日志分为5个等级
# 默认只显示warning等级以上的信息
import logging
from logging import handlers
sh = logging.StreamHandler()
rh = handlers.RotatingFileHandler('myapp.log', maxBytes=1024,backupCount=5)
fh = handlers.TimedRotatingFileHandler(filename='myapp2.log', when='s', interval=5, encoding='utf-8')
logging.basicConfig(level=logging.INFO,
handlers=[rh,fh,sh],
datefmt='%Y-%m-%d %H:%M:%S',
format='%(asctime)s - %(name)s[%(lineno)d] - %(levelname)s -%(module)s: %(message)s')
while True:
logging.WARNING('')
异常处理
opt_lst = [1,2,3,4]
try:
num = int(input('请输入序号 :'))
print(opt_lst[num-1])
except ValueError:
print('请输入一个数字')
except IndexError:
print('请输入1-4之间的数字')