Python 从入门到进阶之路(五)
之前的文章我们简单介绍了一下 Python 的函数,本篇文章我们来看一下 Python 中的面向对象。
Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。
面向对象技术简介
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 方法:类中定义的函数。
- 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
- 局部变量:定义在方法中的变量,只作用于当前实例的类。
- 实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
- 实例化:创建一个类的实例,类的具体对象。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
和其它编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制。
Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。
对象可以包含任意数量和类型的数据。
Python 中定义类的方法是以 class k开头,我们先定义一个类:
class Cat:
def eat(self):
print("猫吃鱼") cat = Cat()
cat.eat() # 猫吃鱼
如上 ,我们定义了一个 Cat 类,里面定义了一个方法,我们可以通过 变量=类名() 的方式来实例化一个类,这样我们就可以调用类里面的属性和方法,所以当我们调用 cat.eat() 时输出打印 Cat 类里面的 eat() 方法。
在上面的 eat() 方法中,我们默认穿了一个 self 的参数,它代表该类的实例,不一定非叫 self ,可以叫 xxx,只是我们约定俗成叫 self,跟 *args 和 **kwargs 一个道理,那该如何理解这个 self 呢,如下:
class Cat:
def eat(self):
print(self.name+"吃鱼") tom = Cat()
tom.name = "Tom"
tom.eat() # Tom吃鱼 jerry = Cat()
jerry.name = "Jerry"
jerry.eat() # Jerry吃鱼
在上面的代码中,我们定义了两个 Cat 的实例,并且在每个实例中都添加了一个 name 属性,如果我们想要在 eat() 方法中输出各自定义的 name 值,我们可以通过 self 属性来定义,因为 self 就表示该类的实例,所以就会去拿各自实例里面的 name 值。
上面的代码中我们可以实现输出不同的 name 值,但是需要我们在实例化后自己定义 name,我们也可以在定义类的时候就将 name 值传入来做:
class Cat:
def __init__(self,name):
self.name = name
def eat(self):
print(self.name+"吃鱼") tom = Cat("Tom")
tom.eat() # Tom吃鱼 jerry = Cat("Jerry")
jerry.eat() # Jerry吃鱼
上面的代码中,我们在 Cat 类中定义了一个 __init__() 的方法,该方法是类自带的方法,第一个参数必须为 self,我们可以在里面定义自己所需的变量。如上,我们在实例化 Cat 类的时候就将 Tom ,Jeery 传入,然后在 self 形参后面添加形参,该形参与传入参数的顺序意义对应,这样我们就可以使用传入的参数了,定义和使用时需要在前面加 self.
在上面的代码演示中,我们可以看出当我们实例化一个类之后,就能调用该类的方法,这种方法叫公有方法,还有一种方法叫私有方法,就是实例化后不能被调用,只有自己内部可以调用,如下:
class Cat:
def __init__(self,name):
self.name= name
def eat(self):
print(self.name+"吃鱼")
self.__run()
def __run(self):
print("私有方法") tom = Cat("Tom")
tom.eat() # Tom吃鱼 私有方法
tom.__run() # AttributeError: 'Cat' object has no attribute '__run'
上面的代码中当我们实例化 tom 后,可以通过 eat() 方法调用到 __run() 方法,但是直接调用 __run() 会报错。
不仅私有方法不能被调用,私有属性也不能,如下:
class Cat:
age = 11
__height = 120
def add(self):
self.age += 1
self.__height += 1 tom = Cat()
tom.add()
print(tom.age) #
print(tom.__height) # AttributeError: 'Cat' object has no attribute '__height'
接下来我们看一下类中的继承,在上面的代码中我们定义了一个 Cat 的类,里面有一个 eat() 方法,当我们定义一个 Dog 类时,它也有一个 eat() 方法,而且 eat() 方法是一样的,现在 Cat 类有一个 bark() 方法,Dog 类里也有一个 bark() 方法,但是这两个方法执行的结果不一样,而且 Dog 类里有一个 swim() 方法,而 Cat 里没有,如果我们都分别定义这两个类的话,代码会很长,而且如果两个相同的 eat() 方法需要修改时需要修改两个地方,这时我们可以用继承的方式解决,如下:
class Animal:
def eat(self):
print("吃吃吃") class Cat(Animal):
def bark(self):
print("喵喵喵") class Dog(Animal):
def bark(self):
print("汪汪汪") def swim(self):
print("狗刨式") cat = Cat()
cat.eat() # 吃吃吃
cat.bark() # 喵喵喵
cat.swim() # AttributeError: 'Cat' object has no attribute 'swim' dog = Dog()
dog.eat() # 吃吃吃
dog.bark() # 汪汪汪
dog.swim() # 狗刨式
我们将 Cat 类和 Dog 类相同的 eat() 方法定义在了 Animal 类里,然后在创建 Cat 和 Dog 类时添加了 (Animal),意思是继承 Animal 类,这样我们在实例化 Cat 和 Dog 类后就能调用 Animal 类里的方法 eat(),而且还能调用各自实例里的 bark() 方法,但是如果没有另一个类,则不能使用该类的方法,如 cat 调用 dog 的 swim() 方法就会报错。
当然我们可以让 Cat 类也继承 Dog 类,如下:
class Animal:
def eat(self):
print("吃吃吃")
# Cat 类要想继承 Dog 类必须写在 Dog 类后面
# class Cat(Dog,Animal):
# def bark(self):
# print("喵喵喵") class Dog(Animal):
def bark(self):
print("汪汪汪")
def swim(self):
print("狗刨式") class Cat(Dog,Animal):
def bark(self):
print("喵喵喵") cat = Cat()
cat.eat() # 吃吃吃
cat.bark() # 喵喵喵
cat.swim() # 狗刨式 dog = Dog()
dog.eat() # 吃吃吃
dog.bark() # 汪汪汪
dog.swim() # 狗刨式
如上,我们可以让 Cat 同时继承 Dog 和 Animal 两个类,但是如若想要继承某类,必须先创建该类。
我们也可以多重继承,即让 Animal 类也继承某类,这样 Cat 和 Dog 如果继承了 Animal 类,那么也可以使用 Animal 类继承的父类的属性和方法。
只得注意的是私有属性和方法不能被继承,因为私有属性和方法只能在自己的类中使用。
接下来我们看一下类中方法的重写:
class Animal:
def eat(self):
print("吃吃吃") class Cat(Animal):
pass class Dog(Animal):
def eat(self):
print("大口大口吃") cat = Cat()
cat.eat() # 吃吃吃 dog = Dog()
dog.eat() # 大口大口吃
在上面的代码中,我们让 Cat 和 Dog 类都继承了 Animal 类,但是在 Dog 类中,我们定义了一个和 Animal 类中一样的方法名,但是执行的结果不一样,当我们分别调用实例化的 cat 和 dog 的 eat() 方法时,Cat 类由于没有自己的 eat() 方法,所以向上寻找,发现继承的 Animal 类中有 eat() 方法,所以就调用了 Animal 类中的 eat() 方法,但是 Dog 类中有 eat() 方法,所以就调用自己的 eat() 方法,不在向上寻找,这就是类中方法的重写。
在上面我们说过了类属性和实例方法,接下来我们来看一下类方法:
class Cat:
# 类属性
age = 10 # 实例方法
def __init__(self):
self.name = "Tom" def info(self):
print(self.name, self.age) # 类方法
@classmethod
def addAge(cls):
cls.age = 22 tom = Cat()
tom.info() # Tom 10
Cat.info() # TypeError: info() missing 1 required positional argument: 'self' tom.addAge()
print(tom.age) #
print(Cat.age) # Cat.addAge()
print(tom.age) #
print(Cat.age) #
如果我们在类里面的方法前面加 @classmethod,就表明该方法为类方法,在说类方法前我们再来看一下实例方法。
当我们实例化一个 tom 后,我们就可以调用 tom 里面的实例方法,我们之前说过 self 指的是该类的实例化,所以当我们调用 tom.info() 时能正常调用,但是 Cat.info() 时则会报错,因为里面的 self 指向的是实例化的 tom,而不是 Cat 类,所以会报错。
在类方法中,我们同样谣传一个默认的形参,默认叫 cls,它指向的是类本身,而不是该类的实例化,所以我们可以通过 cls.age=22 来更改类里面的类属性,而且类方法 addAge() 可以使用实例化的 tom 来调用,也可以使用 Cat 类本身来调用。
Python 从入门到进阶之路(五)的更多相关文章
- Python 从入门到进阶之路(一)
人生苦短,我用 Python. Python 无疑是目前最火的语言之一,在这里就不再夸他的 NB 之处了,本着对计算机编程的浓厚兴趣,便开始了对 Python 的自学之路,并记录下此学习记录的心酸历程 ...
- Python 从入门到进阶之路(三)
在之前的文章我们介绍了一下 Python 中 if while for 的使用,本章我们来看一下 Python 中的变量类型. 在 Python 定义变量时的规则是 变量名 = 变量 ,Python ...
- Python 从入门到进阶之路(七)
之前的文章我们简单介绍了一下 Python 中异常处理,本篇文章我们来看一下 Python 中 is 和 == 的区别及深拷贝和浅拷贝. 我们先来看一下在 Python 中的双等号 == . == 是 ...
- Python 从入门到进阶之路(六)
之前的文章我们简单介绍了一下 Python 的面向对象,本篇文章我们来看一下 Python 中异常处理. 我们在写程序时,有可能会出现程序报错,但是我们想绕过这个错误执行操作.即使我们的程序写的没问题 ...
- Python 从入门到进阶之路(四)
之前的文章我们简单介绍了一下 Python 的几种变量类型,本篇文章我们来看一下 Python 中的函数. 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性, ...
- Python 从入门到进阶之路(二)
之前的文章我们对 Python 语法有了一个简单的认识,接下来我们对 Python 中的 if while for 做一下介绍. 上图为 if 判断语句的流程,无论任何语言,都会涉及到判断问题,if ...
- python快速入门及进阶
python快速入门及进阶 by 小强
- Python 爬虫从入门到进阶之路(十五)
之前的文章我们介绍了一下 Python 的 json 模块,本章我们就介绍一下之前根据 Xpath 模块做的爬取<糗事百科>的糗事进行丰富和完善. 在 Xpath 模块的爬取糗百的案例中我 ...
- Python 爬虫从入门到进阶之路(五)
在之前的文章中我们带入了 opener 方法,接下来我们看一下 opener 应用中的 ProxyHandler 处理器(代理设置). 使用代理IP,这是爬虫/反爬虫的第二大招,通常也是最好用的. 很 ...
随机推荐
- 表删除时 Cannot delete or update a parent row: a foreign key constraint fails 异常处理
有两张表,结构如下: t_item: t_bid: id int id int n ...
- LeetCode刷题总结-栈、链表、堆和队列篇
本文介绍LeetCode上有关栈.链表.堆和队列相关的算法题的考点,推荐刷题20道.具体考点分类如下图: 一.栈 1.数学问题 题号:85. 最大矩形,难度困难 题号:224. 基本计算器,难度困难 ...
- JavaScript动画实例:旋转的圆球
1.绕椭圆轨道旋转的圆球 在Canvas画布中绘制一个椭圆,然后在椭圆上绘制一个用绿色填充的实心圆.之后每隔0.1秒刷新,重新绘制椭圆和实心圆,重新绘制时,实心圆的圆心坐标发生变化,但圆心坐标仍然位于 ...
- Python基础-day01-6
算数运算符 计算机,顾名思义就是负责进行 数学计算 并且 存储计算结果 的电子设备 目标 算术运算符的基本使用 01. 算数运算符 算数运算符是 运算符的一种 是完成基本的算术运算使用的符号,用来处理 ...
- ELK查询命令详解
目录 ELK查询命令详解 倒排索引 使用ElasticSearch API 实现CRUD 批量获取文档 使用Bulk API 实现批量操作 版本控制 什么是Mapping? 基本查询(Query查询) ...
- java对象的实例化过程
简单类对象的实例化过程 1.在方法区加载类: 2.在栈内存申请空间,声明变量P: 3.在堆内存中开辟空间,分配对象地址: 4.在对象空间中,对对象的属性进行默认初始化,类成员变量显示初始化: 5.构造 ...
- JPA中实现双向一对多的关联关系
场景 JPA入门简介与搭建HelloWorld(附代码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103473937 ...
- 基于Tomcat的GeoServer部署步骤
一.安装JAVA 资源:JDK1.8 提取码:0y26 步骤: 1.安装完成后,右击"我的电脑",点击"属性",选择"高级系统设置": 2. ...
- Linux7 64安装 oracle 11g Error in invoking target 'agent nmhs' of makefile
在makefile中添加链接libnnz11库的参数修改$ORACLE_HOME/sysman/lib/ins_emagent.mk,将$(MK_EMAGENT_NMECTL)修改为:$(MK_EMA ...
- mysql数据库排坑过程
刚安装mysql后想通过navicat来连接mysql,发现报错 1251这个错误,不慌.这个很简单. 首先通过cmd进入mysql. 然后修改密码规则 ALTER USER 'root'@'loca ...