⼀、⾯向对象编程思想
1、什么是⾯向过程(关注的是功能实现的步骤过程)
传统的⾯向过程的编程思想总结起来就⼋个字——⾃顶向下,逐步细化!
→ 将要实现的功能描述为⼀个从开始到结束按部就班的连续的“步骤”
→ 依次逐步完成这些步骤,如果某⼀个步骤的难度较⼤,⼜可以将该步骤再次细化为若⼲个⼦步骤,以 此类推,⼀直到结尾并得到我们想要的结果
2、什么是⾯向对象(关注的是对象本身----万物皆对象)
有动词就⼀定有实现这个动作的实体!
所谓的模拟现实世界,就是使计算机的编程语⾔在解决相关业务逻辑的时候,与真实的业务逻辑的发⽣ 保持⼀致,需要使任何⼀个动作的发⽣都存在⼀个⽀配给该动作的⼀个实体(主体)。
因为在现实世界 中,任何⼀个功能的实现都可以看做是⼀个⼀个的实体在发挥其各⾃的“功能”(能⼒)并在内部进⾏协 调有序的调⽤过程!
3、举个栗⼦:使⽤⾯向对象实现报名系统开发
第⼀步:分析哪些动作是由哪些实体发出的
学⽣提出报名、学⽣提供相关资料、学⽣缴费、学校收费、教师分配教室、班级增加学⽣信息。
于是,在整个过程中,⼀共有四个实体:学⽣、学校、教师、班级!在现实中的⼀个具体的实体,就是计算机编程中的⼀个对象
第⼆步:定义这些实体,为其增加相应的属性和功能
属性就是实体固有的某些特征特性信息,在⾯向对象的术语中,属性就是以前的变量。
⽐如:
⼀个⼈的属性有:身⾼、体重、姓名、年龄、学历、电话、籍贯、毕业院校等
⼀个⼿机的属性有:价格、品牌、操作系统、颜⾊、尺⼨等
功能就是就是实体可以完成的动作,在⾯向对象的术语中,功能就是封装成了函数或⽅法
第三步:让实体去执⾏相应的功能或动作
学⽣提出报名、学⽣提供相关资料、教师登记学⽣信息、学⽣缴费、学校收费、教师分配教室、班级增加学⽣信息
4、⾯向对象编程思想迁移
以前写代码,⾸先想到的是需要实现什么功能——调⽤系统函数,或者⾃⼰⾃定义函数,然后按部就班 的执⾏就⾏了!
以后写代码,⾸先想到的是应该由什么样的主体去实现什么样的功能,再把该主体的属性和功能统⼀的 进⾏封装,最后才去实现各个实体的功能。
注意:⾯向对象并不是⼀种技术,⽽是⼀种思想,是⼀种解决问题的最基本的思维⽅式!
⾯向对象的核⼼思想是:不仅仅是简单的将功能进⾏封装(封装成函数),更是对调⽤该功能的 主体进⾏封装,实现某个主体拥有多个功能,在使⽤的过程中,先得到对应的主体,再使⽤主体去实现 相关的功能!
5、⾯向对象与⾯向过程的区别
① 都可以实现代码重⽤和模块化编程,⾯向对象的模块化更深,数据也更封闭和安全
② ⾯向对象的思维⽅式更加贴近现实⽣活,更容易解决⼤型的复杂的业务逻辑
③ 从前期开发的⻆度来看,⾯向对象⽐⾯向过程要更复杂,但是从维护和扩展的⻆度来看,⾯向对象 要远⽐⾯向过程简单!
④ ⾯向过程的代码执⾏效率⽐⾯向对象⾼
⼆、⾯向对象的基本概念
1、⾯向对象中两个⽐较重要概念
对象:object,现实业务逻辑的⼀个动作实体就对应着OOP编程中的⼀个对象!
所以:① 对象使⽤属性(property)保存数据!② 对象使⽤⽅法(method)管理数据!
类:对象的产⽣:在Python中,采⽤类(class)来⽣产对象,
对象的属性和⽅法的规定:⽤类来规定对象的属性和⽅法。
也就是说,在Python 中,要想得到对象,必须先有类!
引入类概念的原因:类本来就是对现实世界的⼀种模拟,在现实⽣活中,任何⼀个实体都有⼀个类 别,类就是具有相同或相似属性和动作的⼀组实体的集合!所以,在Python中,对象是指现实中的⼀个 具体的实体,⽽既然现实中的实体都有⼀个类别,所以,OOP中的对象也都应该有⼀个类!
⼀个对象的所有应该具有特征特性信息,都是由其所属的类来决定的,但是每个对象⼜可以具有不同的 特征特性信息,⽐如,我⾃⼰(⼈类)这个对象,名字叫张三,性别男,会写代码,会教书;另⼀个对 象(⼈类)可能叫李四,性别男,会演戏,会唱歌!
2、类的定义
在Python中,我们可以有两种类的定义⽅式:Python2(经典类)和 Python3(新式类)
经典类:不由任意内置类型派⽣出的类,称之为经典类
class 类名:
# 属性
# 方法
新式类:
class 类名(object):
# 属性
# 方法
类名的规则:类名既可以使⽤⼤写形式也可以使⽤⼩写形式,遵守⼀ 般的标识符的命名规则(以字⺟、数字和下划线构成,并且不能以数字开头),⼀般为了和⽅法名相区 分,类名的⾸字⺟⼀般⼤写!(⼤驼峰法
3、类的实例化(创建对象)
类的实例化就是把抽象的事务具体为现实世界中的实体。
类的实例化就是 通过类得到对象。
Python 类只是对象的⼀种规范,类本身基本上什么都做不了,必须利⽤类得到对象,这个过程就叫作类的实例 化!
基本语法:
对象名 = 类名()
在其他的编程语⾔中,类的实例化⼀般是通过new关键字实例化⽣成的,但是在Python中,我们不需要
new关键字,只需要类名+()括号就代表类的实例。
示例:
# 1.定义一个类
class Person(object):
# 定义一个相关方法
def eat(self):
print('吃零食')
def drink(self):
print('喝可乐')
# 2.实例化对象
p1 = Person()
# 3,调用类中的方法
p1.eat()
p1.drink()
#类是⼀个抽象概念,在定义时,其并不会真正的占⽤计算机的内存空间。但是对象是⼀个具体的事务,
#所以其要占⽤计算机的内存空间
4、类中的self关键字
self也是Python内置的关键字之⼀,其指向了 类实例对象本身。
# 1、定义⼀个类
class Person():
# 定义⼀个⽅法
def speak(self):
print(self)
print('Nice to meet you!')
# 2、类的实例化(⽣成对象)
p1 = Person()
print(p1)
p1.speak()
p2 = Person()
print(p2)
p2.speak()
总结:类中的self就是谁实例化了对象,其就指向谁。相当于其他编程语⾔中的“this”关键字
三、对象的属性添加与获取
1、什么是属性
在Python中,任何⼀个对象都应该由两部分组成:属性 + ⽅法
属性即是特征,⽐如:
⼈的姓名、年龄、身⾼、体重…都是对象的属性。
⻋的品牌、型号、颜⾊、载重量...都是对象的属性。
对象属性既可以在类外⾯添加和获取,也能在类⾥⾯添加和获取。
2、在类的外⾯添加属性和获取属性
添加:
对象名.属性=属性值
获取:在Python中,获取对象属性的⽅法我们可以通过 对象名 . 属性 来获取
# 定义一个person类
class Person(object):
pass
# 实例化Person类,生成p1对象
p1 = Person()
# 为p1添加属性
p1.name = '张三'
p1.age = 20
p1.local = '大山'
# 获取p1对象的属性
print(f"姓名:{p1.name},年龄:{p1.age},地点:{p1.local}")
3、在类的内部获取外部定义的属性
# 定义一个person类
class Person(object):
def speak(self):
print(f"姓名:{p1.name},年龄:{p1.age},地点:{p1.local}")
# 实例化Person类,生成p1对象
p1 = Person()
# 为p1添加属性
p1.name = '张三'
p1.age = 20
p1.local = '大山'
# 调用函数speak
p1.speak()
问题:⽬前我们的确可以通过 对象 . 属性 的⽅式设置或获取对象的属性,但是这种设置属性的 ⽅式有点繁琐,每次定义⼀个对象,就必须⼿⼯为其设置属性,在我们⾯向对象中,对象的属性能不能 在实例化对象时,直接进⾏设置呢?
可以,但是需要使⽤魔术⽅法
四、魔术⽅法
1、什么是魔术⽅法
魔术变量: __name__ , __file__ 这些都是魔术变量(拥有特殊功能的变量)
在Python中, __xxx__() 的函数叫做魔法⽅法,指的是具有 特殊功能 的函数。
魔术⽅法都有⾃⼰的触发条件:
__init__() 当实例化对象时,其会⾃动被触发(被调⽤)
__del__() 当⼿⼯删除对象或对象被销毁时,其会⾃动被触发(被调⽤)
2、 __init__() ⽅法(初始化⽅法或构造⽅法)
思考:⼈的姓名、年龄等信息都是与⽣俱来的属性,可不可以在⽣产过程中就赋予这些属性呢?
答:可以,使⽤ __init__() ⽅法,
其作⽤:实例化对象时,连带其中的参数,会⼀并传给 `__init__` 函数⾃动并执⾏它。 __init__() 函数的参数列表会在开头多出⼀项,它永远指代新建的那个 实例对象,Python语法要求这个参数必须要有,名称为self。
# 定义一个类
class Person(object):
# 初始化实例对象属性
def __init__(self,name,age,add):
# 赋予name属性、age属性、add属性给实例化对象本身
# self.实例化对象属性 = 参数
self.name = name
self.age = age
self.add = add
# 实例化对象并传入初始化属性值
p1 = Person('张三',20,'大山')
# 调用p1对象自身属性 name与age
print(p1.name)
print(p1.age)
① _init_()⽅法,在创建⼀个对象时默认被调⽤,不需要⼿动调⽤ Python
② _init_(self)中的self参数,不需要开发者传递,python解释器会⾃动把当前的对象引⽤传递过去。
3、 __str__() ⽅法
当使⽤print输出对象的时候,默认打印对象的内存地址。
如果类定义了 __str__ ⽅法,那么就会打印 从在这个⽅法中 return 的数据。(另外要特别注意__str__⽅法返回 字符串类型 的数据) 没有使⽤ __str__() ⽅法的类:
# 定义一个类
class Person(object):
# 初始化实例对象属性
def __init__(self,name,age,add):
# 赋予name属性、age属性、add属性给实例化对象本身
# self.实例化对象属性 = 参数
self.name = name
self.age = age
self.add = add
# 定义一个__str__内置魔术方法,用于输出信息
def __str__(self):
return f"姓名:{self.name},年龄:{self.age},地点:{self.add}"
# 实例化对象并传入初始化属性值
p1 = Person('张三',20,'大山')
print(p1)
① __str__ 这个魔术⽅法是在类的外部,使⽤print(对象)时,⾃动被调⽤的
② 在类的内部定义 __str__ ⽅法时,必须使⽤return返回⼀个字符串类型的数据
4、 __del__() ⽅法(删除⽅法或析构⽅法)
__init__⽅法与__del__⽅法是⼀对
当删除对象时(调⽤del删除对象或者⽂件执⾏结束后),python解释器会⾃动调⽤ 法。 __del__() ⽅
class Person(object):
# 构造函数__init__
def __init__(self,name,age):
self.name = name
self.age = age
# 构造函数__del__
def __del__(self):
print(f"{self}对象已被删除")
# 实例化对象
p1 = Person('张三',10)
# 删除对象p1
del p1
__del__() ⽅法在使⽤过程中,⽐较简单,但是其在实际开发中,有何作⽤呢?
答:主要⽤于关闭⽂件操作、关闭数据库连接等等。
5、总结
提到魔术⽅法:① 这个⽅法在什么情况下被触发 ② 这个⽅法有什么实际的作⽤
__init__() :初始化⽅法或者称之为“构造函数”,在对象初始化时执⾏,其主要作⽤就是在对象初 始化时,对对象进⾏初始化操作(如赋予属性)
__str__() :对象字符串⽅法,当我们在类的外部,使⽤print⽅法输出对象时被触发,其主要功能就 是对对象进⾏打印输出操作,要求⽅法必须使⽤return返回 字符串 格式的数据。
__del__() :删除⽅法或者称之为“析构⽅法”,在对象被删除时触发(调⽤del删除对象或⽂件执⾏ 结束后),其主要作⽤就是适⽤于关闭⽂件、关闭数据库连接等等。
五、⾯向对象的三⼤特性
1、⾯向对象有哪些特性
三种:封装性、继承性、多态性
2、继承性
1.什么是继承
我们接下来来聊聊Python代码中的“ 继承” :类是⽤来描述现实世界中同⼀组事务的共有特性的抽象模 型,但是类也有上下级和范围之分,⽐如:⽣物 => 动物 => 哺乳动物 => 灵⻓型动物 => ⼈类 => ⻩种 ⼈
如果⼀个类A使⽤了另⼀ 个类B的成员(属性和⽅法),我们就可以说A类继承了B类,同时这也体现了OOP中 代码重⽤的特性 !
2.继承的基本语法
假设A类要继承B类中的所有属性和⽅法(私有属性和私有⽅法除外)
class B(object):
pass
class A(B):
pass
a = A()
a.B中的所有公共属性
a.B中的所有公共⽅法
3.与继承相关的⼏个概念
继承:⼀个类从另⼀个已有的类获得其成员的相关特性,就叫作继承!
派⽣:从⼀个已有的类产⽣⼀个新的类,称为派⽣!
很显然,继承和派⽣其实就是从不同的⽅向来描述的相同的概念⽽已,本质上是⼀样的!
⽗类:也叫作基类,就是指已有被继承的类!
⼦类:也叫作派⽣类或扩展类
扩展:在⼦类中增加⼀些⾃⼰特有的特性,就叫作扩展,没有扩展,继承也就没有意义了!
单继承:⼀个类只能继承⾃⼀个其他的类,不能继承多个类,单继承也是⼤多数⾯向对象语⾔的特 性!
多继承:⼀个类同时继承了多个⽗类, (C++、Python等语⾔都⽀持多继承)
4.单继承
单继承:⼀个类只能继承⾃⼀个其他的类,不能同时继承多个类。这个类会有具有⽗类的属性和⽅法。
基本语法:
# 1、定义⼀个共性类(⽗类)
class Person(object):
pass
# 2、定义⼀个个性类(⼦类)
class Student(Person):
pass
示例:
# ⽐如汽⻋可以分为两种类型(汽油⻋、电动⻋
# 1、定义⼀个共性类(⻋类)
class Car(object):
def run(self):
print('i can run')
# 2、定义汽油⻋
class GasolineCar(Car):
pass
# 3、定义电动⻋
class EletricCar(Car):
pass
bwm = GasolineCar()
bwm.run()
5.单继承特性(多层继承):传递性
在Python继承中,如A类继承了B类,B类⼜继承了C类。则根据 继承的传递性,则A类也会⾃动继承C类 中所有属性和⽅法(公共)
class C(object):
def func(self):
print('我是C类中的相关⽅法func')
class B(C):
pass
class A(B):
pass
a = A()
a.func()
6.多继承(多重继承)
什么是多继承?
Python语⾔是少数⽀持多继承的⼀⻔编程语⾔,所谓的多继承就是允许⼀个类同时继承⾃多个类的特 性。
基本语法:
class B(object):
pass
class C(object):
pass
class A(B, C):
pass
a = A()
a.B中的所有属性和⽅法
a.C中的所有属性和⽅法
注意:虽然多继承允许我们同时继承⾃多个类,但是实际开发中,应尽量避免使⽤多继承,因为如果两 个类中出现了相同的属性和⽅法就会产⽣命名冲突。
7.子类扩展
扩展特性:继承让⼦类继承⽗类的所有公共属性和⽅法,但是如果仅仅是为了继承公共属性和⽅法,继 承就没有实际的意义了,应该是在继承以后,⼦类应该有⼀些⾃⼰的属性和⽅法。
什么是重写?
重写也叫作 覆盖,就是当⼦类成员与⽗类成员名字相同的时候,从⽗类继承下来的成员会重新定义! 此时,通过⼦类实例化出来的对象访问相关成员的时候,真正其作⽤的是⼦类中定义的成员!
class Father(object):
属性
⽅法
class Son(Father):
⽗类属性和⽅法
⾃⼰的属性和⽅法(如果⼦类中的属性和⽅法与⽗类中的属性或⽅法同名,则⼦类中的属性或
⽅法会对⽗类中同名的属性或⽅法进⾏覆盖(重写))
重写⽗类中的⽅法以后,此时⽗类中的⽅法还在,只不过是在其⼦类中找不到了。类⽅法的调⽤顺序,当我们在⼦类中重构⽗类的⽅法后,Cat ⼦类的实例先会在⾃⼰的类 Cat 中查找该⽅法,当找不到该⽅法时才会去⽗类 Animal 中查找对应的⽅ 法。
8.super()调⽤⽗类属性和⽅法
super():调⽤⽗类属性或⽅法,
完整写法: super( 当前类名 , self). 属性或⽅法 () ,在Python3以 后版本中,调⽤⽗类的属性和⽅法我们只需要使⽤ super(). 属性 或 super(). ⽅法名 () 就可以完 成调⽤了。
super().__init__(父类中的属性)
示例:
# 父类:汽车
class Car(object):
# 初始化,构造方法
def __init__(self, brand, model, color):
self.brand = brand # 品牌
self.model = model # 型号
self.color = color # 颜色
def run(self): # 方法,行驶
print('i can run')
class ElectricCar(Car): # 子类:电动车
# 重写构造方法
def __init__(self, brand, model, color, battery):
super().__init__(brand, model, color) # 调用父类的构造方法
self.battery = battery # 电池属性
def run(self): # 重写 run 方法
print(f'i can run with electric, i have a {self.battery} kwh battery')
tesla = ElectricCar('特斯拉', 'Model S', '红色', 70)
tesla.run()
3、封装性
在Python代码中,封装有两层含义:
① 把现实世界中的主体中的属性和⽅法书写到类的⾥⾯的操作即为封装
class Person():
# 封装属性
# 封装⽅法
② 封装可以为属性和⽅法添加为私有权限,不能直接被外部访问
封装中的私有属性和私有⽅法
在⾯向对象代码中,我们可以把属性和⽅法分为两⼤类:公有(属性、⽅法)、私有(属性、⽅法)
Python:公有(属性、⽅法),私有(属性、⽅法)
Java:公有(属性、⽅法),受保护(属性、⽅法),私有(属性、⽅法)
公有属性和公有⽅法:⽆论在类的内部还是在类的外部我们都可以对属性和⽅法进⾏操作。
但是有些情况下,我们不希望在类的外部对类内部的属性和⽅法进⾏操作。我们就可以把这个属性或⽅ 法封装成私有形式。
私有属性的访问限制
设置私有属性和私有⽅法的⽅式⾮常简单:在属性名和⽅法名 前⾯ 加上两个下划线 __ 即可。
基本语法:
class Girl():
def __init__(self, name):
self.name = name
self.__age = 18 # 私有属性,外部无法直接访问
xiaomei = Girl('小美')
print(xiaomei.name) # 正常访问公有属性
print(xiaomei.__age) # 报错,提示 Girl 对象没有 __age 属性
类 中的私有属性和私有⽅法,不能被其⼦类继承。 另外 由以上代码运⾏可知,私有属性不能在类的外部被直接访问。
私有属性设置与访问"接⼝"
外部可以通过特定的"接⼝"来实现对私有属性的⽅法。
接⼝就是我们通常说的⼀个函数,这个函数可以实现对某些属性的访问(设置与获取)
在Python中,⼀般定义函数名' get_xx '⽤来获取私有属性,定义' set_xx '⽤来修改私有属性值。
class Girl():
def __init__(self, name):
self.name = name
self.__age = 18 # 私有属性
# 公共方法:提供给外部的访问接口
def get_age(self):
# 内部访问:允许直接访问
# 外部访问:根据需求要添加限制条件
return self.__age
# 公共方法:提供给外部的设置接口
def set_age(self, age):
self.__age = age
# 测试代码
girl = Girl('小美')
girl.set_age(19)
print(girl.get_age()) # 输出:19
私有⽅法
私有⽅法的定义⽅式与私有属性基本⼀致,在⽅法名的前⾯添加两个下划线__ ⽅法名 ()
封装性的意义
① 以⾯向对象的编程思想进⾏项⽬开发 __ ⽅法名 ()
② 封装数据属性:明确的区分内外,控制外部对隐藏的属性的操作⾏为(过滤掉异常数据)
③ 私有⽅法封装的意义:降低程序的复杂度
4、多态性
1、什么是多态
多态指的是⼀类事物有多种形态。
定义:多态是⼀种使⽤对象的⽅式,⼦类重写⽗类⽅法,调⽤不同⼦类对象的相同⽗类⽅法,可以产⽣ 不同的执⾏结果。
不同对象 => 使⽤相同⽅法 => 产⽣不同的执⾏结果。
① 多态依赖继承(不是必须的) ② ⼦类⽅法必须要重写⽗类⽅法
⾸先定义⼀个⽗类,其可能拥有多个⼦类对象。当我们调⽤⼀个公共⽅法(接⼝)时,传递的对象不 同,则返回的结果不同。
好处:调⽤灵活,有了多态,更容易编写出通⽤的代码,做出通⽤的编程,以适应需求的不断变化!
2、多态性的原理
公共接⼝service就是多态的体现,随着传⼊动物对象的不同,能返回不同的结果。
3、多态代码实现
多态:可以基于继承也可以不基于继承
'''
首先定义一个父类,其可能拥有多个子类对象。当我们调用一个公共方法(接口)时,传递的对象不同,则返回的结果不同。
'''
class Fruit(object): # 父类 Fruit
def makejuice(self):
print('i can make juice')
class Apple(Fruit): # 子类:苹果
# 重写父类方法
def makejuice(self):
print('i can make apple juice')
class Banana(Fruit): # 子类:香蕉
# 重写父类方法
def makejuice(self):
print('i can make banana juice')
class Orange(Fruit): # 子类:橘子
# 重写父类方法
def makejuice(self):
print('i can make orange juice')
# 定义一个公共接口(专门用于实现榨汁操作)
def service(obj):
# obj 要求是一个实例化对象,可以传入苹果对象/香蕉对象
obj.makejuice()
# 调用公共方法
service(Orange()) # 输出:i can make orange juice
扩展
(1)+ 多态体现 +加号只有⼀个,但是不同的对象调⽤+⽅法,其返回结果不同。
如果加号的两边都是数值类型的数据,则加号代表运算符
如果加号的两边传⼊的是字符串类型的数据,则加号代表合并操作,返回合并后的字符串 'a' + 'b' = 'ab' 如果加号的两边出⼊序列类型的数据,则加号代表合并操作,返回合并后的序列 [1, 2, 3] + [4, 5, 6] = [1, 2, 3, 4, 5, 6]
5、总结
特性 | 含义 | 关键点 | Python 实现方式 | 示例 |
---|---|---|---|---|
封装 (Encapsulation) | 将数据和操作数据的方法绑定在一起,隐藏对象内部实现细节,只暴露必要接口 | 保护数据安全,避免被随意修改 | 使用类定义属性和方法;通过私有属性(__或_开头)实现隐藏 | class Person: def init(self, name): self.__name = name # 私有属性 def get_name(self): return self.__name |
继承 (Inheritance) | 子类可以继承父类的属性和方法,实现代码复用与扩展 | 支持单继承、多继承;可以重写父类方法 | 定义类时指定父类 class subclass(Parent) | class Animal: def speak(self): print('Animal sound') class Dog(Animal): def speak(self): print('woof') |
多态 (Polymorphism) | 同一接口,不同实现;不同对象可以以相同方式调用方法,体现出行为多样性 | 方法各相同,但不同类中有不同实现 | 通过方法重写实现 | def make_sound(animal): animal.speak() make_sound(Dog()) # woof! make_sound(Animal()) # Animal sound |
综合理解:
封装是基础,⽤于组织数据和逻辑;
继承是⼿段,⽤于构建类之间的关系;
多态是能⼒,让程序更具扩展性和灵活性。
六、⾯向对象其他特性
1、类属性
Python中,属性可以分为 实例属性 和 类属性 。
类属性就是 类对象中定义的属性,它被该类的所有实例对象所共有。通常⽤来记录 与这类相关 的特 征,类属性 不会⽤于记录 具体对象的特征。
在Python 中,⼀切皆对象。类也是⼀个特殊的对象,我们可以单独为类定义属性。
class Person(object):
# 定义类属性
count = 0
def __init__(self, name, age):
self.name = name
self.age = age
# 创建实例对象
p1 = Person('Tom', 23)
p2 = Person('Harry', 26)
2、类属性代码实现
class Person(object):
# 定义类属性count,用于记录生成的Person类对象的个数
count = 0
# 定义一个__init__魔术方法,用于进行初始化操作
def __init__(self, name):
self.name = name
# 对count类属性进行+1操作,用于记录这个Person类一共生成了多少个对象
Person.count += 1
# 1、实例化对象
p1 = Person('Tom')
p2 = Person('Harry')
p3 = Person('Jennifer')
# 2、在类外部输出类属性
print(f'我们共使用Person类生成了{Person.count}个实例对象')
3、类⽅法
为什么需要类⽅法,在⾯向对象中,特别强调数据封装性。所以不建议直接在类的外部对类属性进⾏直 接获取。所以我们如果想操作类属性,建议使⽤类⽅法。
class Tool(object):
# 定义一个类属性count
count = 0
# 定义一个__init__初始化方法
def __init__(self, name):
self.name = name
Tool.count += 1
# 封装一个类方法:专门实现对Tool.count类属性进行操作
@classmethod # 声明为类方法,用于对类属性进行操作
def get_count(cls): # cls代表类对象
print(f'我们使用Tool类共实例化了{cls.count}个工具')
# 实例化对象
t1 = Tool('斧头')
t2 = Tool('榔头')
t3 = Tool('铁锹')
# 调用类方法
Tool.get_count()
类 ⽅法主要⽤于操作类属性或类中的其他⽅法。
4、静态⽅法
在开发时,如果需要在类中封装⼀个⽅法,这个⽅法:
① 既 不需要访问实例属性或者调⽤实例⽅法
② 也 不需要访问类属性或者调⽤类⽅法
这个时候,可以把这个⽅法封装成⼀个静态⽅法
# 开发一款游戏
class Game(object):
# 开始游戏,打印游戏功能菜单
@staticmethod # 修饰符,声明为静态方法,无需传递self参数,直接使用类名即可,无需实例化对象
def menu(): # 静态方法
print('1、开始游戏')
print('2、游戏暂停')
print('3、退出游戏')
# 开始游戏、打印菜单
Game.menu() # 调用静态方法,无需实例化对象,直接使用类名即可
区别:
类属性:适⽤于所有实例共享的数据。---数据共享
类⽅法:⽤于操作类相关逻辑,⽀持继承,适合⼯⼚模式。
静态⽅法:逻辑归属类但不依赖类或实例的状态,提升代码可读性和复⽤性。