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

一文秒懂Python面向对象

[复制链接]

4

主题

0

回帖

13

积分

新手上路

积分
13
发表于 2024-9-10 16:22:42 | 显示全部楼层 |阅读模式
目录一、概念和基本属性二、初始化函数三、魔法函数四、构造函数(构造器)与析构函数(类似行为)构造函数(构造器)__init__析构函数(类似行为)__del__五、三大特性:封装、继承、多态封装继承多态六、抽象类七、类中的内容以及向类中动态添加内容1.实例属性2.实例方法3.类属性4.类方法5.静态方法八、数据的访问级别九、属性的封装与操作十、单例类一、概念和基本属性Python面向对象编程(简称OOP)是Python语言中最重要的特性之一。它通过将数据和操作数据的方法封装在对象中,使得程序更加模块化、可重用和易于维护。它遵循一切皆对象的理念,可以将现实世界的事物使用类与实例进行模拟。下面我们来说一说什么是类,什么是实例?类:类是一个用于创建对象的模板,它约定了对象应该具有的属性和方法。属性是对象的特征(如数据),而方法是对象可以执行的操作(如函数)。类是一个抽象的概念,它本身不表示任何具体的数据,但它可以被用来创建表示具体数据的对象。在Python中,你可以使用class关键字来定义一个类。类的定义通常包括:类名:类的唯一标识符初始化方法(__init__):一个特殊的方法,用于在创建对象时初始化对象的属性。其他方法:定义在类中的函数,用于执行与对象相关的操作。实例:实例是类的具体实现,或者说是根据类创建的对象。每个实例都拥有类中定义的属性和方法,但它们可以有不同的属性值。换句话说,实例是类的具体实例化结果,它代表了具体的数据和与之相关的操作。在Python中,你可以通过类名后跟一对圆括号(可能包含初始化参数)来创建类的实例。在创建实例时,Python会自动调用类的__init__方法来初始化对象的属性。下面是代码示例:#自定义一个类classMyClass:pass#声明一个MyClass类的实例mc1=MyClass()二、初始化函数在Python中,初始化函数是一个特殊的方法,用于在创建类的新实例时设置或初始化对象的属性。这个方法通常被称为__init__方法(双下划线init,后跟双下划线)。__init__方法是类的构造器,它在创建类的新实例时自动调用。__init__ 方法的基本用法:定义:在类定义中,__init__ 方法被定义为一个方法,但它不接受self以外的任何参数,除非这些参数是你希望在创建对象时指定的。self参数:__init__ 方法必须包含一个名为 self 的参数。在类的方法中,self 代表类的实例本身。通过这个参数,你可以访问类中的属性和其他方法。初始化属性:在 __init__ 方法内部,你可以设置对象的属性。这通常通过 self.属性名=值 的形式来完成。下面是代码示例:classPerson:def__init__(self,name,age):self.name=name#初始化name属性self.age=age#初始化age属性defgreet(self):print(f"name:{self.name},age:{self.age}")#创建Person类的实例person1=Person("小明",18)#调用实例的方法person1.greet()#输出:name:小明,age:18在这个示例中,Person 类有一个 __init__ 方法,它接受三个参数:self、name 和 age。self 参数是对新创建的 erson 实例的引用,而 name 和 age 是传递给 __init__ 方法的参数,用于初始化对象的属性。当 erson("小明",18) 被执行时,Python创建了一个 erson 类的实例,并自动调用 __init__ 方法,将 "小明" 和 18作为参数传递给它。然后,__init__ 方法将这些值分别赋给新实例的 name 和 age 属性。三、魔法函数Python中的魔法函数(又称为特殊方法或双下划线方法)是Python类定义中可以重写的特殊方法。这些方法总是以双下划线开始和结束,例如__init__、__str__、__add__等。这些方法提供了对象的内置行为,如初始化、字符串表示、算术运算等。当特定的操作被应用到类的实例时,Python解释器会自动调用这些方法。下面是一些常用的魔法函数及其用途的简要介绍:__init__(self,...):类的初始化方法。当创建类的新实例时,会自动调用此方法。它通常用于设置对象的初始状态或属性。__str__(self):定义对象的字符串表示形式。当对对象使用str()函数或者print()函数打印对象时,会自动调用此方法。__repr__(self):定义对象的“官方”字符串表示形式,并应尽可能提供足够的信息,以便能够通过eval()函数重新创建对象。在交互式环境中,如果__str__没有被定义,则会使用__repr__的输出。__add__(self,other):定义加法运算符(+)的行为。__sub__(self,other):定义减法运算符(-)的行为。__mul__(self,other):定义乘法运算符(*)的行为。__truediv__(self,other):定义真除法运算符(/)的行为(Python3)。__floordiv__(self,other):定义地板除运算符(//)的行为。__mod__(self,other):定义取模运算符(%)的行为。__pow__(self,power,modulo=None):定义幂运算符(**)的行为,以及可选的模幂运算(pow(x,y,z))。__eq__(self,other):定义等于运算符(==)的行为。__ne__(self,other):定义不等于运算符(!=)的行为。__lt__(self,other):定义小于运算符()的行为。__ge__(self,other):定义大于等于运算符(>=)的行为。__getitem__(self,key):定义获取容器中指定元素的行为(如使用obj[key])。__setitem__(self,key,value):定义设置容器中指定元素的值的行为(如使用obj[key]=value)。__delitem__(self,key):定义删除容器中指定元素的行为(如使用delobj[key])。__iter__(self):定义容器迭代的行为。__next__(self):与迭代器协议相关,定义迭代器对象的next()方法的行为。下面是代码示例:classMyClass:def__init__(self,name,age):print(f"初始化函数执行了")self.name=nameself.age=agedef__str__(self):returnf"醒醒啦:{self.name}"def__len__(self):returnlen(self.name)def__gt__(self,other):returnself.age>other.agedef__lt__(self,other):returnself.age=other.agedef__le__(self,other):returnself.agebelseb#类方法:在类中定义的方法,类方法第一个参数是cls,则它是类方法,有装饰器#和类属性一样,通过类名调用,也可通过实例名调用但不推荐@classmethoddefinfo(cls):print(cls)def__init__(self,name,age):#向实例中添加的属性称为实例属性self.name=nameself.age=agedefset_name(self,name):#第一个参数是self,则它是实例方法self.name=namedefget_name(self):returnself.namedef__str__(self):returnf"名字:{self.get_name()}年纪:{self.age}"#实例属性:在类中定义的属性,实例属性是绑定到实例上的,每个实例都有自己独立的属性#实例方法:在类中定义的方法,实例方法第一个参数是self,则它是实例方法p0=Person("小明",18)print(p0.name,p0.age)p0.set_name("小路")print(p0.get_name())#类属性通过类名访问print(Person.MAX_AGE,Person.MIN_AGE)#类属性通过类名修改Person.MAX_AGE=130print(Person.MAX_AGE,Person.MIN_AGE)#类属性也可以通过实例名访问,但是不推荐print(p0.MAX_AGE,p0.MIN_AGE)#类属性通过实例名修改,相当于向实例中添加了一个MAX_AGE属性,而不是修改Person类中的MAX_AGE属性p0.MAX_AGE=140print(p0.MAX_AGE,Person.MAX_AGE)#直接通过类名调用print(Person.my_fun1(10,20))在Python中,我们还可以动态添加类内容,下面是动态添加类内容的代码示例:importtypesclassStudent:pass#实例化两个实例s1和s2s1=Student()s2=Student()#向实例s1中动态添加实例属性#每个实例都有自己的实例属性,不共享s1.name="小明"#实例s1可以访问print(s1.name)#实例s2不可以访问try:print(s2.name)exceptAttributeErrorase:print(e)#类不可以访问try:print(Student.name)exceptAttributeErrorase:print(e)#向实例s1中动态添加实例方法#实例方法绑定在实例s1中defmy_set_name(self,name):self.name=namereturnname#添加实例方法需要用到types模块下的MethodType方法,该方法接受两个参数:要添加的方法名和实例名#实例调用方法时调用的方法名是添加实例方法时等号前面的s1.set_name=types.MethodType(my_set_name,s1)#实例s1可以访问print(s1.set_name("小红"))#实例s2不可以访问try:print(s2.set_name("小红"))exceptAttributeErrorase:print(e)#类Student不可以访问try:print(Student.set_name("小红"))exceptAttributeErrorase:print(e)#向类中动态添加类属性Student.name="小王"#类可以直接访问print(Student.name)#实例s1,s2也可以访问(不推荐)#上方为s1添加了实例属性,就近原则,执行添加的实例属性#通过实例访问name属性时,Python会首先查找实例属性,如果没有找到,才会查找类属性。#这就是所谓的“属性查找的最近原则”。print(s1.name)print(s2.name)#向类中动态添加类方法,通常将cls设置为类方法的默认参数名#方法一:@classmethoddefmy_info(cls):print("我是类方法")Student.info=my_info#类可以访问Student.info()#实例s1,s2也都可以访问(不推荐)s1.info()s2.info()#方法二:#defmy_info(cls):#print("我是类方法")###Student.info=classmethod(my_info)#向类中动态添加静态方法@staticmethoddefmy_fun(a,b):returnaifa>belsebStudent.fun=my_fun#类可以访问print(Student.fun(10,20))#实例s1,s2也都可以访问(不推荐)print(s1.fun(30,40))print(s2.fun(50,60))八、数据的访问级别Python中的数据访问级别分为三大类:公有、私有以及保护类型。公有类型(public):普通名字,在类内和类外和子类中都可以使用私有类型(private):__开头的名字,只能在类内访问保护类型(protect):_开头,可以在类外可以强制访问(不推荐),保护是为子类服务的下面是代码示例:classPerson:def__init__(self,name,__age,_sex):self.name=nameself.__age=__ageself._sex=_sexdefget_sex(self):returnself._sexdefset_sex(self,_sex):self._sex=_sexdefget_age(self):returnself.__agedefset_age(self,__age):self.__age=__agedefget_name(self):returnself.namedefset_name(self,name):self.name=namedef__str__(self):returnf"name:{self.get_name()},age:{self.get_age()},sex:{self.get_sex()}"p0=Person("张飞",20,"男")#公有数据,私有数据,保护数据都可以在类内访问print(p0)#公有数据在类外可以访问print(p0.name,p0.get_name())p0.set_name("李华")print(p0.name)#私有数据在类外不可以访问try:print(p0.__age)exceptAttributeErrorase:print(e)#但是可以通过定义公有函数来访问私有数据print(p0.get_age())#保护数据在类外可以强制访问(不推荐)print(p0._sex,p0.get_sex())p0.set_sex("女")print(p0._sex)classSuperPerson(Person):def__str__(self):returnf"性别:{self._sex}"sp1=SuperPerson("绿巨人",30,"男")#公有数据可以在子类的类外访问print(sp1.name,sp1.get_name())#保护数据可以在子类的类外访问print(sp1._sex)#保护数据可以在子类的类外访问print(sp1)设置数据访问类型的主要好处包括:隐藏内部实现:通过将数据和方法封装在类中,可以隐藏对象内部的数据结构和方法的实现细节,只暴露必要的接口给外部。提高安全性:通过控制对类成员的访问(例如,只允许通过特定的方法进行访问),可以防止外部代码错误地修改或访问内部状态。灵活性和可扩展性:封装使得在不修改现有代码的基础上增加新的功能或修改内部实现成为可能,因为外部代码只与类的接口交互。九、属性的封装与操作在Python中可以使用property装饰器来封装类的属性,可以通过自定义的get和set方法来控制属性的访问和修改。下面是属性封装的代码实例:classPerson:def__init__(self,__name,age,__sex,__height):self.__name=__nameself.age=ageself.__sex=__sexself.__height=__height@propertydefheight(self):returnself.__height@height.setterdefheight(self,height):self.__height=heightdefset_sex(self,sex):ifsexin["男","女"]:self.__sex=sexelse:print("设置失败")defget_sex(self):returnself.__sex#使用property封装真正的属性sex=property(get_sex,set_sex)defget_name(self):returnself.__namedefset_name(self,name):if2
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-1-7 06:51 , Processed in 0.424510 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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