Python 面向对象详细讲解

2023-10-31

*Python 面向对象详细讲解

**

Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。本章节我们将详细介绍Python的面向对象编程。
如果你以前没有接触过面向对象的编程语言,那你可能需要先了解一些面向对象语言的一些基本特征,在头脑里头形成一个基本的面向对象的概念,这样有助于你更容易的学习Python的面向对象编程。
接下来我们先来简单的了解下面向对象的一些基本特征。
面向对象技术简介:
(1)类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
(2)类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
(3)数据成员:类变量或者实例变量, 用于处理类及其实例对象的相关的数据。
(4)方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
(5)局部变量:定义在方法中的变量,只作用于当前实例的类。
(6)实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
(7) 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
(8)实例化:创建一个类的实例,类的具体对象。
(9)方法:类中定义的函数。
(10)对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

创建类
使用 class 语句来创建一个新类,class 之后为类的名称并以冒号结尾:
class ClassName:
‘类的帮助信息’ #类文档字符串
class_suite #类体
类的帮助信息可以通过ClassName.__doc__查看。
class_suite 由类成员,方法,数据属性组成。
实例

以下是一个简单的 Python 类的例子:
实例

-- coding: UTF-8 --

class Employee:
    '所有员工的基类'
    empCount = 0

    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
        Employee.empCount += 1

    def displayCount(self):
        print("Total Employee %d" % Employee.empCount)


    def displayEmployee(self):
        print("Name : ", self.name, ", Salary: ", self.salary)


    # empCount
    # 变量是一个类变量,它的值将在这个类的所有实例之间共享。你可以在内部类或外部类使用
    # Employee.empCount
    # 访问。

    # 第一种方法__init__()
    # 方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法
    #
    # self
    # 代表类的实例,self
    # 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。
    #
    # self代表类的实例,而非类
    #
    # 类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是
    # self。

    class Test:
        def prt(self):
            print(self)
            print(self.__class__)

    t = Test()
    t.prt()

以上实例执行结果为:

在这里插入图片描述
从执行结果可以很明显的看出,self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类。
self 不是 python 关键字,我们把他换成 runoob 也是可以正常执行的:
实例

class Test:
    def prt(runoob):
        print(runoob)
        print(runoob.__class__)
 
t = Test()
t.prt()

以上实例执行结果为:
在这里插入图片描述

创建实例对象

实例化类其他编程语言中一般用关键字 new,但是在 Python 中并没有这个关键字,类的实例化类似函数调用方式。

以下使用类的名称 Employee 来实例化,并通过 init 方法接收参数。

"创建 Employee 类的第一个对象"
emp1 = Employee("Zara", 2000)
"创建 Employee 类的第二个对象"
emp2 = Employee("Manni", 5000)

访问属性

您可以使用点号 . 来访问对象的属性。使用如下类的名称访问类变量:

emp1.displayEmployee()
emp2.displayEmployee()
print “Total Employee %d” % Employee.empCount

完整实例:
实例
#!/usr/bin/python

-- coding: UTF-8 --

class Employee:
    '所有员工的基类'
    empCount = 0

    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
        Employee.empCount += 1

    def displayCount(self):
        print("Total Employee %d" % Employee.empCount)


    def displayEmployee(self):
        print("Name : ", self.name, ", Salary: ", self.salary)


"创建 Employee 类的第一个对象"
emp1 = Employee("Zara", 2000)
"创建 Employee 类的第二个对象"
emp2 = Employee("Manni", 5000)
emp1.displayEmployee()
emp2.displayEmployee()
print("Total Employee %d" % Employee.empCount)

执行以上代码输出结果如下:
在这里插入图片描述

你可以添加,删除,修改类的属性,如下所示:

emp1.age = 7 # 添加一个 ‘age’ 属性
emp1.age = 8 # 修改 ‘age’ 属性
del emp1.age # 删除 ‘age’ 属性

你也可以使用以下函数的方式来访问属性:

getattr(obj, name[, default]) : 访问对象的属性。
hasattr(obj,name) : 检查是否存在一个属性。
setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。
delattr(obj, name) : 删除属性。

hasattr(emp1, ‘age’) # 如果存在 ‘age’ 属性返回 True。
getattr(emp1, ‘age’) # 返回 ‘age’ 属性的值
setattr(emp1, ‘age’, 8) # 添加属性 ‘age’ 值为 8
delattr(emp1, ‘age’) # 删除属性 ‘age’
Python内置类属性

__dict__ : 类的属性(包含一个字典,由类的数据属性组成)
__doc__ :类的文档字符串
__name__: 类名
__module__: 类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)
__bases__ : 类的所有父类构成元素(包含了一个由所有父类组成的元组)

Python内置类属性调用实例如下:
实例
#!/usr/bin/python

-- coding: UTF-8 --

class Employee:
    '所有员工的基类'
    empCount = 0

    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
        Employee.empCount += 1

    def displayCount(self):
        print("Total Employee %d" % Employee.empCount)


    def displayEmployee(self):
        print("Name : ", self.name, ", Salary: ", self.salary)



print("Employee.__doc__:", Employee.__doc__)

print("Employee.__name__:", Employee.__name__)

print("Employee.__module__:", Employee.__module__)

print("Employee.__bases__:", Employee.__bases__)

print("Employee.__dict__:", Employee.__dict__)

执行以上代码输出结果如下:

在这里插入图片描述

python对象销毁(垃圾回收)

Python 使用了引用计数这一简单技术来跟踪和回收垃圾。
在 Python 内部记录着所有使用中的对象各有多少引用。

一个内部跟踪变量,称为一个引用计数器。

当对象被创建时, 就创建了一个引用计数, 当这个对象不再需要时, 也就是说, 这个对象的引用计数变为0 时, 它被垃圾回收。但是回收不是"立即"的, 由解释器在适当的时机,将垃圾对象占用的内存空间回收。

a = 40 # 创建对象 <40>
b = a # 增加引用, <40> 的计数
c = [b] # 增加引用. <40> 的计数

del a # 减少引用 <40> 的计数
b = 100 # 减少引用 <40> 的计数
c[0] = -1 # 减少引用 <40> 的计数

垃圾回收机制不仅针对引用计数为0的对象,同样也可以处理循环引用的情况。循环引用指的是,两个对象相互引用,但是没有其他变量引用他们。这种情况下,仅使用引用计数是不够的。Python 的垃圾收集器实际上是一个引用计数器和一个循环垃圾收集器。作为引用计数的补充, 垃圾收集器也会留心被分配的总量很大(及未通过引用计数销毁的那些)的对象。 在这种情况下, 解释器会暂停下来, 试图清理所有未引用的循环。
实例

析构函数 del ,__del__在对象销毁的时候被调用,当对象不再被使用时,__del__方法运行:
实例
#!/usr/bin/python

-- coding: UTF-8 --

class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __del__(self):
        class_name = self.__class__.__name__
        print(class_name, "销毁")



pt1 = Point()
pt2 = pt1
pt3 = pt1
print(id(pt1), id(pt2), id(pt3))
 # 打印对象的id
del pt1
del pt2
del pt3

以上实例运行结果如下:

在这里插入图片描述

注意:通常你需要在单独的文件中定义一个类,
类的继承

面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。

通过继承创建的新类称为子类或派生类,被继承的类称为基类、父类或超类。

继承语法

class 派生类名(基类名)

在python中继承中的一些特点:

1、如果在子类中需要父类的构造方法就需要显式的调用父类的构造方法,或者不重写父类的构造方法。详细说明可查看: python 子类继承父类构造函数说明。
2、在调用基类的方法时,需要加上基类的类名前缀,且需要带上 self 参数变量。区别在于类中调用普通函数时并不需要带上 self 参数
3、Python 总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。

如果在继承元组中列了一个以上的类,那么它就被称作"多重继承" 。

语法:

派生类的声明,与他们的父类类似,继承的基类列表跟在类名之后,如下所示:

class SubClassName (ParentClass1[, ParentClass2, …]):

实例
#!/usr/bin/python

-- coding: UTF-8 --

class Parent:  # 定义父类
    parentAttr = 100

    def __init__(self):
        print( "调用父类构造函数")

    def parentMethod(self):
        print('调用父类方法')

    def setAttr(self, attr):
        Parent.parentAttr = attr

    def getAttr(self):
        print("父类属性 :", Parent.parentAttr)



class Child(Parent):  # 定义子类
    def __init__(self):
        print("调用子类构造方法")


    def childMethod(self):
        print('调用子类方法')



c = Child()  # 实例化子类
c.childMethod()  # 调用子类的方法
c.parentMethod()  # 调用父类方法
c.setAttr(200)  # 再次调用父类的方法 - 设置属性值
c.getAttr()  # 再次调用父类的方法 - 获取属性值

以上代码执行结果如下:

在这里插入图片描述

你可以继承多个类

class A: # 定义类 A

class B: # 定义类 B

class C(A, B): # 继承类 A 和 B

你可以使用issubclass()或者isinstance()方法来检测。

issubclass() - 布尔函数判断一个类是另一个类的子类或者子孙类,语法:issubclass(sub,sup)
isinstance(obj, Class) 布尔函数如果obj是Class类的实例对象或者是一个Class子类的实例对象则返回true。

方法重写

如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法:

实例:
实例
#!/usr/bin/python

-- coding: UTF-8 --


class Parent: # 定义父类
    def myMethod(self):
        print ('调用父类方法')

class Child(Parent): # 定义子类
    def myMethod(self):
        print ('调用子类方法')

c = Child() # 子类实例
c.myMethod() # 子类调用重写方法

执行以上代码输出结果如下:

在这里插入图片描述

基础重载方法

下表列出了一些通用的功能,你可以在自己的类重写:
序号 方法, 描述 & 简单的调用
1 init ( self [,args…] )
构造函数
简单的调用方法: obj = className(args)
2 del( self )
析构方法, 删除一个对象
简单的调用方法 : del obj
3 repr( self )
转化为供解释器读取的形式
简单的调用方法 : repr(obj)
4 str( self )
用于将值转化为适于人阅读的形式
简单的调用方法 : str(obj)
5 cmp ( self, x )
对象比较
简单的调用方法 : cmp(obj, x)
运算符重载

Python同样支持运算符重载,实例如下:
实例
#!/usr/bin/python

class Vector:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __str__(self):
        return 'Vector (%d, %d)' % (self.a, self.b)

    def __add__(self, other):
        return Vector(self.a + other.a, self.b + other.b)


v1 = Vector(2, 10)
v2 = Vector(5, -2)
print(v1 + v2)

以上代码执行结果如下所示:

在这里插入图片描述

类属性与方法
类的私有属性

__private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。
类的方法

在类的内部,使用 def 关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数
类的私有方法

__private_method:两个下划线开头,声明该方法为私有方法,不能在类的外部调用。在类的内部调用 self.__private_methods
实例
#!/usr/bin/python

-- coding: UTF-8 --

class JustCounter:
    __secretCount = 0  # 私有变量
    publicCount = 0  # 公开变量

    def count(self):
        self.__secretCount += 1
        self.publicCount += 1
        print( self.__secretCount)



counter = JustCounter()
counter.count()
counter.count()
print(counter.publicCount)

print(counter.__secretCount )
 # 报错,实例不能访问私有变量

Python 通过改变名称来包含类名:
在这里插入图片描述

Python不允许实例化的类访问私有数据,但你可以使用 object._className__attrName( 对象名._类名__私有属性名 )访问属性,参考以下实例:

#!/usr/bin/python

-- coding: UTF-8 --

class Runoob:
    __site = "www.runoob.com"

runoob = Runoob()
print (runoob._Runoob__site)

执行以上代码,执行结果如下:

在这里插入图片描述

单下划线、双下划线、头尾双下划线说明:

__foo__: 定义的是特殊方法,一般是系统定义名字 ,类似 __init__() 之类的。

_foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于 from module import *

__foo: 双下划线的表示的是私有类型(private)的变量, 只能是允许这个类本身进行访问了。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 面向对象详细讲解 的相关文章

随机推荐

  • CVPR 2019

    全球计算机视觉三大顶级会议之一 CVPR 2019 将于当地时间 6 月 16 20 日在美国洛杉矶举办 届时 旷视研究院将带领团队远赴盛会 助力计算机视觉技术的交流与落地 在此之前 旷视每周会介绍一篇被 CVPR 2019 接收的论文 本
  • 网络爆破实验

    本次实验主要是暴力破解 暴力破解的原理就是使用攻击者自己的用户名和密码字典 一个一个去枚举 尝试是否能够登录 因为理论上来说 只要字典足够庞大 枚举总是能够成功的 下面将详细讲述我的步骤 一 使用工具 phpstudy burp suite
  • python经典面试题之交换a和b两个数的值

    a b两个值交换 不借助第三个变量如何进行交换 通过异或 交换a b个值 我们要知道异或的规则 就是 0 0 0 1 1 0 0 1 1 0 5 5 0 x x x x 0 知道这个了之后 我们再去看下面的异或交换a b两个值 看看它是怎样
  • 二级域名的查找与扫描

    关于域名的概念我不在这里做过多介绍 关于查找和扫描二级域名的作用 我想对于每一个搞渗透的同志来说是至关重要的 就一点 当主站无从下手的时候 你可以从C段 同IP站点下手 但往往二级域名站点存在的潜在 漏洞 概率是非常高的 同时 这也对摸清目
  • 运维经验记录 在CentOS上挂载Windows共享磁盘

    1 需求 非root用户 普通用户 能够读写windows共享目录 比如查看文件 创建文件 修改文件 删除文件 让普通用户也可以正常读写 uid value and gid value Set the owner and group of
  • 大数据项目-用flink实现用户行为分析二

    实时流量统计 利用用户的偏好行为 例如点击浏览等 对用户进行流量统计 执行步骤 创建一个NetworkFlowAnalysis子模块 将apache服务器的日志文件复制到资源文件目录下 我们将从中读取数据 1 基于服务器log的热门页面浏览
  • SQL 外键约束

    概念 外键用来让2张表的数据之间建立连接 从而保证数据的一致性和完整性 添加外键 第一种 在建表时直接添加 CREATE TABLE 表名 字段名 数据类型 CONSTRAINT 外键名称 FOREIGN KEY 外键字段名 REFEREN
  • Web Service

    1 1 Web Service 基本概念 Web Service 也叫 XML Web Service WebService 是一种可以接收从 Internet 或者 Intranet 上的其它系统中传递过来的请求 轻量级的独立的通讯技术
  • ajax填充没显示出来,ajax请求数据成功,页面的数据没有加载出来

    w3c的ajax的例子 点击按钮 ajax请求读取一个本地ajax txt文件 页面展示其内容 在chrome中打开页面 点击按钮请求成功 但是页面没有显示ajax txt的内容 这是为什么呢 代码和chrome截图如下 function
  • python 虚拟环境

    使用虚拟环境 创建一个完全独立的局部python环境 在此环境中 安装所有与这个项目相匹配的库 一个项目使用一个局部的独立的python环境 互相之间没有干扰 这个局部的独立的python环境就称为虚拟环境 完全模拟系统全局python环境
  • 达梦数据库 linux安装配置步骤

    数据库服务器安装 root TKWOA NWEB5 mount o loop data soft dm8 20210630 x86 rh6 64 ent 8 1 2 18 pac iso mnt root TKWOA NWEB5 root
  • 深度学习-yolov3

    卷积层 从一张完整图片中提取多个特征 池化层 选择一部分最明显的特征 全连接层 将最终选择的特征放在一起组合输出 残差网络 ResNet BN 详解 详解 博文 卷积神经网络中卷积层 池化层 全连接层的作用 池化层作用 shinemyang
  • mobaxterm连接到Linux虚拟机

    软件 VMware CentOS 7 mobaxterm 一 查看虚拟机host 在VMware启动虚拟机后 点击应用程序 再点击终端进入 输入ifconfig查看虚拟机host和用户名 密码是创建虚拟机时设的 红框是虚拟机的ip 下面的是
  • Qt程序crash定位问题

    文章目录 问题 思路 从windos日志获取出错位置 启动Qt命令行环境 问题 Qt程序由于某种未知错误Crash掉 如何定位到出错位置 思路 固件开发时 出错时KDB会弹出少数出错信息 包含出错位置 调用堆栈 可以由出错地址 配合objd
  • lab5:深入理解进程切换

    Linux中的进程切换由context switch函数完成 该函数位于源代码目录的kernel sched core c 中 代码如下 context switch函数 context switch switch to the new M
  • QWidget设置背景图及圆角

    在Qt开发过程中 QWidget是经常作为主窗体的父窗口 有时我们需要对主窗口设置背景 设置圆角以达到美观的效果 通常的有以下三种方法 qss QPalette设置以及paintEvent绘制 下面介绍这三种方法 背景设置介绍 方法一 se
  • Redis4 - 编译安装&连接

    下载安装 redis连接 redis信息查询 下载安装 1 源码下载 https redis io 目前最新版本 4 11 2 解压到指定文件夹 eg 我的放到 build下 3 编译 安装 cd build redis 4 0 11 新建
  • 简单快速复制CSDN上的博客到自己的电脑上(带图片和格式)

    准备工具 typora md编辑器 直接去官网https www typora io 下载 一直点下一步 下载好了后界面是这样的 清爽且好用 需要做一点设置 文件 偏好设置 图像 如下设置 软件已经安装好并且可以使用了 看到这里可能你会有疑
  • ctex插入中文的方法

    documentclass 12pt article 使用中日韩的文字宏包 usepackage CJK begin document 插入中文 hei 表示字体为黑体 kai 楷 li 隶 song 宋 begin CJK GBK hei
  • Python 面向对象详细讲解

    Python 面向对象详细讲解 Python从设计之初就已经是一门面向对象的语言 正因为如此 在Python中创建一个类和对象是很容易的 本章节我们将详细介绍Python的面向对象编程 如果你以前没有接触过面向对象的编程语言 那你可能需要先