找回密码
 立即注册

Python 面向对象

聚怪闩 2026-1-29 14:15

0x01 面向对象概念

类和对象都是面向对象中的重要概念。面向对象是一种编程思想,即按照真实世界的思维方式构建软件
系统。
例如,在真实世界的校园里有学生和老师,学生有学号、姓名、所在班级等属性(数据),还有学习、提问、吃饭和走路等动作(方法)。如果我们要开发一个校园管理系统,那么在构建软件系统时,也会有学生和老师等“类”,张同学、李同学是学生类的个体,被称为“对象”,"对象"也被称为"实例"。

0x02 定义类

Python中的数据类型都是类,我们可以自定义类,即创建一种新的数据类型。

[code]class 类名[(父类)]: #父类可以省略声明,表示直接继承object类 类体 #缩进,在Python中推荐采用4个半角空格 [/code] [code]class Car(object): #类体 pass #pass主要用于占位 [/code]

Car 类继承了 object 类,object 类是所有类的根类,在 Python 中任何一个类(除object外)都直接或间接地继承了 object,直接继承 object 时(object)部分的代码可以省略。

0x03 创建对象

类相当于一个模板,依据这样的模板来创建对象,就是类的实例化,所以对象也被称为"实例"。

image

[code]class Car(object): #类体 pass #pass主要用于占位 car=car() [/code]

0x04 类成员

image

成员变量也成为数据成员,保存了类或对象的数据。例如,学生的姓名和学号。
构造方法事一种特殊的函数,用于初始化类的成员变量。
成员方法是在类中定义的函数。
属性是对类进行封装而提供的特殊方法。

实例变量

实例变量就是对象个体特有的"数据"。

[code]class Dog: def __init__(self,name,age): #__init__()方法是构造方法,用来初始化实例变量 self.name=name #创建和初始化实例变量name self.age=age #创建和初始化实例变量age d=Dog('球球',2) #创建对象 print('我们家狗狗叫{0},{1}岁了'.format(d.name,d.age)) #对实例变量通过"对象.实例变量"形式访问 输出结果为: 我们家狗狗叫球球,2岁了 [/code]

类中的 self 表示当前对象,构造方法中的 self 参数说明这个方法属于实例,self.age 中的 self 表示 age 属于实例,即实例成员变量。

构造方法

类中的__init__()方法是一个非常特殊的方法,用来创建和初始化实例变量,这种方法就是"构造方法"。在定义__init__()方法时,他的第1个参数应该是self,之后的参数用来初始化实例变量。调用构造方法时不需要传入self参数。

[code]class Dog: def __init__(self, name,age,sex='雌性'): #第1个参数必须是self,带有默认值的构造方法能够提供多个不同版本的构造方法 self.name=name #创建和初始化实例变量name self.age=age #创建和初始化实例变量age self.sex=sex #创建和初始化实例变量sex d1=Dog('球球',2) #创建对象调用构造方法,省略默认值 d2=Dog('哈哈',1,'雄性') d3=Dog(name='拖布',sex='雄性',age=3) #使用关键字参数调用构造方法 print('{0}:{1}岁{2}'.format(d1.name,d1.age,d1.sex)) print('{0}:{1}岁{2}'.format(d2.name,d2.age,d2.sex)) print('{0}:{1}岁{2}'.format(d3.name,d3.age,d3.sex)) [/code]

实例方法

实例方法与实例变量一样,都是某个实例(或对象)个体特有的方法。定义实例方法时,它的第1个参数也应该是self,这会将当前实例与该方法绑定起来,这也说明该方法属于实例。在调用方法时不需要传入self,类似于构造方法。

[code]class Dog: def __init__(self, name,age,sex='雌性'): self.name=name self.age=age self.sex=sex def run(self): #定义实例方法,只有一个self参数 print("{}在跑...".format(self.name)) def speak(self,sound): #定义实例方法,第1个参数是self,第2个参数是sound print('{}在叫,"{}"'.format(self.name,sound)) dog=Dog('球球',2) #创建对象调用构造方法,省略默认值 dog.run() #在调用时采用"对象.实例方法"形式,不需要传递参数 dog.speak('汪汪汪') #需要传递一个参数sound 输出结果为: 球球在跑... 球球在叫,"汪汪汪" [/code]

类变量

类变量是属于类的变量,不属于单个对象。
例如,有一个Account(银行账户)类,它有三个成员变量:amount(账户金额)、interest_rate (利率)和owner(账户名)。amount和owner对于每一个账户都是不同的,而interest_rate对于所有账户都是相同的。amount和owners是实例变量,interest_rate是所有账户实例共享的变量,它属于类,被称为"类变量"。

[code]class Account: interest_rate=0.0568 def __init__(self,owner,amount): self.owner=owner self.amount=amount account=Account('Tony',800000.0) print('账户名:{0}'.format(account.owner)) #对实例变量通过"对象.实例变量"形式访问 print('账户金额:{0}'.format(account.amount)) print('利率:{0}'.format(Account.interest_rate)) #对象变量通过"类名.类变量"形式访问 输出结果为: 账户名:Tony 账户金额:800000.0 利率:0.0568 [/code]

类方法

类方法与类变量类似,属于类,不属于个体实例。在定义类方法时,它的第1个参数不是self,而是类本身。

[code]class Account: interest_rate=0.0568 def __init__(self,owner,amount): self.owner=owner self.amount=amount @classmethod #定义类方法需要的装饰器,以@开头修饰函数、方法和类,用来约束他们 def interest_by(cls,amt): #cls代表类自身,即Account类 return cls.interest_rate*amt #cls可以直接用Account替换 interest=Account.interest_by(12000.0) #对类方法可以通过"类名.类方法"形式访问 print('计算利息:{0:.4f}'.format(interest)) 输出结果为: 计算利息:681.6000 [/code]

0x05 封装

封装性是面向对象重要的基本特性之一。封装隐藏了对象的内部细节,只保留有限的对外接口,外部调
用者不用关心对象的内部细节,使得操作对象变得简单。例如,一台计算机内部极其复杂,有主板、CPU、硬盘和内存等,而一般人不需要了解它的内部细节。计算机制造商用机箱把计算机封装起来,对外提供了一些接口,如鼠标、键盘和显示器等,使用计算机就变得非常简单。

  • 双下划线表示私有属性
  • 单下划线表示受保护的没用下划线就是公共的
  • 没用下划线就是公共的

私有变量

为了防止外部调用者随意存取类的内部数据(成员变量),内部数据(成员变量)会被封装为"私有变
量"。外部调用者只能通过方法调用私有变量。在默认情况下,Python中的变量是公有的,可以在类的外部访问它们。如果想让它们成为私有变量,则在变量前加上双下画线(__)即可。

[code]class Account: __interest_rate=0.0568 def __init__(self,owner,amount): self.owner=owner self.__amount=amount def desc(self): #在类的内部可以访问私有变量 print("{0}金额:{1}利率:{2}".format(self.owner,self.__amount,Account.__interest_rate)) account=Account('Tony',800000.0) account.desc() print('账户名:{0}'.format(account.owner)) print('账户金额:{0}'.format(account.__amount)) #错误发生,在类的外部不可以访问私有变量 print('利率:{0}'.format(Account.__interest_rate)) #错误发生 #输出结果为: print('账户金额:{0}'.format(account.__amount)) AttributeError: 'Account' object has no attribute '__amount' Tony金额:800000.0利率:0.0568 账户名:Tony [/code]

私有方法

私有方法与私有变量的封装是类似的,在方法前加上双下画线(__)就是私有方法了。

[code]class Account: __interest_rate=0.0568 def __init__(self,owner,amount): self.owner=owner self.__amount=amount def __get_info(self): #定义私有方法 print("{0}金额:{1}利率:{2}".format(self.owner,self.__amount,Account.__interest_rate)) def desc(self): print(self.__get_info()) #在类的内部可以调用私有方法 account=Account('Tony',800000.0) account.desc() account.__get_info() #在类的外部调用私有方法,发生错误 #输出结果为: AttributeError: 'Account' object has no attribute '__get_info' [/code]

属性的使用

为了实现对象的封装,在一个类中不应该有公有的成员变量,这些成员变量应该被设计为私有的,然后通过公有的set(赋值)和get(取值)方法访问。

[code]class Dog: #构造方法 def __init__(self,name,age,sex='雌性'): self.name=name #创建和初始化实例变量name self.__age=age #创建和初始化私有实例变量__age #实例方法 def run(self): print("{}在跑...".format(self.name)) #get方法 def get_age(self): #定义get()方法,返回私有实例变量__age return self.__age #set方法 def set_age(self,age): #定义set()方法,通过age参数更新私有实例变量__age self.__age=age dog=Dog('球球',2) print('狗狗年龄:{}'.format(dog.get_age())) #通过get()方法取值 dog.set_age(3) #通过set()方法赋值 print('修改后狗狗年龄:{}'.format(dog.get_age())) #通过get()方法取值 [/code]

上面的示例中,当外部调用者通过两个公有方法访问被封装的私有成员变量时,会比较麻烦。我们可以在类中定义属性,属性可以替代get()和set()这两个公有方法,在调用时比较简单。

[code]class Dog: def __init__(self,name,age,sex='雌性'): self.name=name self.__age=age #私有变量__age,对应的属性名应该去除前面双下划线之后的名称,即age def run(self): print("{}在跑...".format(self.name)) @property def age(self): #定义age属性的get()方法,使用@property装饰器进行修饰,方法名就是属性名即age return self.__age @age.setter def age(self,age): #定义age属性的set()方法,使用@age.setter装饰器进行修饰,age是属性名 self.__age=age dog=Dog('球球',2) print('狗狗年龄:{}'.format(dog.age)) #可以通过属性取值,访问形式为"实例.属性" dog.age=3 #可以通过属性赋值,访问形式为"实例.属性" print('修改后狗狗年龄:{}'.format(dog.age)) #可以通过属性取值,访问形式为"实例.属性" [/code]

属性本质上就是两个方法,在方法前加上装饰器使得方法成为属性。属性使用起来类似于公有变量,可以在赋值符(=)左边或右边,左边被赋值,右边取值。

0x06 继承

继承性也是面向对象重要的基本特性之一。在现实世界中继承关系无处不在。例如猫与动物之间的关系:猫是一种特殊动物,具有动物的全部特征和行为,即数据和操作。在面向对象中动物是一般类,被称为"父类";猫是特殊类,被称为"子类"。特殊类拥有一般类的全部数据和操作,可称之为子类继承父类语法很简单,定义类时在类的后面使用一对小括号指定它的父类就可以了。

[code]class Animal: #定义父类动物(Animal) def __init__(self,name): self.name=name def show_info(self): return "动物的名字:{0}".format(self.name) def move(self): print("动一动...") class Cat(Animal): #定义子类猫(Cat) def __init__(self,name,age): super().__init__(name) #调用父类构造方法,初始化父类成员变量 self.age=age cat=Cat('Tom',2) cat.move() print(cat.show_info()) [/code]

子类继承父类时只有那些公有的成员变量和方法才可以被继承。

多继承

在Python中,当子类继承多个父类时,如果在多个父类中有相同的成员方法或成员变量,则子类优先继承左边父类中的成员方法或成员变量,从左到右继承级别从高到低。

[code]class Horse: def __init__(self,name): self.name=name def show_info(self): return "马的名字:{0}".format(self.name) def run(self): print("马跑...") class Donkey: def __init__(self,name): self.name=name def show_info(self): return "驴的名字:{0}".format(self.name) def run(self): print("驴跑...") def roll(self): print("驴打滚...") class Mule(Horse,Donkey): def __init__(self,name,age): super().__init__(name) self.age=age m=Mule('骡子',1) m.run() #继承父类Horse方法 m.roll() #继承父类Donkey方法 print(m.show_info()) #继承父类Horse方法 [/code]

方法重写: 如果子类方法名和父类方法名相同,子类方法会覆盖掉父类的方法。

0x07 多态性

多态性也是面向对象重要的基本特性之一。“多态”指对象可以表现出多种形态。同其他语言差不多,父类表示子类,多用于传递参数。

[code]class Animal: def speak(self): print('动物叫,但不知道是哪种动物叫!') class Dog(Animal): def speak(self): print('小狗:旺旺叫...') class Cat(Animal): def speak(self): print('小猫:喵喵叫...') class Car: def speak(self): print('小汽车: 滴滴叫') def start(obj): obj.speak() start(Dog()) start(Cat()) start(Car()) 输出结果为: 小狗:旺旺叫... 小猫:喵喵叫... 小汽车: 滴滴叫 [/code]
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

路过

雷人

握手

鲜花

鸡蛋
文章点评
学习中心
站长自定义文字内容,利用碎片时间,随时随地获取优质内容。