找回密码
 会员注册
查看: 21|回复: 0

Python-面向对象编程(超详细易懂)

[复制链接]

2万

主题

0

回帖

6万

积分

超级版主

积分
65944
发表于 2024-9-4 17:27:56 | 显示全部楼层 |阅读模式
面向对象编程(oop)    面向对象是Python最重要的特性,在Python中一切数据类型都是面向对象的。    面向对象的编程思想:按照真实世界客观事物的自然规律进行分析,客观世界中存在什么样的实体,构建的软件系统就存在什么样的实体。    例如:在学校里,有学生实体,学生是抽象的描述,称为“类”;而张同学、李同学等具体的学生个体称为“对象”,也称为“实例”;学生有学号、姓名、班级等属性,还有吃饭、走路等操作。面向对象三大特性:封装性、继承性、多态性封装性:使外部访问者不能随意存取对象的内部数据,隐藏了对象的内部细节,只保留有限的对外接口。外部访问者不用关心对象的内部细节,操作对象变得简单。继承性:特殊类继承一般类,拥有一般类的全部数据和操作。一般类称为“父类”或“超类”,特殊类称为“子类”或“派生类”。多态性:在父类中成员被子类继承后,可以具有不同的状态或表现行为。类和对象    ython中的数据类型都是类,类是组成Python程序的基本要素,它封装了一个类对象的数据和操作。定义类Python语言中一个类的实现包括类定义和类体。语法格式如下:class类名[(父类)]:类体 输入下面代码classAnimal():#创建Animal类passclassBooks():##创建Books类pass#分别创建对应的类对象a=Animal()b=Books()print(id(Animal))print(type(Animal))print(type(a))print(type(b))代码运行结果1939387281408Processfinishedwithexitcode0    注意:object类是所有类的根类,在Python中任何一个类都直接或间接的继承object;代码的pass语句表示什么操作都不执行,用来维持程序结构的完整。创建、使用和销毁对象    一个对象的生命周期包括创建、使用和销毁。类实例化可生成对象,所以对象也称为“实例”。    创建对象就是在类对象的后面加上一对小括号,表示调用类对象的构造方法,这就创建了一个对象,示例代码如下classAnimal:pass'''Animal()表达式创建了一个对象,并把创建的对象通过“=”赋给animal变量animal是指向对象的一个引用。通过animal可以使用刚刚创建的对象'''animal=Animal()#print函数实际上是调用了对象的__str__()方法(__str__()是object类的一个方法,#用于返回有关该对象的描述信息)输出字符串信息print(animal)代码运行结果销毁对象    ython会实现自动的垃圾回收:当对象没有被引用时(引用计数为0),由垃圾回收器调用__del__()(析构函数),__del__()被称为“析构方法”,用于实现对象被销毁时所需的操作。比如:释放对象占用的资源(例如:打开的文档资源、网络连接等)。我们也可以通过del语句删除对象,系统会自动调用__del__()方法,一般不需要自定义析构方法。示例代码如下classPerson:def__del__(self):print("销毁对象:{0}".format(self))p1=Person()p2=Person()delp2'''当p2的引用被del语句删除时p2的__del__方法会被调用但是,p1的__del__方法可能在程序结束前不会被调用因为它的引用仍然存在于变量p1中'''print("程序结束")代码运行结果销毁对象:程序结束销毁对象: 实例变量“实例变量”就是某个实例(或对象)个体特有的数据。示例代码如下classAnimal(object):def__init__(self,name,age,weight,gender):self.name=name#定义姓名实例变量self.age=age#定义年龄实例变量self.weight=weight#定义体重实例变量self.gender=gender#定义性别实例变量animal=Animal('Tom',18,66,1)animal1=Animal('Mary',18,50,0)print("姓名:{0},年龄:{1},体重:{2}".format(animal.name,animal.age,animal.weight))print("男性"ifanimal.gender==1else'女性')print("姓名:{0},年龄:{1},体重:{2}".format(animal1.name,animal1.age,animal1.weight))print("男性"ifanimal1.gender==1else'女性')代码运行结果姓名:Tom,年龄:18,体重:66男性姓名:Mary,年龄:18,体重:50女性 类变量    “类变量”是所有实例(或对象)共有的变量,需要在方法外定义,访问实例变量通过“实例名.实例变量名”的形式,而访问类变量“类名.类变量名”的形式访问。示例代码如下classAccount:interest_rate=0.068#类变量#重写构造方法def__init__(self,owner,amount):self.owner=ownerself.amount=amountaccount=Account('Tony',1_800_000.0)#查看实例变量print('account实例所有变量:{0}'.format(account.__dict__))#为account.interest_rate变量赋值,此时无论类中是否有同名变量都会创建一个新的实例变量account.interest_rate=0.01account.interest_rate2=0.01print('账户名:{0}'.format(account.owner))print('账号金额:{0}'.format(account.amount))print('利率:{0}'.format(Account.interest_rate))#查看实例变量print('account实例所有变量:{0}'.format(account.__dict__))代码运行结果account实例所有变量:{'owner':'Tony','amount':1800000.0}账户名:Tony账号金额:1800000.0利率:0.068account实例所有变量:{'owner':'Tony','amount':1800000.0,'interest_rate':0.01,'interest_rate2':0.01}    注意:不要通过实例存取类变量数据。当通过实例读取变量时,Python解释器会先在实例中找这个变量,如果没有再到类中去找;当通过实例为变量赋值时,无论类中是否有该同名变量,Python解释器都会创建一个同名实例变量。 构造方法    __init_()方法是构造方法,用来创建和初始化实例变量,定义时它的第一个参数应该是self,其后的参数才是用来初始化实例变量的;其中参数可以有默认值。调用构造方法时不需要传入self。如果未定义构造方法,则会自动调用默认的构造方法;一旦定义了构造方法,则不会调用默认的构造方法。输入下面代码classAnimal(object):#构造方法def__init__(self,name='mark',age=20,weight=120,gender=120):self.name=name#定义姓名实例变量self.age=age#定义年龄实例变量self.weight=weight#定义体重实例变量self.gender=gender#定义性别实例变量animal0=Animal()#此时没有传入参数,参数为默认值animal=Animal('Tom',18,66,1)animal1=Animal('Mary',18,50,0)print("姓名:{0},年龄:{1},体重:{2}".format(animal0.name,animal0.age,animal0.weight))print("姓名:{0},年龄:{1},体重:{2}".format(animal.name,animal.age,animal.weight))print("姓名:{0},年龄:{1},体重:{2}".format(animal1.name,animal1.age,animal1.weight))代码运行结果姓名:mark,年龄:20,体重:120姓名:Tom,年龄:18,体重:66姓名:Mary,年龄:18,体重:50实例方法    实例方法与实例变量一样都是某个实例个体特有的。定义实例方法时它的第一个参数应该是self,这个过程是将当前实例与该方法绑定起来,使该方法成为实例方法。示例代码如下classAnimal:def__init__(self,age,sex=1,weight=0.0):self.age=ageself.sex=sexself.weight=weightdefeat(self):self.weight+=0.05print("eat...")defrun(self):self.weight-=0.01print("run...")a1=Animal(2,0,10.0)print('a1体重:{0:0.2f}'.format(a1.weight))a1.eat()print('a1体重:{0:0.2f}'.format(a1.weight))a1.run()print('a1体重:{0:0.2f}'.format(a1.weight))代码运行结果a1体重:10.00eat...a1体重:10.05run...a1体重:10.04类方法    类方法不需要与实例绑定,但需要与类绑定,定义时它的第一个参数是类的type实例。type是描述Python数据类型的类,Python中所有数据类型都是type的一个实例。类方法可以访问类变量和其他类方法,但不能访问其他实例方法和实例变量。    定义类方法:方法第一个参数cls是type类型的一个实例;方法使用装饰器@classmethod声明该方法是类方法。该方法不能调用实例属性,也不能调用实例方法。示例代码如下classAccount:interest_rate=0.0668#类变量#重写构造方法def__init__(self,owner,amount):self.owner=ownerself.amount=amount#类方法@classmethoddefinterest_by(cls,amt):returncls.interest_rate*amtinterest=Account.interest_by(12_000.0)print('计算利息:{0:.4f}'.format(interest))代码运行结果计算利息:801.6000静态方法    如果定义的方法既不想与实例绑定,也不想与类绑定,只是想把类作为它的命名空间,那么可以定义静态方法。定义时使用@staticmethod装饰器,声明方法是静态方法,方法参数不指定self和cls。该方法不能调用实例属性,也不能调用实例方法。示例代码如下classAccount:interest_rate=0.0668#类变量#重写构造方法def__init__(self,owner,amount):self.owner=ownerself.amount=amount#类方法@classmethoddefinterest_by(cls,amt):returncls.interest_rate*amt@staticmethoddefinterst_with(amt):returnAccount.interest_by(amt)interest1=Account.interest_by(12_000.0)print('计算利息:{0:.4f}'.format(interest1))interest2=Account.interest_by(12_000.0)print('计算利息:{0:.4f}'.format(interest2))代码运行结果计算利息:801.6000计算利息:801.6000动态绑定属性和方法 示例代码如下classPerson():def__init__(self,name,age):self.name=nameself.age=agedefshow(self):print(f'我的名字是{self.name},我的年龄是{self.age}')person1=Person('张三',18)person2=Person('李四',19)#为person2动态绑定属性person2.gender='male'#为person2动态绑定方法defmethod():print('这是用于动态绑定的方法')person2.fun=method#输出绑定的属性print(person2.gender)#person1并没有gender属性person2.fun()#person1并没有fun()方法代码运行结果male这是用于动态绑定的方法Processfinishedwithexitcode0封装性私有变量    默认情况下,Python中的变量是公有的,可以在类的外部访问他们。如果想让他们成为私有变量,可以在变量前加上双下划线“__”,双下划线开头表示private私有的成员,这类成员只允许定义该属性或方法的类本身进行访问。如果以单下划线开头的属性或方法表示protected受保护的成员,这类成员被视为仅供内部使用,允许类本身和子类进行访问,但实际上它可以被外部代码访问。而首尾双下划线一般表示特殊的方法。示例代码如下classAnimal:def__init__(self,age,sex=1,weight=0.0):self.age=ageself.sex=sexself.__wight=weightdefeat(self):self.__wight+=0.05print("eat...")defrun(self):self.__wight-=0.01print("run...")a1=Animal(2,0,10.0)#该段代码发生错误,因为weight是私有变量,无法在类的外部访问print('a1体重:{0:0.2f}'.format(a1.weight))a1.eat()a1.run()代码运行结果    ython语言并不像Java,私有变量只是形式上私有,并非严格意义上的私有;如果想要访问私有变量,可以通过 对象名._类名__变量名来访问,但是一般不推荐这么做,因为这违反了封装的原则,使代码的维护变得困难(可见Python的封装性靠的是程序员的自律,而非强制性的语法)。输入下面代码classAnimal:def__init__(self,age,sex=1,weight=0.0):self.age=ageself.sex=sexself.__weight=weight#定义私有变量defeat(self):self.__weight+=0.05print("eat...")defrun(self):self.__weight-=0.01print("run...")a1=Animal(2,0,10.0)print('a1体重:{0:0.2f}'.format(a1._Animal__weight))a1.eat()a1.run()#通过内置函数dir打印对象的属性和方法print(dir(a1))代码运行结果a1体重:10.00eat...run...['_Animal__weight','__class__','__delattr__','__dict__','__dir__','__doc__','__eq__','__format__','__ge__','__getattribute__','__getstate__','__gt__','__hash__','__init__','__init_subclass__','__le__','__lt__','__module__','__ne__','__new__','__reduce__','__reduce_ex__','__repr__','__setattr__','__sizeof__','__str__','__subclasshook__','__weakref__','age','eat','run','sex']推荐的做法是定义一个公共方法来访问示例代码如下classAnimal:def__init__(self,age,sex=1,weight=0.0):self.age=ageself.sex=sexself.__weight=weight#定义私有变量defeat(self):self.__weight+=0.05print("eat...")defrun(self):self.__weight-=0.01print("run...")defget_weight(self):#添加一个公共方法来获取私有变量的值returnself.__weighta1=Animal(2,0,10.0)print('a1体重:{0:0.2f}'.format(a1.get_weight()))a1.eat()a1.run()print('a1体重:{0:0.2f}'.format(a1.get_weight()))代码运行结果a1体重:10.00eat...run...a1体重:10.04私有方法    私有方法与私有变量是类似的,只要在方法前加上双下划线“__”就是私有方法,在类外面强制使用也是“对象名._变量名__方法名”(不推荐)。示例代码如下classAnimal:def__init__(self,age,sex=1,weight=0.0):self.age=ageself.sex=sexself.__weight=weight#定义私有变量defeat(self):self.__weight+=0.05print("eat...")def__run(self):self.__weight-=0.01print("run...")defget_weight(self):#添加一个公共方法来获取私有变量的值returnself.__weighta1=Animal(2,0,10.0)print('a1体重:{0:0.2f}'.format(a1.get_weight()))a1.eat()a1._Animal__run()#强制访问,不推荐这样做print('a1体重:{0:0.2f}'.format(a1.get_weight()))代码运行结果a1体重:10.00eat...run...a1体重:10.04定义属性    在实际的面向对象设计中,一个类是不应该有公有的实例成员变量的,这些实例成员变量被设计为私有的,然后通过共有的setter和getter访问器访问。(访问器形式的封装需要一个私有变量,需要提供setter和getter访问器,只读变量不用提供setter访问器)示例代码如下classAnimal:def__init__(self,age,sex=1,weight=0.0):self.age=ageself.sex=sexself.__weight=weight#定义私有变量defeat(self):self.__weight+=0.05print("eat...")def__run(self):self.__weight-=0.01print("run...")defget_weight(self):#添加一个公共方法来获取私有变量的值returnself.__weightdefset_weight(self,weight):#添加一个set方法来访问self.__weight=weighta1=Animal(2,0,10.0)#该段代码发生错误,因为weight是私有变量,无法在类的外部访问print('a1体重:{0:0.2f}'.format(a1.get_weight()))a1.set_weight(20.00)print('a1体重:{0}'.format(a1.get_weight()))代码运行结果a1体重:10.00a1体重:20.0    访问器形式的封装在编写代码时比较麻烦,Python提供了属性(poperty),定义属性可以使用@property(将一个方法转换成属性去使用,即定义形式是方法,使用时可以将该方法当成属性来用,也就是不需要加括号)和@属性名.setter装饰器(通过@property设置之后就只能访问不能修改,如果想要修改可以再定义@属性名.setter方法)。示例代码如下classAnimal:def__init__(self,age,sex=1,weight=0.0):self.age=ageself.sex=sexself.__weight=weight#定义私有变量@propertydefweight(self):#添加一个公共方法来获取私有变量的值returnself.__weight@weight.setterdefweight(self,weight):#添加一个set方法来访问self.__weight=weighta1=Animal(2,0,10.0)#该段代码发生错误,因为weight是私有变量,无法在类的外部访问print('a1体重:{0:0.2f}'.format(a1.weight))a1.weight=20.0print('a1体重:{0}'.format(a1.weight))代码运行结果a1体重:10.00a1体重:20.0示例代码二:加深对装饰器的理解示例代码如下classPerson():def__init__(self,name,age):self.name=nameself.__age=age@propertydefage(self):returnself.__age@age.setterdefage(self,value):ifvalue150:print('年龄不在有效范围,已将年龄设置为默认18')self.__age=18else:self.__age=valueperson=Person('张三',18)print(person.name,person.age)person.age=190print(person.age) 代码运行结果张三18年龄不在有效范围,已将年龄设置为默认1818Processfinishedwithexitcode0 继承性    多态性的前提是继承性,子类继承父类时只是继承父类中公有的成员变量和方法,不能继承私有的成员变量和方法。示例代码如下classPerson:def__init__(self,age,sex=1,weight=0.0):self.age=ageself.sex=sexself.__weight=weight#定义私有变量classStudent(Person):#Student继承了Person类def__init__(self,name,age,school):super().__init__(name,age)#定义子类的构造方法时先要调用父类的构造方法,初始化父类实例变量self.school=school 重写方法    如果子类方法名与父类方法名相同,而且参数列表也相同,只是方法体不同,那么子类重写了父类的构造方法;此时在用子类对象调用该方法时,会执行子类的该方法,而不是父类的。示例代码如下classAnimal:def__init__(self,age,sex=1,weight=0.0):self.age=ageself.sex=sexself.weight=weight#定义私有变量defeat(self):self.weight+=0.1print("动物吃...")classDog(Animal):defeat(self):self.weight+=0.1print("狗狗吃...")a1=Dog(2,0,10.0)a1.eat()代码运行结果狗狗吃...多继承    多继承就是一个子类继承多个父类,在Java中只能单继承,因为多继承会发生方法冲突。Python支持多继承,当子类实例调用一个方法时,先从子类中查找,如果没有则查找父类,查找父类的顺序是按照子类声明的父类列表从左到右查找,若没有则查找父类的父类。示例代码如下classParentClass1:defrun(self):print('ParentClass1run...')classParentClass2:defrun(self):print('ParentClass2run...')classSubClass1(ParentClass1,ParentClass2):passclassSubClass2(ParentClass2,ParentClass1):passclassSubClass3(ParentClass1,ParentClass2):defrun(self):print('SubClass3run...')sub1=SubClass1()sub1.run()sub2=SubClass2()sub2.run()sub3=SubClass3()sub3.run()代码运行结果ParentClass1run...ParentClass2run...SubClass3run...示例二:加深对多继承的理解示例代码如下#在多继承时需要调用多个父类的方法进行初始化时,此处定义了A、B两个父类classFatherA():def__init__(self,name):self.name=namedefshowA(self):print('我是FatherA中的方法')classFatherB():def__init__(self,age):self.age=agedefshowB(self):print('我是FatherB中的方法')classSon(FatherA,FatherB):def__init__(self,name,age,gender):#此时不能再用super()来调用,因为无法区分哪个父类,因此需要直接指明调用哪个父类FatherA.__init__(self,name)FatherB.__init__(self,age)self.gender=genderson=Son('CSDN@邂逅自己',18,'female')son.showA()son.showB()代码运行结果我是FatherA中的方法我是FatherB中的方法Processfinishedwithexitcode0多态性 发生多态有两个前提条件:继承—多态发生一定是子类和父类之间重写—子类重写了父类的方法示例代码如下classFigure:defdraw(self):print("Figuredraw...")classEllipse(Figure):defdraw(self):print("Ellipsedraw...")classTriangle(Figure):defdraw(self):print("Triangledraw...")f2=Ellipse()f2.draw()f3=Triangle()f3.draw()代码运行结果 Ellipsedraw...Triangledraw...案例二:加深对多态的理解示例代码如下#多态可以在程序运行过程中动态决定调用哪个方法#该代码说明了在Python中要实现多态不需要对象之间有继承关系、也不关心对象的数据类型#需要有同名方法,即便在一开始不知道数据类型classPerson():defshow(self):print('我是Person的show方法')classDog():defshow(self):print('我是Dog的show方法')classCat():defshow(self):print('我是Cat的show方法')deffun(obj)bj.show()person=Person()dog=Dog()cat=Cat()fun(person)fun(dog)fun(cat)代码运行结果我是Person的show方法我是Dog的show方法我是Cat的show方法Processfinishedwithexitcode0 类型检查    与Java语言相比,多态性对于动态语言Python而言意义不大。但是无论多态性对Python的多大,Python作为面向对象的语言多态性是存在的。函数描述isinstance(object,classinfo)可以检查object实例是否由classinfo类或infoclass子类所创建的实例 issubclass(class,classinfo)可以检查class是否是classinfo的子类示例代码如下classFigure:defdraw(self):print("Figuredraw...")classEllipse(Figure):defdraw(self):print("Ellipsedraw...")classTriangle(Figure):defdraw(self):print("Triangledraw...")f1=Figure()f2=Ellipse()f3=Triangle()print(isinstance(f2,Figure))#Trueprint(isinstance(f3,Figure))#Trueprint(isinstance(f1,Figure))#Trueprint(isinstance(f1,object))#True,因为任何类都是object类的子类print(issubclass(Figure,object))#Trueprint(issubclass(Ellipse,Triangle))#False代码运行结果TrueTrueTrueTrueTrueFalse 鸭子类型    不关注变量的类型,而是关注变量具有的方法。鸭子类型像多态一样工作,但是没有继承,只要像“鸭子”一样的行为(方法)就可以了。(用“鸭子类型”代替多态性设计能够充分发挥Python动态语言特点,但是对程序员要求也非常高)示例代码如下classAnimal(object):defrun(self):print("Animalrun...")classDog(Animal):defrun(self):print("Dogrun...")classCar:defrun(self):print("Carrun...")defgo(animal):ifnotisinstance(animal,(Animal,Car)):#检查animal是否为Animal或Car的实例return#如果不是,则作为递归的基案结束递归animal.run()#调用run方法#创建实例animal_instance=Animal()dog_instance=Dog()car_instance=Car()#使用实例调用go函数go(animal_instance)go(dog_instance)go(car_instance)#添加了一个类型检查来确保只有Animal或Car的实例才会调用run方法。如果传入的不是这些类的实例,#go函数将直接返回,避免递归调用。代码运行结果Animalrun...Dogrun...Carrun...Python根类—objectPython所有类都直接或间接的继承object类,因此所有类拥有object类的属性和方法;object类有很多方法。方法描述__str__()默认返回对象的类名,以及内存地址等信息;可以重写该方法,输出描述信息__eq__()重写该方法指定相等的规则(即指定比较的是哪些实例变量相等)__new__()由系统调用,用于创建对象__init__()创建对象时手动调用,用于初始化对象属性值 示例代码1如下classPerson:def__init__(self,name,age):self.name=nameself.age=agedef__str__(self):#重写str方法,返回什么样的字符串可以自己指定template='Person[name={0},age={1}]'s=template.format(self.name,self.age)returnsPerson=Person('Tony',18)print(Person)代码运行结果Person[name=Tony,age=18]示例代码2如下classPerson:def__init__(self,name,age):self.name=nameself.age=agedef__str__(self):#重写str方法,返回什么样的字符串可以自己指定template='Person[name={0},age={1}]'s=template.format(self.name,self.age)returnsdef__eq__(self,other):#重写eq方法,指定只有姓名和年龄都相等时才是Trueifself.name==other.nameandself.age==other.age:returnTrueelse:returnFalsep1=Person('Tony',18)p2=Person('Tony',18)p3=Person('Mary',18)print(p1==p2)print(p1==p3)代码运行结果TrueFalse示例代码3如下classPerson():def__init__(self,name,age):self.name=nameself.age=agedef__str__(self):return'我是重写str方法后输出的内容'person=Person('CSDN@邂逅自己',18)#若不重写str方法#则输出对象时是输出内存地址#重写str方法后#则输出对应的内容,如果有的话print(person)代码运行结果我是重写str方法后输出的内容Processfinishedwithexitcode0特殊方法实际上,在Python中使用运算符时也是通过调用特殊方法来实现的运算符特舒方法描述+_add_()执行加法运算-_sub_()执行减法运算,>=,!=_gt_(),_ge_(),_ne_()执行比较运算*,/_mul_(),_truediv_()执行乘法运算,非整数运算%,//_mod_(),_floordiv_()执行取余运算,整除算法**_pow_()执行幂运算特殊属性特殊属性说明obj.__dict__对象的属性字典,使用语法:对象名.__dict__obj.__class__对象所属的类,使用语法:对象名.__class__class.__bases__类的父类元组,使用语法:类名.__bases__class.__base__类的父类,使用语法:类名.__base__class.__mro__类的层次结构,使用语法:类名.__mro__class._subclasses类的子类列表示例代码如下classFatherA():passclassFatherB():passclassson(FatherA,FatherB):def__init__(self,name,age):self.name=nameself.age=agea=FatherA()b=FatherB()c=son('张三',18)print('-'*20,'__dict__','-'*20)#输出对象的属性字典print(a.__dict__)print(b.__dict__)print(c.__dict__)print('-'*20,'__class__','-'*20)#输出对象所属的类print(a.__class__)print(b.__class__)print(c.__class__)print('-'*20,'__bases__','-'*20)#输出父类元组print(FatherA.__bases__)print(FatherB.__bases__)print(son.__bases__)print('-'*20,'__base__','-'*20)#输出所属的父类print(FatherA.__base__)print(FatherB.__base__)print(son.__base__)#如果继承了多个父类,结果只显示第一个父类,要想知道所有的父类需要用__bases__print('-'*20,'__mro__','-'*20)#输出类的层次结构print(FatherA.__mro__)print(FatherB.__mro__)print(son.__mro__)#输出结果解析,以(,,,)#为例,其中,为分隔符,前面表示son类,中间的内容表示son类继承了FatherA和FatherB,最后内容白叟son类又间接继承了object类print('-'*20,'__subclasses__','-'*20)#输出类的子类列表print(FatherA.__subclasses__())print(FatherB.__subclasses__())print(son.__subclasses__())代码运行结果--------------------__dict__--------------------{}{}{'name':'张三','age':18}--------------------__class__----------------------------------------__bases__--------------------(,)(,)(,)--------------------__base__----------------------------------------__mro__--------------------(,)(,)(,,,)--------------------__subclasses__--------------------[][][]Processfinishedwithexitcode0类的浅拷贝与深拷贝浅拷贝:拷贝时对象包含的子对象内容不拷贝,因此,源对象与拷贝对象会引用同一个子对象。深拷贝:使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不相同。示例代码如下classCPU():passclassDisk():passclasscomputer():def__init__(self,cpu,disk):self.cpu=cpuself.disk=diskcpu=CPU()disk=Disk()computer=computer(cpu,disk)#变量赋值computer1=computerprint(computer,'子对象的内存地址',computer.cpu,computer.disk)print(computer1,'子对象的内存地址',computer1.cpu,computer1.disk)#类对象的拷贝print('-'*20,'类对象的浅拷贝','-'*20)importcopycomputer2=copy.copy(computer)#computer2是新产生的子对象,但是cpu和disk不变print(computer2,'computer2子对象的内存地址',computer2.cpu,computer2.disk)#类对象的深拷贝print('-'*20,'类对象的深拷贝','-'*20)computer3=copy.deepcopy(computer)#computer2、cpu和disk都是新产生的子对象print(computer3,'computer3子对象的内存地址',computer3.cpu,computer3.disk)代码运行结果子对象的内存地址子对象的内存地址--------------------类对象的浅拷贝--------------------computer2子对象的内存地址--------------------类对象的深拷贝--------------------computer3子对象的内存地址Processfinishedwithexitcode0参考书籍:《python从小白到大牛》(第2版)关东升编著 文章创作不易,本文18000+字,为了大家能理解,写的很详细,这也让我花了很多时间。最后,如果觉得本文对大家有帮助的话,还请给我点个赞和关注,谢谢大家!!!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-31 04:31 , Processed in 0.683606 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表