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
posted @ 2020-03-05 13:05  赵刚、  阅读(137)  评论(0编辑  收藏  举报