init方法
创建对象的步骤: tom = Cat("汤姆",40)
1.创建一个对象,self指向这个对象
2.python自动调用__init__方法,把参数传入
3.返回创建对象的引用给tom
过程
过程只负责执行,没有返回结果.
类和对象
类:创建对象的模板;功能单一,负责创建对象;
对象:由类创建,具体存在的事物;
类的三要素:
类名:大驼峰命名法(首字母大写,不用下划线)
属性(一种名词):对象特征的描述
方法(动词):具有的行为(功能function)
查看对象的内置方法
dir内置函数 :dir(object)
内置函数/方法: __方法名__
定义类
class 类名(object):
def 方法名(self,其它参数):
print()
class 类名:
pass
对象中的引用
对象创建的过程:
1.在内存中创建一个对象
2.将这对对象的引用返回给= 左边的变量 (old)
2. 用一个变量接收对象的引用. tom = Cat() 就像是给这个对象贴标签(这个变量就是这个标签)
tom中保存这对象的引用,即在内存中的地址
print(object_name) 可以输出 对象在内存中地址(默认十六进制)
对象设置属性
self: 哪个对象调用方法,方法内的self就是哪一个对象的引用(即当前对象的引用)
通过self. 来调用方法的
init和del方法
init :初始化
del : 结束
__init__在对象创建以后做的第一件事
__del__在对象销毁前做的最后一件事(引用计数为零时,做的最后一件事)
向对象使用del关键字会自动调用__del__方法
代码执行结束,系统清理内存,调用__del__方法
str
__str__ : 返回
让print(object)输出你想要输出的内容(不写str输出的是一个地址值)
必须要 返回 一个 字符串
开发过程
1.明确开发需求
2.当有多个对象时,应先开发被使用的对象
()的作用
能够把()内部的代码连接在一起;用来把太长的代码换行到几行
is运算符
is用于判断两个变量引用的对象是否一致(即内存地址是否一致)
在Python中对 None的判断 pep8 建议使用 is
私有属性/方法
私有:不希望被外部访问,即只希望被内部访问;(目的:为了安全)
定义方法:__方法名/属性名
作用:只能在内部被访问
处理方式: 在名称前面加上 _类名 => _类名__名称
因此只要通过: _类名__名称 就能访问, 所以python没有真正意义上的私有
python没有真正意义上的私有
继承
目的:减少代码冗余
继承:子类 拥有 父类 的所有 方法和属性
继承的语法:
class 类名(父类名):
pass
优点:可以直接享受父类中已经封装好的方法,不需要再次开发
传递性:派生类B拥有基类A的所有属性和方法,B的派生类C拥有A的所有属性和方法
父类的属性和方法,可以不断的向子类,子类的子类传递
重写(override)
应用场景:当父类的方法实现不能满足子类的需求是,对方法进行重写
两种情况:
1.覆盖父类的方法
2.对父类的方法进行 扩展
1.覆盖父类:
在子类中定义一个和父类同名的方法并且实现
再次调用,只会调用子类重写的方法
2.对父类的方法进行 扩展
1.在子类中重写 父类的方法
2.在需要的位置 ,调用父类的方法,用 super().父类的方法 来调用父类的方法
3. 编写子类特有的代码
super 是一个特殊的类:
super() 是使用super类创建的对象
作用:指向父类
super().方法 :就是调用父类中的指定方法
调用父类方法的另外一种方式(Python2.x)
父类名.方法(self)
self:必须写
如果使用了 当前子类名 调用方法,会形成递归调用,出现死循环
不能继承的东西:父类的私有的属性/方法
子类不能在自己的内部/外部,直接父类的私有属性/方法
子类可以通过父类的 公有方法,间接访问父类的私有属性/方法
原因: 还是因为私有这两个字,私有:只允许内部访问!
为什么可以访问,只是在父类中找了 公有方法 这个代理,私有方法/属性仍然只能内部访问
多继承
子类拥有多个父类,并且具有父类的所有的属性和方法(公有)
语法:
class(父类名1,父类名2...):
pass
MRO:Method Resolution Order
方法搜索路径:主要用于在多继承是判断方法/属性 的调用路径
__mro__ 可以查看方法的搜索顺序 print(类名.__mro__)
从当前类开始,到object类结束,如果还没有找到,程序报错
新式类和经典类
经典类:不以 object 为基类的类
新式类: 以 object 为基类的类
python2.x : 经典类因为没有继承object,没有object内置属性
python3.x :默认都是新式类,都继承类object的内置属性
新式类和经典类在多继承时会影响到方法的搜索顺序
dir(object):查看对象的内置方法
多态
多态:不同的子类对象,调用相同的父类方法,产生不同的执行结果
优点:
增加了代码的灵活度
以继承和重写父类方法为前提
是调用方法的技巧,不会影响到类的内部设计(传递的对象不同,调用同一个方法结果不同)
实例
由类创建出来的 对象 是 实例
创建的这个过程就叫做 实例化
对象的属性:实例属性
对象的方法:实例方法
每一个对象 都有自己独立的空间: 用于保存各自不同的属性
但对象的方法,在内存中只有一份(在类所在的内存空间).
调用时,需要把对象的引用传递到方法内部
类是一个特殊的对象
---> ,
-->,.
,
类属性
类对象 中定义的属性
作用:用于记录与类相关的 特征
定义属性:
属性名 = value (在class下方)
访问属性:
类名.类属性名
对象名.类属性名(不推荐)
访问时有向上查找机制,
但是赋值就没有:对象.类属性 = 值, 结果是给对象添加一个属性(对象属性),不会修改类属性
属性的获取机制
向上查找机制(自下而上)
1.首先在对象内部查找
2.没有找到,会向上去 它的类去查找
类方法
定义:
1.@classmethod
2.第一个参数是:cls (使用其它名字也可以,习惯使用cls)
@classmethod
def 类方法名(cls):
pass
在类方法内部:
可以通过cls. 访问这个类的属性
也可以通过 cls. 调用其它 类方法
调用:
在外部,通过 类名.类方法 -->不需要先创建对象
在类方法内部, 可以直接使用 cls 访问 类属性 或 类方法
静态方法
当一个方法需要访问 实例属性 时, 定义为 实例方法
当一个方法需要访问 类属性 时 , 定义为 类方法
当一个方法 即不需要访问 实例属性有不访问 类属性时, 定义为 静态方法
静态方法:不需要传参数的方法(不需要访问实例属性也不需要访问类属性的方法)
定义:
1.@staticmethod
2.不需要参数
@staticmethod
def 静态方法名():
pass
调用: 类名.静态方法名 -->不需要先创建对象
使用场景:不需要传参数时,定义成静态方法
类和静态
类和静态 会随着类的加载而加载 ,在__init__ 之前(即在创建对象之前)
同样不需要先创建对象,可以直接调用(类名.方法名)
不同:静态不许要参数,类需要参数
方法选择
--->
.
--->
--->,
,
单例设计模式
设计模式: 解决某一类问题的一个套路
单例设计模式: 类创建的对象永远只有一个实例---> 每次执行创建,返回的内存地址是相同的
1.定义一个类属性instance,初始值是None, 目的用于记录 单例对象的引用
2.重写 __new__方法
3.如果类属性instance is None() (即判断是否已存在一个实例), (如果不存在)调用父类方法分配一个空间,并用类属性记录结果
4. 返回类属性记录的 对象引用
class Music(object):
instance = None
flag = False
def __new__(cls,*args,**kwargs):
if cls.instance is None:
cls.instance = super().__new__(cls)
return cls.instance
def __init__(self):
if Music.flag:
return
print("initialazation")
Music.flag = True
new
__new__方法:
1.在内存中为对象分配空间
2.返回对象的引用
(python解释器接收到引用后,将引用作为第一个参数,传递给__init__方法)
举例:__new__就像是:给你买一套房子(分配内存空间),并把房子的钥匙给你(返回引用)
重写__new__方法:
def __new__(cls,*args,**kwargs):
1.调用父类的__new__方法,来分配内存空间
instance = super().__new__(cls) new为静态方法,所以必须手动把cls参数传入
2.把这个空间的引用返回给__init__(self)方法
return instance