"""
继承
多态与多态性
面向对象高级
装饰器
内置方法
反射(******)
元类
单例模式 什么是单例模式?????
异常处理
"""
# 面向对象
"""
面向过程编程
面向过程编程,核心是过程二字,过程就是解决问题的步骤 即先干什么再干什么最后干什么
基于该思想编程就好比在造一条流水线
优点:复杂的问题流程化从而简单化
缺点:可扩展性较差
面向对象编程
面向对象编程 核心是对象二字 对象即一系列相似的特征与技能的集合体
基于该思想编写程序就好比在创造一个世界,程序员就是这个世界的造物主
在造物主眼里一切皆对象
优点:可扩展性高
缺点:较于面向过程编程难度较高
"""
# 什么是类?:一系列对象相似的特征与技能的结合体
# 类你可以理解为就一个容器, 将产生的一堆名字放到这个容器中
# # python为了提供了获取容器对象内部属性或方法的固定用法 统一采用 句点符 .
# # 句点符的左边肯定是一个容器类型(里面存了一堆名字) # 模块
# print(User.school)
# print(User.func)
# 对象
#调用类实例化生成的叫做对象,对象是一个具体的实在的东西,而类是一个抽象的不存在的概念
# 属性查找顺序
# 先从自身找,找不到然后会去产生它的类里面去找,然后再去类的父类的里面找,一层一层的往上找,
##直到找到我为止 找不到就报错
# 定义一个类你就把它看成是 一个新的数据类型
# l = [1,2,3,4,5,6]
# print(type(l))
##python 统一了类与类型的概念,一切皆对象,包括一个字典 一个字符串 一个列表 一个数 都是它所属的
##一个类调用之后产生的一个对象,只不过省略了调用类的过程
# 绑定方法
# 在类中定义的函数 叫方法 类可以直接来调用 但是需要手动传self参数
# 在没有被任何装饰器装饰的情况下 类中的方法是绑定给对象的
# 绑定:谁来调就将谁当做第一个参数自动传入
# 函数与方法区别
# 在调用函数和方法的区别在于 调用时是否会给你自动传参 如果自动传参那么就叫方法
# 如果不能自动传参 那么就叫函数
# 面向对象之 ==========封装
"""
致命三问:
什么是封装?
装:将一大堆名字装到一个容器中
封:隐藏起来 对内公开对外隐藏
为什么要有封装?
将复杂丑陋的接口隐藏起来,暴露给用户简单易操作的接口,还可以对这个接口的操作增加一系列限制条件
如何使用
"""
class User:
def __init__(self,name,age,gender):
self.__name = name
self.__age = age
self.__gender = gender
def tell_info(self):
print('%s:%s:%s'%(self.__name,self.__age,self.__gender))
def set_info(self,name,age,gender):
if not isinstance(name,str):
print('名字必须是str类型')
return
if not isinstance(age,int):
print('age must be a number')
return
if not isinstance(gender,str):
print('gender必须是str类型')
return
self.__age = age
self.__gender = gender
obj = User('jason',18,'male')
obj.tell_info()
# obj.set_info(123,'male',666)
obj.set_info('egon',19,'male')
# print(obj.__name)
# obj.__sex = 'sexy'
# print(obj.__sex)
# 封装特点:
# 1.仅仅是语法层面上的变形 会将__属性名 变形成_类名__属性名
# 2,这种封装仅仅只在类的定义阶段有效
# 3.对内开放对外隐藏
'''
python类中定义的以__ 双下划线开头的属性或者变量 直接用类名或者对象名 加句点符是访问不到的,也就是被隐藏起来了,
实际情况是该变量的名字被做了一个变形,变成了 _类名__属性名
需要注意的是这种封装仅仅是在类的定义阶段有效,在其他阶段定义的这样的类名不会被改名
类内部依然可以访问到这个变量或者属性或者变量名
'''
# coding:utf-8
###面向对象之======继承
"""
什么是继承
继承是一种新建类的方式,继承的类称之为子类或派生类
被继承的类称之为父类或基类或超类
子类继承父类,也就意味着子类继承了父类所有的属性和方法
可以直接调用
为什么要有继承
减少代码冗余
如何使用
"""
class Parent1:
pass
class Parent2:
pass
class Son1(Parent1):
pass
# python中支持多继承
class Son2(Parent1,Parent2):
pass
# 如何查看类的父类
# print(Son1.__bases__)
# print(Son2.__bases__)
###pthon 中可以用这个__bases__查看一个对象或者一个类的父类
###但是没有方法或者语法可以查看一个类的子类
# 自定义的没有显示继承任何类的父类到底有没有偷偷继承某个类呢?
##这个问题就得探究一下新式类与经典类的区别了
# print(Parent1.__bases__)
# print(Parent2.__bases__)
"""
python2:一个类如果没有显示继承任何类的情况下,不继承任何类
python3:一个类如果没有显示继承任何类的情况下,默认都继承object类
经典类与新式类
经典类:
不继承object或者其子类的类 叫经典类
新式类:
继承object或者其子类的类 叫新式类
ps:经典类与新式类只在python2有区分
python3中只有新式类,没有经典类,
"""
# 派生:
# 在继承了父类的属性和方法的基础之上 自己定义了其他的属性和方法
# 如果派生出的方法与父类的同名了 那么相当于覆盖了父类的方法
# 子类方法中调用父类的方法:
# 方式1:指名道姓
# OldboyPeople.__init__(self,name,age,gender) 跟继承一毛钱关系都没有
# 方式2:跟继承有关系
# 单继承情况下的属性查找
'''
单继承的情况下,属性查找的顺序是从下到上,一层一层的往上找,直到找到为止,找不到就报错
'''
# 多继承情况下的属性查找:
'''
1,没有形成菱形结构也就是没有形成一个圈的时候:
从左到右,一个一个的找,一条分支找完之后,再退回上一个节点,找旁边的一个分支,找完之后再
退回上一个节点,找到为止,或者直到将所有的分支都找完也找不到,就报错
2,形成了菱形结构:
和没有形成菱形结构基本类似,也是按照从左到右的顺序一级一级的找,一个分支一个分支的找,
唯一的区别就是,最后那个汇总的总节点,在前面查找的时候不去查找,在查找到最右边的一个分支的
时候,再去查找,
注意:这个菱形继承最上面的那个类不能是object 类 如果最上面的那个类是object类 那么这个不能算是棱形继承
按照这个查找顺序形成的一个顺序表,叫做mro列表,形成这个列表所采用的算法,叫做C3算法
也就是这个查找顺序
'''
class D:
pass
class E:
pass
class F:
pass
class A(D):
pass
class B(E):
pass
class C(F):
pass
class G(A,B,C):
pass
"""
[G A D B E C F]
[<class '__main__.G'>, <class '__main__.A'>, <class '__main__.D'>,
<class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>,
<class '__main__.F'>, <class 'object'>]
"""
# print(G.mro())
# # super是严格按照mro列表的顺序调用父类的方法的!!!
###举例应用:
###json 序列化本来是不支持时间数据格式的
###这里我们自己定义一个类 做适当的修改,就可以变得支持时间格式了,
# 也就是采用继承的思想,具体做法如下:
from datetime import datetime,date
import json
d ={'name':'jason','password':'123'}
res = {"t1":datetime.today(),'t2':date.today()}
class MyCustomerJson(json.JSONEncoder):
def default(self, o):
if isinstance(o,datetime):
return o.strftime('%Y-%m-%d %X')
elif isinstance(o,date):
return o.strftime('%Y-%m-%d')
else:
return super().default(self,o)
print(json.dumps(res,cls=MyCustomerJson))
# TypeError: Object of type 'datetime' is not JSON serializable
# 面向对象之====>多态与多态性
"""
什么是多态
一种事物的不同形态(动物:人,狗,猫),代码层面上来说其实就是继承
为什么要有多态
多态仅仅是一个概念
多态性:在不需要考虑对象具体类型的情况下 调用对象的方法
如何使用
"""
# 多态性能够实现的基础是什么
class Animal:
def talk(self):
pass
class People(Animal):
def jiao(self):
print('hello')
class Dog(Animal):
def wang(self):
print('wangwang')
class Cat(Animal):
def miao(self):
print('miaomiao')
p = People()
d = Dog()
c = Cat()
p.talk()
d.talk()
c.talk()
import abc
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod
def talk(self):
pass
class People(Animal):
def talk(self):
print('hello')
class Dog(Animal):
def wang(self):
print('wangwang')
class Cat(Animal):
def miao(self):
print('miaomiao')
people = People()
####注意:以后我们写装饰器要这样写,这样才是标准的写法
from functools import wraps
def outer(func):
@wraps(func)
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner
@outer # func = outer(func)
def func():
pass
print(func)
#
class People:
def talk(self):
pass
class Dog:
def talk(self):
pass
class Cat:
def talk(self):
pass
#
'''
# python推崇鸭子类型
# 只要你长得像鸭子 走路像鸭子 说话像鸭子 那么你就是鸭子
# 写面条版程序
# 写函数版本的程序
# 面向对象编程
###我们写程序,最开始就是在一个文件下面,从上到下写,面条版程序,后来,我们学习了函
# 数,然后我们就把实现某一个固定功能的一个代码段封装成一个函数,这就有了函数版本
# 的程序,后来学了面向对象,我们将一些功能函数和属性变量封装起来,这就有了面向对象编程
#此外,我们还学习了模块与包的导入,将特定的功能和函数放置在一个包中,这样使得大大降低了代码的
#冗余,使得程序结构更加的清晰
'''