类的定义与使用(类也可以看做成一个容器)
类在定义的时候定义阶段就会执行类体的代码,属于类的局部名称空间外界无法直接调用。
类名加括号就会产生对象,并且每执行
类的定义与使用(类也可以看做成一个容器)
类在定义的时候定义阶段就会执行类体的代码,属于类的局部名称空间外界无法直接调用。
类名加括号就会产生对象,并且每执行一次都会产生一个全新的对象(内存地址都不一样)。
数据和功能也可以叫属性,数据就是属性名、功能就是方法
对象.__dict__查看对象和类里面的名称空间
对象独有的数据
对象公共的数据:类和对象谁都可以调用(都是都可以拥有的)
专门给学生添加独有数据的功能,类产生对象的过程中自动触发(产生对象就是传要的参数)
对象公共的功能:对象的独有功能,类要调用比较麻烦(类调用需要自己传参数)
对象独有的功能
对象调用类里面的功能函数会自动将对象自己当做第一个参数传进去
当对象点的名字已经存在的情况下会修改这个名字的值
当对象点的名字不存在的情况下则新添数据
类里面的函数动静态方法(@classmethod和@staticmethod)
1.类中直接定义函数,默认绑定给对象,类调用有几个参数就传几个,对象调用第一个参数就是对象本身
2.被@classmethod修饰的函数,默认绑定给类,类调用第一个参数就是类的本身,对象也可以调用并且会自动将产生该对象的类当做第一个参数传入
3.@staticmethod普普通通的函数无论类函数对象调用,都需要自己手动传参
面向对象之继承的概念
面向对象的三大特性(封装、继承、多态)
继承的使用(就是继承一个类或者函数所有的功能)
在定义类的时候类名后面加括号,括号里面填写其它类名就是继承了这个类的功能使用(可以继承多个类,括号内类名之间用括号隔开)
一些小知识(继承其它的类叫子类或者派生类)被继承的类叫(父类、基类、超类)
继承的本质
对象的话:数据与功能的结合体
子类的话:多个对象相同数据和功能的结合体
父类的话:多个类(子类)相同数据和功能结合体
就是将多个类相同的东西抽出去形成一个新的类
将多个类继承刚刚抽取出来的新的类
类的操作顺序(包括继承)
没有的继承下类的查找顺序
先从自己(对象)的名称空间查找,然后去产生该对象的类中查找,没有的话报错
单继承查找的顺序
先找自己(对象)的名称空间,去产生对象的类去找,去这个类的父类去找
多继承情况下的查找顺序
菱形继承:广度优先(最后才会找闭环的定点)父类(从左往右)依次查找
第一步肯定是从对象自己找起来
非菱形继承:深度优先(从左往右每条道走完为止)一条支线走完才走另一条
补充点:mro()方法可以直接获取名字的查找顺序print(对象.mor())
经典类与新式类
经典类:不继承object或者其子类的类(在python2中有经典类和新式类)
新式类:继承object或者其子类的类(在python3中只有新式类(所有类默认都继承object))
注意以后我们在定义类的时候,如果没有其他明确的父类,也可能习惯写object兼容
派生方法(子类继承父类的方法然后在中间做一些修改不影响正常使用)
子类基于父类某个方法做了扩展
super().init(继承父类里的方法) 这个就是子类调用父类的方法
class MyList(list):
def append(self, values)
if values == 'jason':
reyirn
super().append(values)
更改了list的append方法然后又继承listappend的方法在中间做一些判断
派生方式的使用(继承某个类的,重写被继承类里面的某个方法,在方法里面添加一些额外操作或者限制,最后利用super重新调用被继承类里面的方法)
json序列化(里外都需要是能被序列化的内容)
查看dumps源码
能够被序列化的类型
这个函数报错的源头
第一种解决方法直接把内容变成字符串
第二种派生方法(做父类的扩展然后在返回父类中派生方法的使用原理)
面向对象三大特性之封装
封装:就是将数据和功能'封装'起来
隐藏:将数据和功能隐藏起来不让用户直接调用,而是开发一些接口间接调用
隐藏
在编写面向对象代码类的定义时,也会看到很多单下划线开头的名字,表达的意思通常特使不要直接访问,而是查找一下下面可能定义的接口
接口
伪装:将类里面的方法伪装成类里面的数据,通过装饰器(@property)把函数(功能通过点的方法使用不用加括号),@被装饰的函数名.setter,作用是在设定值之前进行类型检查,通过类型检查后,将值value存放到真实的位置隐藏的功能中,@被装饰的函数名.deleter删除这个被装饰的函数隐藏的属性
注意点,只能有self这一个参数有其它参数就使用不了伪装
三大特性之多态
多态:一种事物的多种形态
面向对象中多态意思是,一种事物可以有多种形态但是针对相同的功能应该定义相同的方法
这样无论我们拿到的是哪个具体的事物,都可以通过相同的方法调用功能(比如硬盘,文件都可以读写然后用相同的功能)
有强迫性的让你必须有相同的功能才能使用
导入模块 import abc
class 类名(metaclass=abc.ABCMeta):
@abc.abstractmethod
def 函数名(self):
pass
用这个装饰器装饰然后你继承这个类就必须要有这个功能(函数)代码不同
若子类中没有一个名为这个的功能则会抛出异常TypeError,无法实例化
面向对象之反射(变量名跟字符串差别很大)就要用反射来利用字符串操作对象的数据和方法(函数)(反射从另外一个角度看,能够将面向对象的代码与用户交互起来)
hasattr():判断对象是否含有某个字符串对应的属性名或方法名(函数),会把这个字符串变成一个变量名从对象、产生这个类的对象、和父类去寻找
getattr():根据字符串获取对象对应的属性名(值)或方法名(函数体代码),只要是对象能调用或者使用的功能(拿取值或者函数地址)
了解
setattr():根据字符串给对象设置或者修改数据
delattr():根据字符串删除对象里面的名字
面向对象的魔法方法(不需要人为调用在特定的条件下回自动触发运行)
def init(self,参数):
创建空对象之后自动触发给对象添加独有的数据(对象添加独有的时候触发)
def ser(self):
return 字符串数据
对象被执行打印操作的时候触发,返回的结果是什么结果就是什么(要有返回值返回值必须是字符串)会替代打印的对象
def call(self, *args, **keargs):
print(数据)
return 数据
对象加括号调用的时候自动触发print,还可以返回(return)什么对象接收什么,对象放回的数据也可以接收
def getattr(self, item):
print(数据)
print(item)
return 数据