Python知识点13---面向对象的编程

提前说一点:如果你是专注于Python开发,那么本系列知识点只是带你入个门再详细的开发点就要去看其他资料了,而如果你和作者一样只是操作其他技术的Python API那就足够了。

Python是一个完全面向对象开发的语言,它的一切都以对象的方式操作

类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
数据成员:类变量或者实例变量, 用于处理类及其实例对象的相关的数据。
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
局部变量:定义在方法中的变量,只作用于当前实例的类。
实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
实例化:创建一个类的实例,类的具体对象。
方法:类中定义的函数。
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

定义一个类的语法如下,注意如果你用的是Python2,那么不要写objeck,不然会报错的

class ClassName(objeck):'类的帮助信息'   #类文档字符串class_suite  #类体#类的实例方法def aaa(self) :return

实例化类,生成对象语法如下

变量名 = 类名()  ---不需要其他语言那样的new

Python的类里面,和其他语言不同的就是,有时方法中会多一个 self,这个变量你要使用的时候,一般都是放在第一个参数位,并且代表对象本身,下面这个例子可以解释这一点

class Test:def prt(self):print(self)t = Test()
print(t)
t.prt()结果发现指向的都是同一个对象:
<__main__.Test instance at 0x10d066878>
<__main__.Test instance at 0x10d066878>

切记:对于 self 本身来说,它不是一个定死的关键字,我们换成其他的名字也可以,只是在开发中我们按照惯例,把它写在了第一个参数位,并且起名为 self ,它本身其实是和JAVA的this对象等价的,只不过Python需要在参数位声明一下而已

而且当你使用了self的时候,在传递参数时,不需要在意它的值,因为可以自动补齐,如下

class Test :def fun_name(self,b,c):print(b+str(c))a = Test()
a.fun_name('忽略self正常传参',21)
结果:忽略self正常传参21

对于Python的类来说,也是拥有属性的,我们在类的内部,类实体方法的外部,书写属性即可,但是切记在类中书写属性的时候一定要给一个初值,不然访问的时候会报错

class Test :age = ''def fun_test():print('llll')

在使用这个类创建对象之后,对象会拥有类的所有东西,属性自然也包括其中,调用时语法如下,这一点在Python中叫做 “类外面获取对象属性

对象名.属性名		#调用获取
对象名.属性名 =#修改

但是注意,Python允许一个对象拥有属于自己的属性,这种属性不需要在类中定义,直接使用对象调用就可以,会自动生成一个数据这个对象自己的属性,其他对象没有,下面这个例子可以解释这一点,这一点在Python中也叫做 “类外面添加对象属性

class Test :def fun_name():print('llll')a = Test()
b = Test()a.age = '12'
print(a.age)
print(b.age)结果会报错,提示对象b没有age属性:
12
Traceback (most recent call last):File "main.py", line 12, in <module>print(b.age)
AttributeError: Test instance has no attribute 'age'

这个时候有的小伙伴可能就会疑惑,有类外面获取对象属性、类外面添加对象属性,这两点都聚焦在对象的身上,和类的关系不是很明显,其实Python还有最后一种相关操作,叫做“在类内部获取对象属性”,对于这一点,个人认为其实是Python提供给我们开发者的一种辅助,防止我们由于其他因素导致访问不到对象的属性,比如被局部变量或者其他变量干扰,操作方式如下

class Test :age = 12def fun_name(self):print(self.age)a = Test()
a.fun_name()

其实就是self的应用,不过注意,这种操作可以和类外部添加属性那样直接调用一个原先没有的属性

class Test :def fun_name(self):print(self.age)a = Test()
a.age = 10
a.fun_name()

现在我猜测大家或许会混乱,没关系,记住核心的一点:在Python中,可以像常规那样使用对象和类,只是Python除此之外,允许一个属性在使用的时候,是从无到有的,也就是没有被预先定义的

其实对于self来说,它不止可以调用我们自己定义的属性,它还带有着其他的东西,有兴趣大家可以在其他地方找一找资料,比如可以获取对象实例化的类名

class Test :def fun_name(self):print(self.__class__)a = Test()
a.fun_name()结果:__main__.Test

对于对象的属性,Python其实有着其他的方式可以调用

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__: 类定义所在的模块
__bases__ : 类的所有父类构成元素(包含了一个由所有父类组成的元组)

有意思的是我们通过类名可以直接将自己定义的属性获取到,这个时候,这个属性也叫做类属性


下面我们了解一下,在Python中对象是如何被垃圾回收的

在Python中只有一种垃圾回收机制,就是引用计数法,在 Python 内部记录着所有使用中的对象各有多少引用。

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

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

垃圾回收机制不仅针对引用计数为0的对象,同样也可以处理循环引用的情况。循环引用指的是,两个对象相互引用,但是没有其他变量引用他们。这种情况下,仅使用引用计数是不够的。Python 的垃圾收集器实际上是一个引用计数器和一个循环垃圾收集器。作为引用计数的补充, 垃圾收集器也会留心被分配的总量很大(即未通过引用计数销毁的那些)的对象。 在这种情况下, 解释器会暂停下来, 试图清理所有未引用的循环,其实说白了就是有a、b两个对象,它们独立与其他对象,产生较为单独的一对相互引用关系,这种对象时间长了,也会被回收掉

特别注意一个对象被回收时,会调用它的__del__方法,这个方法是用来回收对象的,但大家不要纠结,后面我会单独说这种有四个下滑线的方法,是干什么的


下面我们来了解一下类的继承,类继承语法如下

class 派生类名(基类名):...

Python的类继承的时候,和其他语言一样有着注意点:

1、如果在子类中需要父类的构造方法就需要显式的调用父类的构造方法,或者不重写父类的构造方法。实例如下

当你没有重写构造方法时:
class Father():def __init__(self, name):self.name=namedef getName(self):return 'Father ' + self.nameclass Son(Father):def getName(self):return 'Son '+self.nameson=Son('runoob')
print ( son.getName() )结果:Son runoob
从结果中你可以发现,传入的name值作用在了父类的构造器上-----------------------------------------------------------------------------
当你重写了子类的构造方法,但是没有调用父类的时候:
class Father():def __init__(self, name):self.name=namedef getName(self):return 'Father ' + self.nameclass Son(Father):def __init__(self, name):print ( "hi" )self.name =  namedef getName(self):return 'Son '+self.nameson=Son('runoob')
print ( son.getName() )结果:
hi
Son runoob
从结果来看,发现并没有调用父类的构造方法------------------------------------------------------------
当你重写了子类的构造方法,并调用了父类的构造方法时:
class Father():def __init__(self, name):self.name = nameprint("这里是父类")class Son(Father):def __init__(self, name):#第一种调用方法:super(Son, self).__init__(name)#第二种调用方法:Father.__init__(self,name)print ("hi")self.name =  namedef getName(self):return 'Son '+self.nameson=Son('runoob')
print ( son.getName() )
结果:
这里是父类
hi
Son runoob

2、在调用基类的方法时,基类的方法必须有self参数,不然无法执行,对于这一点其实大家养成写方法参数要带上self的习惯就可以了

基类没有self:
class Father():def __init__(self, name):self.name = namedef nnn():print('父类方法')class Son(Father):def __init__(self, name):Father.__init__(self,name)self.name =  nameson=Son('runoob')
son.nnn()
结果报错:
Traceback (most recent call last):File "main.py", line 17, in <module>son.nnn()
TypeError: nnn() takes no arguments (1 given)----------------------------------------------------------------
基类有self
class Father():def __init__(self, name):self.name = namedef nnn(self):print('父类方法')class Son(Father):def __init__(self, name):Father.__init__(self,name)self.name =  nameson=Son('runoob')
son.nnn()
结果:父类方法

3、Python 总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。


值得高兴的是Python支撑多继承

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

还提供了两个检查函数

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

Python也支持多态,在重写父类方法的时候也要注意self

class Father():def __init__(self, name):self.name = namedef nnn(self):print('父类方法')class Son(Father) :def __init__(self, name) :Father.__init__(self,name)self.name = namedef nnn(self,age) :print('子类方法' + str(age))def nnn(self,age,ppp) :print('子类方法' + str(age) + str(ppp))a = Son('Tom')
a.nnn(10)
a.nnn(10,20)
结果:
子类方法10
子类方法1020

如果看了我写的公共方法篇,一定知道加法是合并的意思,而有趣的是Python的对象也支持这样的操作,不过想要对象之间执行合并你需要重写__add__方法

class Vector:def __init__(self, a, b):self.a = aself.b = bdef __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
结果:Vector (7, 8)

值得一提的是,在Python中类也是有静态方法的
class Father():def __init__(self, name):self.name = name@staticmethoddef nnn(self):print('静态方法')Father.nnn()
a = Father('Tom')
a.nnn()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/20308.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java面试——专业技能

优质博文&#xff1a;IT-BLOG-CN 一、简单讲下 Java 的跨平台原理 由于各个操作系统&#xff08;Windows&#xff0c;Linux等&#xff09;支持的指令集不是完全一致的。就会让我们程序在不同的操作系统上要执行不同的程序代码。Java 开发了适用于不同操作系统及位数的 Java 虚拟…

【教程】自监督 对比学习,代码,爽学一波

from&#xff1a; https://docs.lightly.ai/self-supervised-learning/examples/simclr.html

代码随想录第22天|回溯part2 组合总和III电话号码的字母组合

216.组合总和III 当组合的数量为k就判断和&#xff0c;并且返回。 在枚举的时候可以进行剪枝&#xff0c;如果总和已经超过了n&#xff0c;那么就没必要继续递归下去了 class Solution { public:vector<int> path;vector<vector<int>> res;void backTrackin…

微信小程序手机号码授权登录

文章目录 一、微信小程序开发二、使用步骤1.前端代码2.后台配置3.后台代码 总结 一、微信小程序开发 目前个人的小程序无法使用手机号码授权登录&#xff0c;可以使用测试号进行开发 二、使用步骤 1.前端代码 代码如下&#xff08;示例&#xff09;&#xff1a; <butto…

Java版本家政上门系统源码,自主研发、安全可控,支持任意二次开发

家政上门系统源码&#xff0c;Java版本&#xff0c;自主研发、安全可控。支持任意二次开发、有丰富合作案例。多端管理&#xff1a;管理端、用户端、服务端。 技术参数&#xff1a; 技术架构&#xff1a;springboot、mysql 、Thymeleaf 开发语言&#xff1a;java1.8、vue 开…

python 象棋小游戏代码

以下是一个简单的Python象棋小游戏的代码示例。这个示例使用了pygame库来创建图形用户界面和处理用户输入。 首先&#xff0c;确保安装了pygame库&#xff1a; pip install pygame 然后&#xff0c;可以运行以下代码&#xff1a; import pygame import sys # 初始化pygam…

软件开发步骤详解

一、引言 随着信息技术的迅猛发展&#xff0c;软件已成为现代社会不可或缺的一部分。无论是企业运营、个人生活还是科学研究&#xff0c;都离不开各种软件的支持。因此&#xff0c;掌握软件开发的步骤和技巧对于IT从业者来说至关重要。本文旨在详细介绍软件开发的整个流程&…

Python知识点7---字典与集合

提前说一点&#xff1a;如果你是专注于Python开发&#xff0c;那么本系列知识点只是带你入个门再详细的开发点就要去看其他资料了&#xff0c;而如果你和作者一样只是操作其他技术的Python API那就足够了。 Python的字典与集合是没有下标一说的&#xff0c;字典说的其实就是ma…

使用机器学习做医学图像分类的开源项目集锦

项目名称仓库描述主要特点适配建议U-Net用于生物医学图像分割zhixuhao/unetKeras中的U-Net实现&#xff0c;用于2D图像分割。 - 基本的U-Net架构 - 生物医学图像训练示例 - 简单的数据加载器 - 修改数据加载器以处理特定MRI格式 - 调整训练管道以适应STIR序列和标签 使用PyTor…

更改Web网站设计——css和css框架

虽然使用HTML可以定义文章的结构&#xff0c;但是其中不包含设计相关的信息。此时CSS就派上用场&#xff0c;可以用它对HTML文章指定设计样式。由于可以决定Web网页的外观风格&#xff0c;因此&#xff0c;它有时也被称为格式表。 如果使用CSS设置背景色&#xff0c;文…

计算机网络期末复习(1)计算机网络在信息时代对的作用 计算机网络的定义和分类 三种交换方法

计算机网络在信息时代扮演着至关重要的角色&#xff0c;它极大地改变了我们生活、工作和学习的方式。 计算机网络在信息时代的作用 信息共享与传播&#xff1a;计算机网络使全球范围内的信息快速共享成为可能&#xff0c;无论是新闻、学术研究还是娱乐内容&#xff0c;都可以…

初识 JavaScript

目录 1. 什么是 JavaScript2. JS 引入方式2.1 内部引入方式2.2 外部引入方式 3. JS 中的注释4. JS 中的结束符5. 输入和输出5.1 输出5.2 输入 6. 变量与常量6.1 变量的声明6.2 变量的赋值6.3 常量 7. JS 中的数据类型8. JS 中的类型转换8.1 隐式转换8.2 显式转换 正文开始 1. …

Java 多线程相关面试题

1. ConcurrentHashMap的读是否要加锁&#xff0c;为什么? 读操作没有加锁&#xff0c;目的是为了进一步降低锁冲突的概率&#xff0c;为了保证读到刚修改的数据&#xff0c;搭配了volatile 关键字&#xff1b; 2. 介绍下 ConcurrentHashMap 的锁分段技术? 这个是 Java1.7 …

TP8 定时任务yzh52521/http-crontab 教程

官方文档&#xff1a; https://www.thinkphp.cn/ext/36 源码仓&#xff1a; http-crontab: 接口化秒级定时任务管理 GitHub - yuanzhihai/http-crontab: 接口化秒级定时任务管理 参考案例&#xff1a; http-crontab:Workerman ThinkPHP6 实现后台可视化定时任务管理 htt…

深入解析Java注解机制:元注解、自定义处理器及其在框架中的妙用

1.注解简介与作用 1.1 什么是注解&#xff08;Annotation&#xff09; 在Java中&#xff0c;注解是一种应用于类、方法、变量、参数和Java包等元素的标记。这些标记可以在编译时、加载时甚至运行时被读取&#xff0c;并执行相应的处理。通过使用注解&#xff0c;开发人员可以…

C++中的List

摘要 C 标准库中的 std::list 是一种双向链表容器&#xff0c;它允许在常数时间内进行插入和删除操作&#xff0c;每个元素包含一个指向前一个和后一个元素的指针。这给我们开发提供了高效的插入和删除操作。 引入头文件 要使用 std::list&#xff0c;需要包含头文件 <li…

钣金件设计规范

(一&#xff09; 钣金 1、钣金的概念 钣金&#xff08;sheet metal&#xff09;是针对金属薄板&#xff08;厚度通常在6mm以下&#xff09;的 一种综合冷加工工艺&#xff0c;包括冲裁、折弯、拉深、成形、锻压、铆合等&#xff0c; 其显著的特征是同一零件厚度一致。 2、钣…

C语言属于什么是编程语言:探索C语言的本质与特性

C语言属于什么是编程语言&#xff1a;探索C语言的本质与特性 在编程领域&#xff0c;C语言无疑是一种重要的、广泛应用的编程语言。但是&#xff0c;C语言究竟属于哪一类编程语言&#xff1f;它又有哪些独特的特性和价值&#xff1f;本文将从四个方面、五个方面、六个方面和七…

精通推荐算法8:Embedding表征学习 -- 总体架构

1 Embedding表征学习的总体架构 目前&#xff0c;推荐算法精排模型大多基于Embedding MLP范式&#xff0c;模型底层是Embedding层&#xff0c;作用是将高维稀疏的输入特征转换为低维稠密的特征向量&#xff0c;并实现一定的模糊查找能力。模型上层是MLP层&#xff0c;作用是对…

在鲲鹏服务器上安装nginx

华为鲲鹏服务器采用华为自研cpu ARMv8架构,提供 Windows 和多个Linux 系统 常使用 CentOS 7.6 64bit with ARM Nginx 和 Apache 一样都是一种 Web 服务器。是基于 REST 架构风格&#xff0c;以统一资源描述符URI 或者统一资源定位符URL 作为沟通依据&#xff0c;通过 HTTP 协议…