概念
表示具有相同属性和方法的对象的集合,在使用类时,先声明在创建类实例,通过访问类实例访问类中的属性方法
元类
python 中一切皆为对象,所有对象都是通过实例化或者调用类得到的,既然是调用类得到的,这个类就称之为元类
class关键字创建类的流程分析
用class关键字定义的类本身也是一个对象,负责产生该对象的类称之为元类(元类可以简称为类的类),内置的元类为type
类的组成部分为类名,基类和类的名称空间,类的名称空间是执行类代码而得到的
class关键字创建类的过程:
1、拿到类名
2、拿到基类
3、执行类体代码。拿到类的名称空间
4、调用元类返回对象
自动创建类
#在python中,当你用 class 关键字的时候,python将自动创建这个object, 有什么方法能手动创建呢,那就是 type 方法. 这是一个很特殊的方法,能够创建一个类. type 的语法如下: def func(self): print(self.id) print '===dynamic create class==='+ '*'*50 MyClass = type('MyClass',(object,),{"a":123,"b":"summer","msg":"test message","func":func}) myclass = MyClass() myclass.func() print '===dynamic create subclass==='+ '*'*50 MySubClass = type('MySubClass',(MyClass,),{"c":"c-value"}) print (MySubClass.c,MySubClass.a,MySubClass.b) print( issubclass(MySubClass, MyClass)) mysubclass = MySubClass() mysubclass.func()
这个例子利用 type 创建了一个MyClass 类,然后又创建了 MySubClass 继承了MyClass 类,并绑定了属性,方法。MySubClass 也绑定自己特有的属性,同时又继承了基类的属性,方法。
这样就实现了,在python 中动态创建类,主要功臣就是 type 方法,为什么type 有这么厉害,其最终原因是:type 是 metaclass ,元类,用来创建类的类。打个比方:
Class=MetaClass()
instance=Class()
type 就是一个 metaclass, python利用type在后面创建各种各样的类
metaclass (元类)就是用来创建类的类。
metaclass的主要目的就是在创建类的时候,做一些自动的改变
类的特性分为封装,继承,和多态
封装
封装是指将数据与具体操作的实现代码放在某个对象内部,使这些代码的实现细节不被外界发现且不能通过任何形式修改对象内部实现,正是由于封装机制。程序在使用某一对象时不需要关心该对象的数据结构细节及实现操作的方法。使用封装能隐藏对象实现细节,使代码更易维护,同时因为不能直接调用、修改对象内部的私有信息,在一定程度上保证了系统安全性
继承
单继承
一个最简单的例子就是孩子会具有父母的一些特征,即每个孩子都会继承父亲或者母亲的某些特征,当然这只是最基本的继承关系,现实世界中还存在着更复杂的继承,继承最大的好处是子类获得了父类的全部变量和方法的同时,又可以根据需要进行修改、拓展。
子类可以继承父类的构造方法,实例变量,类变量,实例方法,类方法和静态方法,类方法生面classmethod,静态方法声明staticmethod
多继承
子类在调用某个方法或变量的时候,首先在自己内部查找,如果没有找到,则开始根据继承机制在父类里查找,根据类的父类定义中的顺序,以深度优先的方式逐一查找父类!
继承参数的书写有先后顺序,写在前面的被优先继承
多态
指同一一个方法调用由于对象不同会产生不同的行为。
多态是方法的多态,属性没有多态。
多态的存在有2个必要条件:继承、方法重写
类相关方法
isinstance
isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。 isinstance() 方法的语法: isinstance(object, classinfo) 参数: object -- 实例对象。 classinfo -- 可以是类名、基本类型或者有它们组成的元组。 返回值: 如果对象的类型与参数二的类型(classinfo)相同则返回 True,否则返回 False。
type
type() 不会认为子类是一种父类类型,不考虑继承关系。
isinstance() 会认为子类是一种父类类型,考虑继承关系。
子类派生,增加自己独有的方法或者属性
super
Super()函数强制调用父类方法,super(子类名,self).方法名()需要传入的是子类名和self,调用的是父类里的方法,按父类的方法需要传入参数,通常在子类的构造方法中使用,通过super()方法调用,从而可以使子类继承父类的实例变量。
子类重写添加父类方法,append直接添加
类魔术方法
__Init__
类创建时会自动创建__init__方法,类似java语言中的构造方法,每当创建一个类的新实例时,python都会自动执行,必须包含一个参数self,并且排在第一位,self参数是一个指向实例本身的引用,用于访问类中的属性和方法,在调用时会自动传递实际参数self,当__init__只有一个参数时,创建类实例时,不需要指定参数。
类中定义的属性和方法,在类外部可以直接调用,隐藏类内部的复杂逻辑,保证类内部属性方法不被外部访问可以加_foo,或者收尾加__foo__变成私有属性或者方法,只能在类内部调用
__new__
_new__ 通常用于控制生成一个新实例的过程。它是类级别的方法。 __new__ 至少要有一个参数 cls,代表要实例化的类,该参数在实例化时由 Python 解释器自动提供; __new__ 必须要有返回值,返回实例化出来的实例; __init__ 通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性,做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法
单例模式
该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
实现单例模式的核心原理是——重写类方法中的__new__方法。
使用 类名() 创建对象时,Python 解释器首先会调用 __new__ 方法为对象分配空间并返回对象的引用,Python 解释器获得对象的引用 后,将引用作为第一个参数,传递给 __init__ 方法。
比如,某个程序的配置信息存放在一个文件中,客户端通过一个Appconfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都在使用配置文件的内容,也就说,很多地方都需要创建Appconfig 对象的实例,这样子就会导致系统中存在很多Appconfig 的实例对象,而这种会严重浪费内存资源。尤其在配置文件内容很多的情况下。事实上 ,类似Appconfig 这样的类 我们希望在程序运行期间只存在一个实例对象。
单例模式个实现方法
1、实例化一个的对象,要用时直接import导如这个对象,而不是再实例化一个,这样就做到了单例模式了,每次都用的是同一个对象
2、我们知道,当我们实例化一个对象时,是先执行了类的__new__方法(我们没写时,默认调用object.new),实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所有我们可以基于这个,实现单例模式。通过new方法内判断是否创建过对象,来实现单例模式,我们实例化三个对象t1,t2,t3三个对象内存地址都是一样的,这就说明他们是同一个对象。
3、通过装饰器实现单例模式:任意一个类使用了该装饰器就会变成一个单例模式的类;
代码示例
class Myclass(): __obj = None def __new__(cls): if cls.__obj is None: #把创建出来的对象赋值给私有成员__obj cls.__obj = object.__new__(cls) return cls.__obj obg1 = Myclass() obg2 = Myclass() obg3 = Myclass() #第一次实例化对象时,创建一个对象赋值给cls.__obj,返回cls.__obj #第二次是实例化对象时,判定__obj is None不成立,直接返回上一次创建好的那个对象 #第三次是实例化对象时,判定__obj is None不成立,直接返回上一次创建好的那个对象
单例模式优点
1.节约内存,不管实例化多少,对象都指向一个内存地址
2.多个地方创建的示例他们的属性互动
类添加属性方法
无参方法
#对象添加
def test(): print('变形') obj.test = test obj.test()
#类添加
Myclass.test = test
Myclass.test()
有参方法
#对象添加
def test(name): print('{}变形'.format(name)) obj.test = test obj.test('小魔仙')
#类添加
Mycalss.test = test
Mycalss.test('小魔仙')
类外类添加属性方法
对象不能调用类中无参方法,无法在类外访问私有成员属性和私有成员方法
#类添加成员属性 Myclass.color = '黑色'
类和对象之间的区别
#1、对象可以调用类的成员属性和方法,类不能调用对象中的成员 #2、类中的成员属性和方法归属于类本身,对象可以调用,但是没有修改和删除的权利 #3、对象在调用相应成员是,先看看自己有没有,如果有,调用自己的,如果没有调用类中的成员,如果类中成员也没有,直接报错
调用类私有方法和属性
#改名策略 #类名 + 私有成员 #对象调用 obj = Myclass() obj._Myclass加上私有属性或方法 #类调用 Myclass._Myclass加上私有属性或方法
删除类中公有成员属性和方法
#删除成员属性或方法 #类删除 del Myclass.成员属性或方法 #对象删除 obj = Myclass() del obj.成员属性或方法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通