day08 面向对象进阶
在 用户\AppData\Roaming\Typora
按照修改日期排序
删除最近修改的那些文件
内容回顾
# 序列化
# 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语法
# py2 和 py3 – 继承顺序
# 封装
# 私有的概念
# property \classmethod \staticmethod
# 双下方法
# new
# str
# 反射
# 模块
# 模块的导入
# 包的导入
# 项目名称
pickle和json
dic1 = {‘k1’:‘v1’}
dic2 = {‘k2’:‘v2’}
import json
import pickle
# with open(‘file’,‘w’) as f:
# # ‘{“k1”: “v1”}’ + ‘\n’
# json.dump(dic1,f)
# json.dump(dic2,f)
# with open('file','rb') as f:
# ret1 = pickle.load(f)
# ret2 = pickle.load(f)
# print(ret1)
# print(ret2)
with open('file','w') as f:
ret = json.dumps(dic1)
f.write(ret+'\n')
ret = json.dumps(dic2)
f.write(ret + '\n')
with open('file','r') as f:
for line in f:
line = line.strip()
if line:
dic = json.loads(line)
print(dic)
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
有很多xxx方法
init方法也在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本身是谁的对象都没有关系
多态
在python中处处是多态
# 在python中处处是多态
# def func(int a,int b,int c):
# pass
# java是比较严谨的,所有在传递参数的时候必须指定参数的类型才可以
# class User:pass
# class Student(User):pass
# class Manager(User):pass
#
# def change_pwd(person):
# pass
# 希望指定的类型 既能够保证 学生对象能传进来 管理员也能传进来
# print(type('123'))
# alex = Manager()
# print(type(alex))
# 周老板 = Student()
# print(type(周老板))
# User这个类可以表现出多种状态 :学生的状态 管理员的状态
面向对象的装饰器
# 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做什么用 在什么时候执行
# new方法是开空间用的,在init之前执行
反射
# 什么是反射
# 如果有一个变量名 是字符串数据类型的 你能获取到这个变量的值么?
# 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(‘>>>’)
# 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'))
模块和包
# 模块
# 什么是模块?
# 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之间的数字’)
www.cnblogs.com/Eva-J/articles/7228075.html