Python 面向对象编程(上篇)
1、 类定义2、 实例3、 打印实例4、 属性5、 private,protected,public6、 继承7、 多态Python🔟:0小白基础之——Python 包和模块使用注意事项
Python9️⃣:0小白基础之——Python十大数据结构
Python8️⃣:0小白基础之——Python 面向对象编程(下篇)
Python7️⃣:0小白基础之——Python 面向对象编程(上篇)
Python6️⃣:0小白基础之——Python函数专题
Python5️⃣:0小白基础之——Python编程习惯专题
Python4️⃣:0小白基础之——流程控制专题
Python3️⃣:0小白基础之——列表专题
Python2️⃣:0小白基础之——字符串专题
Python1️⃣:0小白基础之——数字专题
.
面向对象程序设计思想,首先思考的不是程序执行流程,它的核心是抽象出一个对象,然后构思此对象包括的数据,以及操作数据的行为方法。
1、 类定义
动物是自然界一个庞大的群体,以建模动物类为主要案例论述OOP编程。 Python语言创建动物类的基本语法如下,使用 class
关键字定义一个动物类:
class Animal():
类里面可包括数据,如下所示的 Animal 类包括两个数据: self.name 和 self.speed :
class Animal():def __init__(self,name,speed):self.name = name # 动物名字self.speed = speed # 动物行走或飞行速度
注意到类里面通过系统函数init为类的2个数据赋值,数据前使用 self 保留字。
self 的作用是指名这两个数据是实例上的,而非类上的。
同时注意到init方法的第一个参数也带有 self,所以表明此方法是实例上的方法。
2、 实例
理解什么是实例上的数据或方法,什么是类上的数据,需要先建立 “实例” 的概念,“类” 的概念,如下:
# 生成一个名字叫加菲猫、行走速度8km/h的cat对象cat = Animal('加菲猫',8)# cat 就是 Animal 的实例,也可以一次创建成千上百个实例,如下创建1000只蜜蜂:bees = [Animal('bee'+str(i),5) for i in range(1000)]
总结:自始至终只使用一个类 Animal ,但却可以创建出许多个它的实例,因此是一对多的关系。实例创建完成后,下一步打印它看看:
print(cat)
# <__main__.Animal object at 0x0000022608D71C40>
结果显示它是 Animal 对象,其实打印结果显示实例属性信息会更友好,那么怎么实现呢?
3、 打印实例
只需重新定义一个系统(又称为魔法)函数 __ str __ ,就能让打印实例显示的更加友好:
class Animal():def __init__(self,name,speed):self.name = name # 动物名字self.speed = speed # 动物行走或飞行速度def __str__(self):return '''Animal({0.name},{0.speed}) is printed name = {0.name}speed = {0.speed}'''.format(self)cat = Animal('加菲猫',8)print(cat)# 使用 0.数据名称 的格式,这是类专有的打印格式。
4、 属性
至此,我们都称类里的 name 和 speed 为数据,其实它们有一个专业名称:属性。
同时,上面还有一个问题我们没有回答完全,至此已经解释了实例的属性。那么什么是类上的属性? 如下,在最新 Animal
类定义基础上,再添加一个 cprop 属性,它前面没有 self 保留字:
class Animal():cprop = "我是类上的属性cprop"def __init__(self,name,speed):self.name = name # 动物名字self.speed = speed # 动物行走或飞行速度def __str__(self):return '''Animal({0.name},{0.speed}) is printed name={0.name}speed={0.speed}'''.format(self)cat = Animal('加菲猫',8)print(cat)print(Animal.cprop) # 类上的属性直接使用类引用。print(cat.cprop)# 类上的属性,实例同样可以引用,并且所有的实例都共用此属性值:
Python作为一门动态语言,支持属性的动态添加和删除。 如下 cat 实例原来不存在 color 属性,但是赋值时不光不会报错,相反会直接将属性添加到 cat 上;
那么,如何验证 cat 是否有 color 属性呢?使用内置函数 hasattr。
cat.color = 'green'
hasattr(cat,'color') # cat 已经有color属性
注意:以上添加属性方法仅仅为 cat 实例本身添加,而不会为其他实例添加。
monkey = Animal('大猩猩',2)
hasattr(monkey,'color')
5、 private,protected,public
# 测试私有属性、私有方法class Employee:__company = "程序员"def __init__(self,name,age):self.name = nameself.__age = age # 私有属性def __work(self): # 私有方法print("\n好好工作,赚钱娶媳妇!")print("年龄:{0}".format(self.__age))print(Employee.__company)e = Employee("高淇",18) # 创建对象print(e.name) # 调用 name# print(e.__age) 不能直接调用私有属性print(e._Employee__age) # 调用 agee._Employee__work() # 调用私有方法print(Employee._Employee__company)
注意看到 self.__age 属性,它就是一个私有属性,只能被 Employee 类内的所有方法引用,但是,不能被其他类引用。__work 方法,是一个私有方法,也是只能被 Employee 类内的所有方法引用。
总结: name 属性相当于java的public属性,而 __age 相当于java的private属性。
6、 继承
上面已经讲完了OOP三大特性中的封装性,而继承是它的第二大特性。子类继承父类的所
有 public 和 protected 数据和方法,极大提高了代码的重用性。
现在有个新的需求,要重新定义一个 Cat 猫类,它也有 name 和 speed 两个属性,同时还有 color 和 genre两个属性,打印时只需要打印 name 和 speed 两个属性就行。 因此,基本可以复用基类 Animal ,但需要修改 __speed 属性为受保护( protected ) 的_speed 属性,这样子类都可以使用此属性,而外部还是访问不到它。 综合以上, Cat类的定义如下:
class Animal():cprop = "我是类上的属性cprop"def __init__(self,name,speed):self.name = name # 动物名字self.speed = speed # 动物行走或飞行速度def __str__(self):return '''Animal({0.name},{0.speed}) is printed name={0.name}speed={0.speed}'''.format(self)class Cat(Animal):def __init__(self,name,speed,color,genre):super().__init__(name,speed) # 父类属性self.color = colorself.genre = genre# 只打印 name,speedtest = Cat("飞猪",11,"红色","CatGenre")
以上就是基本的继承使用案例,继承要求基类定义的数据和行为尽量标准、尽量精简,以此提高继承的复用性。
7、 多态
如果说OOP的封装和继承使用起来更加直观易用,那么作为第三大特性的多态,在实践中真正运用起来可就不那么容易。有的读者OOP编程初期,可能对多态的价值体会不深刻,甚至都已经淡忘它的存在。
那么问题就在:多态到底真的有用吗?到底使用在哪些场景?
多态价值很大,使用场景很多,几乎所有的系统或软件,都能看到它的应用。
使用对比法,如果不用多态,方法怎么写;使用多态,又是怎么写。
Python:类的继承,调用父类的属性和方法基础详解