Python - 面向对象
面向对象的优点day20:
1.对相似功能的函数,同一个业务下的函数进行归类分类
2.站在上帝的角度构建代码,类就是一个公共的模块.对象就是模板实例化出来的,得到了对象就得到了一切
面线对象的结构:
类的组成就两部分
1.属性(静态属性)
2.函数就是方法(动态方法)
# 面向对象:
# 类: 某一种东西的统称或概述
# 对象:对一个东西的具体描述
# 面向对象的优点:
# 1.结构清晰,可读性高
# 2.上帝思维
# 类的结构:
# class 类名(驼峰体):
# 静态属性(静态字段,类变量)
# 方法 (动态字段,动态属性)
# 查看类中所有内容
# 类名.__dict__
# 查看对象中所有内容
# 对象.__dict__
# 万能的点
# 增,
# 类名.变量名 = "值"
# 删,
# del 类名.变量名
# 改,
# 类名.变量名 = "值"
# 查
# 类名.变量名
# 类名() # 实例化一个对象
实例化一个对象发生的三件事
# 1.实例化一个对象,给对象开辟一个空间
# 2.实例化对象时自动执行__init__方法
# 3.将对象的参数地址传递给self 隐性传递,给对象封装属性
# self 是什么?
# self是一个方法中的位置参数
# self的名字给进行更改,但是不建议更改
# self 就是实例化对象的本身(self和对象指向的是同一个内存地址)
# 一个类可以实例化多个对象
# 对象空间之间是独立的
# 对象只能使用类中的属性和方法,不能进行修改
# 不建议使用类名操作方法
# 查找顺序:
查找顺序:
# 1.先找对象
# 2.创建对象的类
# 先找对象空间,空间中没有找实例化这个对象的类空间(对象中记录实例化这个对象的类地址)
类的关系day21
# 1.类空间
# 给类空间和对象空间添加属性
# 类外部,内部,方法中
所有的对象只能查询和使用类空间的属性 不能修改和变更
查询方式:
对象.名字: 对象空间 =>类对象指针 => 类空间 => 父类空间
类名.名字: 类空间 => 父类空间
# 2.类关系:
# 依赖:将一个类的对象当做参数传递给另一个类的方法中
# 组合:将一个类的对象封装到另一个类实例化的对象空间中
# self.g.f.eat() 一定是组合 (组合是咱们最常用的关系)
# 依赖关系和组合关系: 会用就行
# 函数嵌套
依赖关系:主从之分:将一个类名或者对象传入到另一个类的方法中
继承day22
初始继承:
B(A)如果B类继承了A类 B类就称为子类 派生类 A类就称为父类 基类 超类
面向对象的三大特性之一:继承 封装 多态
继承分为:单继承 多继承
继承的优点:1减少重复代码 2增加类之间的耦合性 3代码更加清晰,流畅
单继承
1.类名执行父类的属性方法: (就近原则) 当前类 => 当前类的父类 => 当前类的父类的父类
2.子类对象,执行父类的属性方法: 对象=> 实例化这个对象的类 => 当前类的父类 (单向不可逆:子类使用父类 的属性,父类不能使用子类的方法)
3.既要执行子类的方法也要执行父类的方法:
方法一: 不依赖继承的 =>思路就是函数的调用
# 在本类的__init__方法中,使用另一个类名的__init__方法进行初始化
# def __init__(self,name,age,sex):
# A.__init__(self,name,age)
# self.sex = sex
方法二:依赖于继承(用的比较多) super().__init__执行父类的方法,官方称为重构父类方法
# def __init__(self,name,age,sex): # 初始化方法
# super(本类,self).__init__(name,age)
# super().__init__(name,age) # 重构方法
# self.sex = sex
python类分为两种:1.经典类 2.新式类
python 2x :在python2.2之前都是经典类 python2.2之后,经典类与新式类共存
python 3x :全部都是新式类
经典类: 不继承object 类
新式类: 继承object 类
# 1.多继承day23
python类分为两种:1.经典类 2.新式类
python 2x :在python2.2之前都是经典类 python2.2之后,经典类与新式类共存
python 3x :全部都是新式类
经典类: 不继承object 类
新式类: 继承object 类
# 经典类:不继承object 类 深度优先 A(B,C,D) 从左向右进行继承
# 新式类: 继承object 类c3(mro)算法
# 类名.mro()
# mro(子类(父类1,父类2)) = [ 子类 ] + merge( mro(父类1), mro(父类2), [ 父类1, 父类2] )
# merge == 合并
# mro 只有新式类才能使用
# 2.封装 : 将一些代码或数据存储到某个空间中就是封装
# 3.多态 : Python默认就是多态
鸭子类型(编程思想)day24
鸭子类型:当看到一只鸟走起来像鸭子,游泳起来像鸭子,叫起来像鸭子,那么这只鸟就可以被称为鸭子
# class Str:
#
# def index(self):
# print("啊啊啊")
#
# def walk(self):
# print("一步两步")
#
# def do(self):
# print("左手右手一个慢动作")
#
# class List:
#
# def index(self):
# print("嗯嗯嗯")
#
# def walk(self):
# print("一步两步")
#
# def do(self):
# print("左手右手一个慢动作")
# a = A()
# b = B()
# a.call()
# b.call()
# 统一接口 ,归一化(规范)
# def call(object):
# object().call()
#
# call(B)
# call(A)
# python中 str,list,tuple中很多使用鸭子类型
# str.index()
# list.index()
# tuple.index()
类的约束
类的约束:控制子类定义一些方法
# 方法一: 推荐使用方法一
# raise : 主要抛出异常
# 方式一: (推荐并且常用的方式)
# raise 主动抛出异常(主动报错)
# class PayClass:
# def pay(self):
# raise Exception("你子类必须要写一个pay方法")
#
# class WechatPay(PayClass):
#
# def pay(self):
# print("微信支付")
# class AliPay(PayClass):
#
# def pay(self):
# print("支付宝支付")
# class QQpay(PayClass):
#
# def pay(self):
# print("QQ支付")
#
# # def pay(self):
# # pass
#
# def pay(object):
# object().pay()
# pay(QQpay)
# 方法二:
# from abc import ABCMeta,abstractmethod
# 抽象类,接口类:指定一些规则
from abc import ABCMeta,abstractmethod # 抽象类,接口类
# class PayClass(metaclass=ABCMeta): # 元类
# @abstractmethod
# def pay(self):
# raise Exception("你子类必须要写一个pay方法")
#
# class WechatPay(PayClass):
#
# def pay(self):
# print("微信支付")
#
# class AliPay(PayClass):
#
# def pay(self):
# print("支付宝支付")
#
# class QQpay(PayClass):
#
# def pay(self):
# print("QQ支付")
# def pay(object):
# object().pay()
# pay(WechatPay)
# pay(AliPay)
# pay(QQpay)
# qq = QQpay()
# qq.pay()
super
Python中的super()方法设计目的是用来解决多重继承时父类的查找问题,所以在单重继承中用不用 super 都没关系;但是,使用 super() 是一个好的习惯。一般我们在子类中需要调用父类的方法时才会这么用。
super()的好处就是可以避免直接使用父类的名字.主要用于多重继承
————————————————
# 按照mro的查找顺序进行查找
# super(类名,self) 从当前mro中查找类名的下一个类 类名是b 就找下一个
# super是按照mro的顺序进行继承
新式类查找不到顶 最后一次查找到顶
类的私有成员day25
类的私有成员:①私有类的静态属性 ②私有类的方法 ③私有对象的属性
类的私有成员
# 以__开头的变量就是私有的
# _desires = "有欲望" # (程序员之间约定俗成)类私有的属性
私有累的属性:只能在类的内部可以访问(在类的外部都不能访问,子类也不能)
私有成员来说:当你遇到重要的数据,功能(只允许本类使用的一些方法,数据)设置成私有成员
python所有的私有成员都是纸老虎,形同虚设(名被改了而已)
# 私有属性和方法在当前类中可以查看及使用
# 子类不能继承父类的私有方法和属性
# 私有的目的就是保护数据的安全性
# 类的私有属性
# 类的私有方法
# 对象的私有属性
# 强制查看私有方法或属性
# _类名私有变量名
# _类名私有方法名
类的其他成员
1.类的其他成员
# 实例方法
# 依赖对象,不需要装饰器装饰,方法的参数是self
# 类方法
# @classmethod : 依赖类 被classmethod装饰器装饰的方法参数是cls
一般都是类名去调用的方法并且自动将类名地址传递给cls 但如果通过对象调用也可以,但是传的地址还是类名地址!
类名作用:1.可以实例化对象
2.可以操作(修改)类的属性
# 静态方法
# @staticmethod : 不依赖对象和类 就是一个普通的函数(就是为了保证规范性,合理化,后续的维护性)
# 属性(组合)
# @property
# def bmi():
# pass
# @bmi.setter
# @bmi.getter
# @bmi.deleter
将执行一个函数需要函数名()变换成直接函数名
将动态方法 伪装成了一个属性,虽然在代码级别上没有什么提升,但是让你看起来更合理
方法伪装成了一个属性而已,本质还是方法
# 2.元类
# python大部分自带的类和自己定义的类都是由type类实例化出来的
# python中一切皆对象
# issubclass() # 判断参数1是不是参数2的子类
# isinstance() # 判断参数1是不是参数2的对象
# object 和 type 的关系
# object 是 type 的对象
# type 是 object 的子类
# 3.反射
# 通过字符串操作对象的属性和方法
# 1.对象的角度使用反射
# 2.类的角度使用反射
# 3.当前模块使用反射
# 4.其他模块使用反射
# 模块部分使用反射的方式:
# 方法一:
# import sys
# sys.modules[__name__]
# 方法二:
# globals()[__name__]
# hasattr(对象,字符串) 判断当前对象是否存在
# getattr(对象,字符串,查找不到的返回值)
# setattr(对象,字符串,值)
# delattr(对象,字符串)
# hasattr() 及 getattr() 配合使用
# if hasattr():
# getattr()
# 反射(组合) -- # 通过字符串操作对象的属性和方法
# getattr() # 获取
# setattr() # 设置
# hasattr() # 判断是否存在
# delattr() # 删除
# hasattr *****
# getattr *****
# setattr ***
# delattr **
双下方法day26
# 双下方法:给源码程序员使用,咱们慎用 (以便你们更好的阅读源码)
# __len__
# class A(object):
#
# def __init__(self,name):
# self.name = name
# print("触发了__init__")
#
# def __len__(self): # len() 触发
# print("走这里")
# return len(self.name) # return len("alex") str中__len__
# # 必须有返回值,返回值的类型必须是整型
#
# a = A("alexqrqwr")
# print(len(a))
# str
# a = "12345" # str这个类的实例
# lst = [1,2,3,4,4,5,5,5,5] # list这个类的实例
# print(len(a))
# print(len(lst))
# __hash__ hash()触发
# class A(object):
#
# def __init__(self,name,age):
# self.name = name
# self.age = age
#
# def __hash__(self): # hash()
# hash({1,2,345}) # 可变数据类,不可数据类型
# # 必须有返回值,返回值的类型必须是整型
#
# a = A("meet",25)
# print(hash(a))
# __str__ *** Django
# class A:
#
# def __init__(self,name,age,sex):
# self.name = name
# self.age = age
# self.sex = sex
#
# def __str__(self): # print 触发 str()
# print(111)
# return f"姓名:{self.name} 年龄:{self.age} 性别:{self.sex}"
# # 必须有返回值,返回值的类型必须是字符串
#
#
# a = A("meet",20,"男")
# a1 = A("meet11",200,"男11")
# str(a)
# print(a)
# print(a1)
# a = A("meet",20,"男")
# a1 = A("meet2",200,"女")
#
# print(f"姓名:{a.name} 年龄:{a.age} 性别:{a.sex}") # "姓名:meet 年龄:20 性别:男"
# print(f"姓名:{a1.name} 年龄:{a1.age} 性别:{a1.sex}") # "姓名:meet2 年龄:200 性别:女"
# __repr__
# class A:
#
# def __init__(self):
# pass
#
#
# def __repr__(self): # print触发 %r
# print(1111)
# return "日魔"
#
# def __str__(self): # str 优先级高于 repr 两个都存在就只执行str
# return "宝元"
#
# a = A()
# print("%r"%(a))
# __call__ *** 面试题
# class A:
#
# def __init__(self):
# pass
#
# def __call__(self, *args, **kwargs): # 对象()时调用的__call__
# print("走我")
# print(*args, **kwargs)
#
# a = A()
# a()
# __eq__ # 等于
# class A(object):
#
# def __init__(self,name,age):
# self.name = name
# self.age = age
#
# def __eq__(self, other): # a == a1
# if self.name == other.name:
# return True
# else:
# return False
#
# a = A("meet",56)
# a1 = A("meet",108)
#
# print(a == a1)
# __del__ 析构方法
# class A:
# def __init__(self):
# pass
#
# def __del__(self): del 触发
# print("删除时执行我")
#
# a = A()
#
# import time
# time.sleep(5)
# del a
# a = 1
# b = a
# a = b
# 垃圾回收
# 80 5/s
# 引用计数
# 标记清除
# 分袋回收 袋一:10 2/h 袋二: 5/3 4h 袋三: 3 20h
# __new__ 单例模式(面试必问) # 工厂模式 等等
# class A(object):
#
# def __init__(self,name): # 初始化
# self.name = name
# print("我是__init__,先走我")
#
# def __new__(cls, *args, **kwargs):
# obj = object.__new__(A)
# print("我在哪:",obj)
# return obj # obj == __init__()
#
# # print("我是__new__,先走我")
# # return "啦啦啦"
#
# a = A("meet")
# print("我是谁:",a)
# class A:
#
# def __init__(self):
# print(1111)
#
# a = A()
# print(a)
# class A(object):
#
# def __init__(self,name): # 初识化
# self.name = name
# def __new__(cls, *args, **kwargs):
# obj = object.__new__(A) # 调用的是object类中的__new__ ,只有object类中的__new__能够创建空间
# return obj #本质: obj == __init__() return __init__() # 触发了__init__方法
# # print("先执行的是我")
# # return "宝元"
# a = A("meet") # a是对象的内存地址
# a1 = A("日魔") # a是对象的内存地址
# a2 = A("朝阳") # a是对象的内存地址
# print(a.name)
# print(a1.name)
# print(a2.name)
# 先执行__new__方法在执行__init__方法
# class A:
# __a = None #__a = 0x000001F346079FD0
#
# def __init__(self,name,age):
# self.name = name
# self.age = age
#
# def __new__(cls, *args, **kwargs):
# if cls.__a is None:
# obj = object.__new__(cls)
# cls.__a = obj
# return cls.__a
#
# a = A("meet",123) # 0x000001F346079FD0
# a1 = A("日魔",11)
# print(a.name)
# print(a1.name)
# 单例模式:不管你创建多少次,使用的都是同一个内存空间
# 模块的导入,手写的单例模式
# 实例化对象时发生的事
# 1.创建对象,并开辟对象空间 __new__
# 2.自动执行__init__方法
# __item__ 可以向操作字典一样操作实例方法
# dic["键"] = 值
# del dic["键"]
# dic["键"]
# class A:
#
# def __init__(self,name,age):
# self.name = name
# self.age = age
#
# def __getitem__(self, item):
# print(self.__dict__)
# print(self.__dict__[item]) # self.__dict__ 获取的就是字典
#
# def __setitem__(self, key, value):
# self.__dict__[key] = value
#
# def __delitem__(self, key):
# del self.__dict__[key]
#
# a = A("meet",58)
# a["sex"] = "男"
# a["sex"]
# del a["sex"]
# print(a.__dict__)
# 了解一下上下文
# __enter__
# __exit__
# class my_open:
#
# def __init__(self,file,mode="r",encoding="utf-8"):
# self.file = file
# self.mode = mode
# self.encoding = encoding
#
# def __enter__(self):
# self.f = open(self.file,self.mode,encoding=self.encoding)
# return self.f
#
# def __exit__(self, exc_type, exc_val, exc_tb):
# print(exc_type,exc_val,exc_tb) # 没有错误时就是None
# self.f.close()
#
#
# with my_open("a.txt") as ffff:
# for i in ffff:
# print(i)
# print(ffff.read(1111))
# print(ffff.read())
# with open("a") as f: 使用了上下文
# 1.双下方法:
# ***
# __str__ : str() print
# __call__ : 对象()
# __new__ : 实例化时自动触发,先执行__new__在执行__init__ (面试手写单例模式)
# __len__ : len()
# __hash__: hash()
# __repr__: %r
# __eq__ : ==
# __del__ : del
# __item__ 系列 和字典操作一样
# __getitem__ : dic["键"]
# __setitem__ : dic["键"] = 值
# __delitem__ : del dic["键"]
# 2.异常处理:
# 错误:
# 1.语法错误
# 2.逻辑错误
# 常用异常:
# SyntaxError
# IndexError
# KeyError
# ValueError
# NameError
# TypeError
# StopIteration
# ImportError
# Exception
# 异常的编写结构
# try: #尝试
# int("alex") # 尝试运行的代码
#
# except ValueError as e: # 捕捉异常
# print(e) # 显示异常
# 异常处理:
# 1.防止程序中断运行
# 2.出现异常,程序终止用户体验不良好
# 异常的处理方式:
# 1.if (避免出现报错) if可以进行异常处理,但是只能针对某一段代码.
# 2.try(捕捉错误) 可以捕获异常,保证程序不中断运行
# 分支:
# try:
# num = int(input("请输入数字:"))
# lst = [1,2,3]
# # dic = {"name":"meet",1:"rimo"}
# # print(dic[num])
# print(lst[num])
#
# except ValueError as e:
# print(e)
#
# except KeyError as e:
# print(f"没有{e}这个键")
#
# except IndexError as e:
# print(e)
#
# except Exception as e:
# print(e)
# 分支 + else
# try:
# num = int(input("请输入数字:"))
# lst = [1,2,3]
# # dic = {"name":"meet",1:"rimo"}
# # print(dic[num])
# print(lst[num])
#
# except ValueError as e:
# print(e)
#
# except KeyError as e:
# print(f"没有{e}这个键")
#
# except IndexError as e:
# print(e)
#
# except Exception as e:
# print(e)
#
# else:
# print("没有异常走我")
# 分支 + else + finally
# try:
# num = int(input("请输入数字:"))
# lst = [1,2,3]
# # dic = {"name":"meet",1:"rimo"}
# # print(dic[num])
# print(lst[num])
#
# except ValueError as e:
# print(e)
#
# except KeyError as e:
# print(f"没有{e}这个键")
#
# except IndexError as e:
# print(e)
#
# except Exception as e:
# print(e)
#
# else:
# print("没有异常走我")
# finally:
# print("清理工作")
# assert 断言
# 推荐:使用try,但是不建议在任意位置添加try