今天我一头扎进了Python的面向对象编程世界,这一路的探索可太有趣啦,收获满满当当,必须马上记录下来!
一、类中的概念:代码世界的神奇基石
(一)面向对象与面向过程:两种奇妙的编程魔法
面向过程编程就像一场按部就班的烹饪秀。想象一下,你手里拿着一份详细的菜谱,上面清楚地写着做菜的每一个步骤。你只要按照这些步骤,一个一个地把对应的"烹饪小任务"(也就是函数)完成,最后就能做出美味的菜肴啦。在这个过程中,你特别关注每一步代码是怎么执行的,就像关注烹饪时先放什么调料、后用多大火候一样。
而面向对象编程呢,则像是一场热闹的厨房派对。在这个派对里,厨师、各种厨具、新鲜的食材都被看作一个个有独特"个性"的"小角色"(也就是对象)。
每个"小角色"都有自己的行为和特点,比如厨师会炒菜,锅铲能翻炒,食材可以被加工。大家在这个做菜的过程中相互配合、互动。它是一种超酷的编程思维,主要是为了解决代码重复利用的问题。就好比把厨房的各种操作和工具都整理成一个个"小模板"(类),在不同的烹饪场景里(软件系统),可以直接用这些"小模板"创造出具体的"帮手"(对象实例),这样就能大大提高开发效率啦!
(二)类与对象:模板和实例的奇妙变身
类是Python里一种超厉害的数据结构,它就像是一个神奇的模板,是从现实世界里各种事物抽象出来的。比如说"人"类,这个类里面可以包含像姓名、年龄这样的"小标签"(属性),还可以有说话、走路这些有趣的"小技能"(方法)。
对象则是根据这个神奇模板创造出来的具体"小生命"。想象一下,"人"类是一个通用的模具,通过这个模具,我们可以创造出"小明"这个具体的人。"小明"就是一个对象,他有自己的姓名、年龄,还能使用"人"类赋予他的说话、走路这些技能。类和对象可是面向对象编程的关键宝贝,只有理解了它们,才能真正走进这个奇妙的编程世界。
(三)面向对象术语:编程世界的专属密码
- 类变量(属性):它就像是班级里的公共用品,在整个由类创建的"小世界"(实例化的对象)里,大家都可以共用。它被定义在类里面,但又在方法的"小天地"之外。通常情况下,它不会被当作某个特定同学(实例变量)的专属物品来使用哦。
- 数据成员:这是一个统称,既包括了像班级公共用品一样的类变量,也包括每个同学自己独有的"小秘密"(实例变量),它们都是用来处理类和它所创建的对象相关的数据的。
- 方法:可以把它想象成每个"小角色"(对象)会的一项特殊技能,在类里被定义成函数的样子。
- 方法重写:当从"长辈"(父类)那里继承来的技能不太符合"晚辈"(子类)的需求时,"晚辈"就可以自己动手改造这个技能,这就是方法重写,也叫方法覆盖。就像爸爸的旧衣服不合身了,孩子可以改一改,让它更适合自己。
- 实例变量:它是每个"小角色"在自己的"小空间"(方法)里定义的变量,只有这个"小角色"自己能使用,别的"小角色"可碰不到。
- 多态:想象一下,你喊一声"跑起来",小狗、小猫、小朋友都开始跑,但它们跑的姿势各不相同。这就像多态,对不同类的对象使用同样的操作,它们会根据自己的特点做出不同的反应。
- 封装:这是一种保护"小秘密"的好办法,把对象内部的一些复杂工作细节都藏起来,只给外面的世界提供一些必要的"小窗口"(接口)。就好比手机,我们平时只用按键和屏幕这些"小窗口"来操作,不用了解手机内部复杂的电路构造,这样既安全又方便。
- 继承:就像孩子会继承爸爸妈妈的一些特点一样,在编程里,派生类可以继承基类的各种"宝贝"(字段和方法)。而且,派生类的对象还能当作基类对象来使用呢。这就像是孩子长大后,在某些场合也能代替父母去做一些事情。我们可以基于普通的类,创建出更有针对性的特殊类对象。
- 实例化:这是从抽象到具体的神奇过程,创建一个类的具体对象,就好像把一个想象中的角色变成了真实存在的"小生命"。
- 对象:它是类定义的数据结构实例,就像一个装满宝贝的小盒子,里面既有像公共用品和个人小秘密一样的类变量、实例变量(数据成员),又有像特殊技能一样的方法。而且这个小盒子还很厉害,可以装下任意数量和类型的数据呢。
二、使用类和实例:让代码世界活起来
(一)类的定义:搭建代码小世界的框架
在Python这个神奇的代码世界里,我们使用class
这个魔法关键字来定义类。类里面的方法和普通的函数定义有点像,但又有个小特别的地方。方法的第一个参数通常是self
,它就像是每个"小角色"(对象)的"自我标识"。通过这个"自我标识","小角色"可以访问和修改自己的"小标签"(属性)。来看看这个例子:
python
class NewClass:
i = 1
j = 2
def Newfunc1(self):
print(1)
def Newfunc2(self):
print(self.i, self.j)
这里的NewClass
就是我们创建的一个类,它有两个"小标签"i
和j
,还有两个"小技能"Newfunc1
和Newfunc2
。在Newfunc2
这个"小技能"里,self
就代表着使用这个技能的具体"小角色",通过它可以访问i
和j
这两个"小标签"。
(二)实例化对象与使用:赋予代码小生命活力
定义好类之后,就到了创造"小生命"(实例化对象)的时候啦!实例化对象就像是从类这个神奇模板里"变"出一个真实存在的"小角色"。创建好"小角色"后,我们就可以让它施展自己的"小技能"(调用对象的方法)来实现各种功能。
这里有个很厉害的"魔法方法"叫__init__
,也叫构造方法。当我们创建新的"小生命"时,Python会偷偷地自动运行这个方法。通过它,我们可以在"小生命"诞生的时候,就给它的"小标签"(属性)赋值,让每个"小生命"都有自己独特的"个性"。比如说:
python
class Humanity:
def __init__(self, name, sex, idcard):
self.name = name
self.sex = sex
self.idcard = idcard
def run(self):
print(f"{self.name}突然就溜了")
def eat(self):
print(f"{self.name}这家伙在吃东西")
def playgame(self):
print(f"{self.name}这货偷偷跑去网吧打游戏去了")
def HumanDes(self):
print(f"性别为{self.sex}的{self.name}出示了身份证:{self.idcard}")
human1 = Humanity("小明", "男", 666666666666)
human1.playgame()
human1.HumanDes()
在这个例子里,我们通过Humanity
类创建了human1
这个"小生命",在创建的时候,就给它的名字、性别和身份证号这些"小标签"都赋了值。然后我们让human1
施展playgame
和HumanDes
这两个"小技能",看看它都做了些什么有趣的事情。
(三)修改属性值:给小生命调整"小标签"
"小生命"(实例化对象)诞生之后,有时候我们需要给它的"小标签"(属性)调整一下。有两种方法可以做到哦。第一种方法就像直接给小朋友换个新的小名牌一样,直接访问实例化对象的属性并修改它。第二种方法则是给"小生命"安排一个特殊的"小任务"(定义一个方法),让它自己去修改"小标签"的值。比如下面这个例子:
python
class Humanity:
def __init__(self, name, sex, idcard):
self.name = name
self.sex = sex
self.idcard = idcard
def change(self, newinfo):
self.idcard = newinfo
human1 = Humanity("小明", "男", 6666666)
human1.change(18888888)
这里我们定义了change
这个"小任务",让human1
通过这个"小任务"把自己的身份证号这个"小标签"的值给改掉了。
(四)私有属性和公有属性:代码小世界的隐私与公开
在Python的代码小世界里,我们平常定义的属性就像是放在公共区域的物品,大家都能直接看到和使用,这就是公有属性。我们可以通过实例化对象名.属性名
这种方式去访问它。
但是,有时候我们也想给"小生命"(对象)的某些"小秘密"(属性或方法)藏起来,不想让别人随便看到和使用。这时候,我们就在变量名或函数名前面加上两个小下划线"__",这样这个方法或变量就变成私有的啦。
虽然在Python里,没有专门的关键字来严格定义私有和公有属性,但是Python会偷偷地把这个"小秘密"的名字改成_类名__变量名
的样子。如果真的有特殊情况,我们也可以通过对象名._类名__变量名
这种方式去访问私有变量和函数,不过最好还是把它们当作真正的"小秘密",不要轻易去触碰哦。
(五)类属性和对象属性:共享与独有的小宝藏
属性的定义方式有两种,这两种方式可有意思啦!一种是类属性,它就像是班级里的公共图书角,属于整个类这个"大家庭"。所有由这个类创建出来的"小生命"(实例)都可以共享这些"图书"(属性值)。它是在类定义的时候直接声明的,我们既可以通过类名,也可以通过实例来访问它。
另一种是对象属性,它是每个"小生命"自己独有的"小宝藏"。每个对象都有自己这一份"小宝藏"的副本,相互之间不会影响。对象属性通常是在类的构造方法__init__
里定义的,通过self
这个"自我标识"来访问和操作。比如下面这个例子:
python
class NewClass:
i = 1
def __init__(self, j):
self.j = j
def newFunc2(self):
print(self.i, self.j)
a = NewClass(2)
b = NewClass(3)
a.newFunc2()
b.newFunc2()
这里的i
就是类属性,j
就是对象属性。a
和b
这两个"小生命"都有自己独立的j
值,但是它们共享i
这个类属性的值。而且,当对象实例刚被创建的时候,它会直接使用类属性的值。
如果我们通过类名去修改类属性的值,所有对象实例看到的类属性值也会跟着改变。
不过,要是某个对象实例自己去修改类属性的值,那这个对象实例就会"偷偷"克隆一份类属性的值,之后不管类属性怎么变,都影响不到这个对象实例里克隆的那份值啦。
三、继承:代码复用的神奇魔法棒
(一)继承的定义:开启代码传承之旅
在编写类的时候,有时候我们会发现新的类和已经存在的某个类很像,就像是在已有的基础上进行升级、细化或者扩展。这时候,就可以使用继承这个神奇的魔法棒啦!
当一个类继承另一个类时,它就像一个聪明的小徒弟,自动学会了师傅(父类)的所有"本领"(属性和方法)。这个新的类就是子类,原来的类就是父类。子类不仅继承了父类的"本领",还能自己再学习一些新的"本领"(定义自己的属性和方法)。比如说:
python
class a:
def afunc(self):
print("这是A类的方法")
class b(a):
def bfunc(self):
print("这是B类的方法")
x = b()
x.afunc()
x.bfunc()
这里的b
类继承了a
类,x
是b
类的一个"小徒弟"(对象)。x
不仅会b
类自己的bfunc
方法,还会a
类的afunc
方法呢。
(二)继承实例:学生类的成长故事
我们之前定义过一个Humanity
类,它就像是一个"人类基础模板",定义了人类通用的属性和方法。现在,我们来定义一个学生类Students
,学生类就像是"人类基础模板"的一个升级版,有自己特有的属性,比如学号,还有特有的方法,比如上课。
在定义学生类的__init__
方法时,我们既可以像复制粘贴一样把父类的属性赋值操作再写一遍,也可以更聪明一点,调用父类的__init__
方法,这样就能减少很多重复的操作啦。就像这样:
python
class Humanity:
def __init__(self, name, sex, idcard):
self.name = name
self.sex = sex
self.idcard = idcard
def run(self):
print(f"{self.name}突然就溜了")
def eat(self):
print(f"{self.name}这家伙在吃东西")
def playgame(self):
print(f"{self.name}这货偷偷跑去网吧打游戏去了")
def HumanDes(self):
print(f"性别为{self.sex}的{self.name}出示了身份证:{self.idcard}")
def change(self, newinfo):
self.idcard = newinfo
class Students(Humanity):
def __init__(self, name, sex, idcard, studentID):
super().__init__(name, sex, idcard)
self.studentID = studentID
def goclass(self):
print(f"学号为{self.studentID}的{self.name}跑去上课了")
hum1 = Students("小明", "男", 123456, 180192)
hum1.goclass()
hum1.playgame()
hum1.HumanDes()
在这个例子里,Students
类继承了Humanity
类。hum1
是Students
类的一个学生"小角色",它不仅会goclass
这个学生特有的方法,还会从Humanity
类继承来的playgame
和HumanDes
这些方法呢。
(三)注意事项:继承路上的小陷阱
当子类继承了父类的属性和方法后,如果子类没有重新编写__init__
这个构造方法,那么在实例化子类的时候,父类的__init__
会自动执行。
这就像孩子如果没有自己特别的起床方式,就会按照爸爸妈妈的起床方式来做一样。如果不注意这个小细节,可能会出现属性赋值不对等各种小问题哦,所以一定要小心呀!
四、组合、内建函数:代码世界的高级工具包
(一)组合:搭建复杂代码城堡
组合是一种很厉害的技巧,就像是用很多小积木搭建一个超级复杂的城堡。在一个类里面,我们可以把其他类当作"小积木"实例化,然后把这些"小积木"组合在一起,形成一个更复杂的对象。比如说:
python
class students:
def __init__(self, studNmus):
self.studNmus = studNmus
class Teachers:
def __init__(self, TeaNums):
self.TeaNums = TeaNums
class Classroom:
def __init__(self, studNmus, TeaNums):
self.student = students(studNmus)
self.teacher = Teachers(TeaNums)
def xprint(self):
print(f"教室有{self.teacher.TeaNums}个老师,{self.student.studNmus}个学生")
a = Classroom(1, 40)
a.xprint()
这里我们用students
类和Teachers
类这两个"小积木",在Classroom
类里搭建出了一个"教室"的场景,通过组合,让代码可以更好地表示复杂的关系。
(二)类方法和静态方法:各司其职的小助手
- 类方法 :它是类对象专属的"小助手",要用
@classmethod
这个神奇的"小贴纸"来标记它。类方法的第一个参数是cls
,它代表着类本身,就像是班级的班长,代表着整个班级。类方法既可以通过类对象来调用,也可以通过实例对象来调用,通常用于操作类属性。比如下面这个例子:
python
class Account:
interest_rate = 0.012
def __init__(self, owner, amount):
self.owner = owner
self.amount = amount
@classmethod
def interest_by(cls, amt):
return cls.interest_rate * amt
account = Account("Tom", 80000.0)
print(f"账户名:{account.owner}")
print(f"账户金额:{account.amount}")
print(f"利率:{Account.interest_rate}")
print(f"{account.owner}的利息:{Account.interest_by(account.amount)}")
在这里,interest_by
就是类方法,通过cls
参数访问类属性interest_rate
,计算出利息。我们既可以用类名Account
调用它,也能用实例account
调用,非常灵活。
- 静态方法 :这是类对象的另一个"小助手",用
@staticmethod
这个"小贴纸"标记。静态方法主要用来存放一些逻辑性的代码,它不依赖于类的属性和方法,就像是一个独立的小工具。它既可以通过类对象调用,也能通过实例对象调用。比如:
python
class A:
def __init__(self, x):
self.x = x
@staticmethod
def staticfunc(x):
print(f"this value is {x}")
def dofunc(self):
self.staticfunc(self.x)
def testfunc(x):
print(x)
b = A(3)
b.dofunc()
b.staticfunc('aaa')
A.staticfunc('gwe')
在这个例子里,staticfunc
就是静态方法,它不关心类的属性,只专注于自己的逻辑处理。b
这个实例可以调用它,类A
本身也能调用。
(三)内建函数:代码世界的万能钥匙
-
issubclass(class, classinfo) :这个函数就像一个"关系探测器",能判断一个类是不是另一个类的子类或子孙类。它还挺"宽容"的,一个类可以被看作是它自己的子类。从Python 2.3版本开始,它的第二个参数可以是由父类组成的元组,只要第一个参数是元组中任意一个类的子类,就会返回
True
。 -
hasattr(object, name) :它是一个"属性小侦探",用来判断某个属性是不是属于一个对象。如果是,就返回
True
,否则返回False
,帮助我们快速了解对象的"装备"情况。 -
getattr(object, name[, default]):这是一个"属性获取器",可以获取对象中某个属性的值。要是属性不存在,它会抛出异常。不过,如果我们给它提供第三个参数,当属性不存在时,就会输出这个默认值,避免程序出错。
-
setattr(object, name, value):它就像一个"属性修改器",可以设定对象的某个属性,让我们能轻松给对象添加或修改"装备"。
-
delattr(object, name):这是"属性删除器",用来删除对象的某个属性,把不需要的"装备"清理掉。
今天在Python面向对象编程的世界里探索了这么多有趣又有用的知识,虽然有些地方理解起来费了点脑筋,但多动手敲代码,感觉一下子就豁然开朗了。
现在我对Python编程的理解更深了,以后写代码肯定能更得心应手!我要继续加油,探索更多编程的奥秘,让自己在代码世界里越来越厉害!