【Python学习笔记】第十九节 Python 面向对象(一)

news/2024/4/26 7:11:00/文章来源:https://blog.csdn.net/yubao0723/article/details/129242158

在现实世界中,随处可见的一种事物就是对象,对象是事物存在的实体,如学生、汽车等。人类解决问题的方式总是将复杂的事物简单化,于是就会思考这些对象都是由哪些部分组成的。通常都会将对象划分为两个部分,即静态部分与动态部分。

顾名思义,静态部分就是不能动的部分,这个部分被称为“属性”,任何对象都会具备其自身属性,如一个人,其属性包括高矮、胖瘦、年龄、性别等。然而具有这些属性的人会执行哪些动作也是一个值得探讨的部分,这个人可以转身、微笑、说话、奔跑,这些是这个人具备的行为(动态部分),人类通过探讨对象的属性和观察对象的行为来了解对象。

Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。本章节我们将详细介绍Python的面向对象编程。


一、面向对象简介

  • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

  • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。

  • 数据成员:类变量或者实例变量, 用于处理类及其实例对象的相关的数据。

  • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。

  • 局部变量:定义在方法中的变量,只作用于当前实例的类。

  • 实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。

  • 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。

  • 实例化:创建一个类的实例,类的具体对象。

  • 方法:类中定义的函数。

  • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

二、创建类

Python使用class关键字来定义类,其语法格式如下:

class ClassName:'类的帮助信息'   #类文档字符串class_suite  #类体
  • 类的帮助信息可以通过ClassName.__doc__查看。

  • class_suite 由类成员,方法,数据属性组成。

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

# coding=utf-8class Cat:#属性age = 1#方法def eat(self):print("猫在吃鱼....")def drink(self):print("猫正在喝.....")def sleep(self):print("猫在睡觉.....")
  • age 变量是一个类变量,它的值将在这个类的所有实例之间共享。你可以在内部类或外部类使用 Cat.age 访问。

  • self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。

self代表类的实例,而非类

类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。

# coding=utf-8class Cat:# 属性weight = 1.0# 方法def eat(self):print("猫在吃鱼....")def drink(self):print("猫正在喝.....")def sleep(self):print("猫在睡觉.....")def prt(me):print(me)print(me.__class__)cat = Cat()
cat.prt();

执行结果为:

从执行结果可以看出,self 代表的是类的实例,代表当前对象的地址,而 self.__class__ 则指向类。

self 不是 python 关键字,我们把他换成 me 也是可以正常执行的:

# coding=utf-8class Cat:# 属性weight = 1.0# 方法def eat(self):print("猫在吃鱼....")def drink(self):print("猫正在喝.....")def sleep(self):print("猫在睡觉.....")def prt(me):print(me)print(me.__class__)cat = Cat()
cat.prt();

三、创建实例对象

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

# coding=utf-8class Cat:# 属性weight = 1.0# 方法def eat(self):print("猫在吃鱼....")def drink(self):print("猫正在喝.....")def sleep(self):print("猫在睡觉.....")# 创建一个对象
tom = Cat()

1、调用对象的方法

# coding=utf-8class Cat:# 属性weight = 1.0# 方法def eat(self):print("猫在吃鱼....")def drink(self):print("猫正在喝.....")def sleep(self):print("猫在睡觉.....")# 创建一个对象
tom = Cat()# 调用对象的方法
tom.eat()
tom.drink()

2、添加属性

# coding=utf-8class Cat:# 属性weight = 1.0# 方法def eat(self):print("猫在吃鱼....")def drink(self):print("猫正在喝.....")def sleep(self):print("猫在睡觉.....")# 创建一个对象
tom = Cat()# 调用对象的方法
tom.eat()
tom.drink()# 添加属性
tom.name = "汤姆"
tom.age = 40

3、获取对象的属性

# coding=utf-8class Cat:# 属性weight = 1.0# 方法def eat(self):print("猫在吃鱼....")def drink(self):print("猫正在喝.....")def sleep(self):print("猫在睡觉.....")def introduce(self):print("%s的年龄是:%d" % (tom.name, tom.age))# 创建一个对象
tom = Cat()# 调用对象的方法
tom.eat()
tom.drink()# 添加属性
# 给tom指向的对象添加2个属性
tom.name = "汤姆"
tom.age = 40# 获取属性的第1种方式
# print("%s的年龄是:%d"%(tom.name, tom.age))tom.introduce()

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

  • getattr(obj, name[, default]) : 访问对象的属性。

  • hasattr(obj,name) : 检查是否存在一个属性。

  • setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。

  • delattr(obj, name) : 删除属性。

hasattr(tom, 'age')  # 如果存在 'age' 属性返回 True。
getattr(tom, 'age')  # 返回 'age' 属性的值
setattr(tom, 'age', 8)  # 添加属性 'age' 值为 8
delattr(tom, 'age')  # 删除属性 'age'

4、__init__()方法

是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法

# coding=utf-8class Cat:# 属性weight = 1.0# 初始化对象def __init__(self, new_name, new_age):self.name = new_nameself.age = new_agedef __str__(self):return "%s的年龄是:%d" % (self.name, self.age)# 方法def eat(self):print("猫在吃鱼....")def drink(self):print("猫正在喝.....")def sleep(self):print("猫在睡觉.....")def introduce(self):print("%s的年龄是:%d" % (self.name, self.age))# 创建一个对象
tom = Cat("汤姆", 40)
tom.eat()
tom.drink()
# tom.name = "汤姆"
# tom.age = 40
tom.introduce()baimao = Cat("白猫", 10)
# baimao.name = "白猫"
# baimao.age = 10
baimao.introduce()

5、__str__方法

用于将值转化为适于人阅读的形式

# coding=utf-8class Cat:# 属性weight = 1.0# 初始化对象def __init__(self, new_name, new_age):self.name = new_nameself.age = new_agedef __str__(self):return "%s的年龄是:%d" % (self.name, self.age)# 方法def eat(self):print("猫在吃鱼....")def drink(self):print("猫正在喝.....")def sleep(self):print("猫在睡觉.....")def introduce(self):print("%s的年龄是:%d" % (self.name, self.age))# 创建一个对象
tom = Cat("汤姆", 40)
tom.eat()
tom.drink()
# tom.name = "汤姆"
# tom.age = 40
tom.introduce()baimao = Cat("白猫", 10)
# baimao.name = "白猫"
# baimao.age = 10
baimao.introduce()print(tom)
print(baimao)

四、Python内置类属性

  • __dict__ : 类的属性(包含一个字典,由类的数据属性组成)

  • __doc__ :类的文档字符串

  • __name__: 类名

  • __module__: 类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)

  • __bases__ : 类的所有父类构成元素(包含了一个由所有父类组成的元组)

# coding=utf-8class Cat:# 属性weight = 1.0# 初始化对象def __init__(self, new_name, new_age):self.name = new_nameself.age = new_agedef __str__(self):return "%s的年龄是:%d" % (self.name, self.age)# 方法def eat(self):print("猫在吃鱼....")def drink(self):print("猫正在喝.....")def sleep(self):print("猫在睡觉.....")def introduce(self):print("%s的年龄是:%d" % (self.name, self.age))# 创建一个对象
tom = Cat("汤姆", 40)
tom.eat()
tom.drink()
# tom.name = "汤姆"
# tom.age = 40
tom.introduce()baimao = Cat("白猫", 10)
# baimao.name = "白猫"
# baimao.age = 10
baimao.introduce()print(tom)
print(baimao)print("Cat.__doc__:", Cat.__doc__)
print("Cat.__name__:", Cat.__name__)
print("Cat.__module__:", Cat.__module__)
print("Cat.__bases__:", Cat.__bases__)
print("Cat.__dict__:", Cat.__dict__)

五、python对象销毁(垃圾回收)

Python 使用了引用计数这一简单技术来跟踪和回收垃圾。

在 Python 内部记录着所有使用中的对象各有多少引用。一个内部跟踪变量,称为一个引用计数器。

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

析构函数 __del__ ,__del__在对象销毁的时候被调用,当对象不再被使用时,__del__方法运行:

# coding=utf-8class Dog:def __del__(self):print("-----英雄over------")dog1 = Dog()
dog2 = dog1del dog1  # 不会调用 __del__方法,因为这个对象 还有其他的变量指向它,即 引用计算不是0
del dog2  # 此时会调用__del__方法,因为没有变量指向它了
print("====================")# 如果在程序结束时,有些对象还存在,那么python解释器会自动调用它们的__del__方法来完成清理工作

六、类的继承

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

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

继承语法

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

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

  • 1、如果在子类中需要父类的构造方法就需要显式的调用父类的构造方法,或者不重写父类的构造方法。详细说明可查看: python 子类继承父类构造函数说明。

  • 2、在调用基类的方法时,需要加上基类的类名前缀,且需要带上 self 参数变量。区别在于类中调用普通函数时并不需要带上 self 参数

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

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

语法:

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

class SubClassName (ParentClass1[, ParentClass2, ...]):...
# coding=utf-8class Animal:def __init__(self):print("调用父类构造函数")def eat(self):print("-----吃----")def drink(self):print("-----喝----")def sleep(self):print("-----睡觉----")def run(self):print("-----跑----")class Dog(Animal):def __init__(self):print("调用子类构造函数")"""def eat(self):print("-----吃----")def drink(self):print("-----喝----")def sleep(self):print("-----睡觉----")def run(self):print("-----跑----")"""def bark(self):print("----汪汪叫---")class Cat(Animal):def catch(self):print("----抓老鼠----")# a = Animal()
# a.eat()wangcai = Dog()
wangcai.eat()tom = Cat()
tom.eat()

继承多个类

class Base(object):def test(self):print("----Base")class A(Base):def test1(self):print("-----test1")class B(Base):def test2(self):print("-----test2")class C(A,B):passc = C()
c.test1()
c.test2()
c.test()

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

  • issubclass() - 布尔函数判断一个类是另一个类的子类或者子孙类,语法:issubclass(sub,sup)

  • isinstance(obj, Class) 布尔函数如果obj是Class类的实例对象或者是一个Class子类的实例对象则返回true。

七、方法重写

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

# coding=utf-8class Animal:def eat(self):print("-----吃----")def drink(self):print("-----喝----")def sleep(self):print("-----睡觉----")def run(self):print("-----跑----")class Dog(Animal):def bark(self):print("----汪汪叫---")class Xiaotq(Dog):def fly(self):print("----飞----")def bark(self):print("----狂叫-----")xiaotq = Xiaotq()
xiaotq.fly()
xiaotq.bark()
xiaotq.eat()

1、基础重载方法

下表列出了一些通用的功能,你可以在自己的类重写:

序号

方法, 描述 & 简单的调用

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)

2、运算符重载

Python同样支持运算符重载,实例如下:

# coding=utf-8class 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)

八、类属性与方法

1、类的私有属性

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

2、类的方法

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

3、类的私有方法

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

# coding=utf-8class Dog:__age = 0name = ""def __init__(self, new_name):self.name = new_nameself.__age = 0  # 定义了一个私有的属性,属性的名字是__agedef set_age(self, new_age):if new_age > 0 and new_age <= 100:self.__age = new_ageelse:self.__age = 0def get_age(self):return self.__agedog = Dog("小白")
# dog.age = -10
# dog.name = "小白"# print(dog.age)dog.set_age(10)
age = dog.get_age()
print(age)# dog.get_name()# dog.__age = -10
# print(dog.__age)  # 报错,实例不能访问私有变量# object._className__attrName( 对象名._类名__私有属性名 )访问属性
print(dog._Dog__age)

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

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

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

  • __foo: 双下划线的表示的是私有类型(private)的变量, 只能是允许这个类本身进行访问了。

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

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

相关文章

SSL证书对虚拟主机的用处有哪些?

虚拟主机是指在同一台服务器上&#xff0c;通过不同的域名或IP地址为多个网站提供服务的一种网络主机。而SSL证书则是一种数字证书&#xff0c;它用于加密网站与用户之间的通信&#xff0c;确保数据传输的安全性和完整性。在虚拟主机上&#xff0c;SSL证书有以下几个用处&#…

HiveSql一天一个小技巧:如何巧用分布函数percent_rank()求去掉最大最小值的平均薪水问题

0 问题描述参考链接(3条消息) HiveSql面试题12--如何分析去掉最大最小值的平均薪水&#xff08;字节跳动&#xff09;_莫叫石榴姐的博客-CSDN博客文中已经给出了三种解法&#xff0c;这里我们借助于此题&#xff0c;来研究如何用percent_rank()函数求解&#xff0c;简化解题思路…

深入理解C#的协变和逆变及其限制原因

阅读本文需要的一些前置知识&#xff1a; C#基本语法、C#的泛型使用、C#的运行过程 由于协变和逆变存在一些细节&#xff0c;在阅读时请注意“接口”和“类型”的差异&#xff0c;此外&#xff0c;文中有可能在不同的语境中将“结构体”和“值类型”混用&#xff0c;但表达的同…

深入浅出1588v2(PTP)里的时间同步原理

1.时间同步1.1 单步同步(OneStep)单步同步最为简单&#xff0c;master向slave发送一个sync的同步包&#xff0c;同步包里带有这条信息发送时master的当前时间t1&#xff0c;假如这条信息从master传输到slave需要的传输时间是D&#xff0c;那么slave收到信息时&#xff0c;maste…

BIM小技巧丨关于如何在Revit明细表中显示门窗面积

在明细表中显示门窗面积(以门明细表为例)在新建一个门明细表后&#xff0c;可以发现在Revit中不能直接使用明细表统计门窗面积。 这时&#xff0c;可以通过使用添加“计算值”的方式来处理&#xff0c;得到如下图所示&#xff0c;两种不同的面积统计结果&#xff1a; 除此之外&…

前端基础之CSS扫盲

文章目录一. CSS基本规范1. 基本语法格式2. 在HTML引入CSS3. 选择器分类二. CSS常用属性1. 文本属性2. 文本格式3. 背景属性4. 圆角矩形和圆5. 元素的显示模式6. CSS盒子模型7. 弹性布局光使用HTML来写一个前端页面的话其实只是写了一个大体的框架, 整体的页面并不工整美观, 而…

ledcode【用队列实现栈】

目录 题目描述&#xff1a; 解析题目 代码解析 1.封装一个队列 1.2封装带两个队列的结构体 1.3封装指向队列的结构体 1.4入栈函数实现 1.5出栈函数实现 1.6取栈顶数据 1.7判空函数实现 题目描述&#xff1a; 解析题目 这个题我是用c语言写的&#xff0c;所以队列的pu…

JavaSE-3 Java运行原理

一、Java的运行过程 &#x1f34e;Java程序运行时,必须经过编译和运行两个步骤。 首先将后缀名为.java的源文件进行编译,最终生成后缀名为.class的字节码文件。然后Java虚拟机将字节码文件进行解释执行,并将结果显示出来。具体过程如下图所示。 &#x1f349;Java程序的运行过…

【Python数据挖掘入门】2.2文本分析-中文分词(jieba库cut方法/自定义词典load_userdict/语料库分词)

中文分词就是将一个汉字序列切分成一个一个单独的词。例如&#xff1a; 另外还有停用词的概念&#xff0c;停用词是指在数据处理时&#xff0c;需要过滤掉的某些字或词。 一、jieba库 安装过程见&#xff1a;https://blog.csdn.net/momomuabc/article/details/128198306 ji…

数字IC手撕代码--小米科技(除法器设计)

前言&#xff1a; 本专栏旨在记录高频笔面试手撕代码题&#xff0c;以备数字前端秋招&#xff0c;本专栏所有文章提供原理分析、代码及波形&#xff0c;所有代码均经过本人验证。目录如下&#xff1a;1.数字IC手撕代码-分频器&#xff08;任意偶数分频&#xff09;2.数字IC手撕…

原始GAN-pytorch-生成MNIST数据集(代码)

文章目录原始GAN生成MNIST数据集1. Data loading and preparing2. Dataset and Model parameter3. Result save path4. Model define6. Training7. predict原始GAN生成MNIST数据集 原理很简单&#xff0c;可以参考原理部分原始GAN-pytorch-生成MNIST数据集&#xff08;原理&am…

记一次线上es慢查询导致的服务不可用

现象 某日线上业务同学反馈订单列表查询页面一直loding&#xff0c;然后提示请求超时&#xff0c;几分钟之后恢复正常 接到报障之后&#xff0c;马上根据接口URL&#xff0c;定位到了请求链路&#xff0c;发现是es查询超时&#xff0c;这里我们的业务订单表数据是由几百万的&a…

如何基于MLServer构建Python机器学习服务

文章目录前言一、数据集二、训练 Scikit-learn 模型三、基于MLSever构建Scikit-learn服务四、测试模型五、训练 XGBoost 模型六、服务多个模型七、测试多个模型的准确性总结参考前言 在过去我们训练模型&#xff0c;往往通过编写flask代码或者容器化我们的模型并在docker中运行…

Python学习笔记202302

1、numpy.empty 作用&#xff1a;根据给定的维度和数值类型返回一个新的数组&#xff0c;其元素不进行初始化。 用法&#xff1a;numpy.empty(shape, dtypefloat, order‘C’) 2、logging.debug 作用&#xff1a;Python 的日志记录工具&#xff0c;这个模块为应用与库实现了灵…

C# Sqlite数据库加密

sqlite官方的数据库加密是收费的&#xff0c;而且比较贵。 幸亏微软提供了一种免费的方法。 1 sqlite加密demo 这里我做了一个小的demo演示如下&#xff1a; 在界面中拖入数据库名、密码、以及保存的路径 比如我选择保存路径桌面的sqlite目录&#xff0c;数据库名guigutool…

Verilog 学习第五节(串口接收部分)

小梅哥串口部分学习part2 串口通信接收原理串口通信接收程序设计与调试巧用位操作优化串口接收逻辑设计串口接收模块的项目应用案例串口通信接收原理 在采样的时候没有必要一直判断一个clk内全部都是高/低电平&#xff0c;如果采用直接对中间点进行判断的话&#xff0c;很有可能…

Linux 红帽9.0 本地源 与 网络源 搭建

本次我们使用的是 redhat 9.0 版本&#xff0c;是redhat 的最新版本&#xff0c;我们一起来对其进行 本地仓库 和 网络仓库的搭建部署~&#xff01;&#xff01;关于 本地仓库&#xff08; 本地源 &#xff09;&#xff0c;和 网络仓库 &#xff08; 网络源 &#xff09;&#…

ESP32蓝牙配网

注意********menuconfig 配置&#xff08;必须打开蓝牙我这是C2所以使用NimBLE &#xff09;可以直接从demo的配置文件拷贝 Component config ---> Bluetooth ---> NimBLE - BLE only Component config ---> Bluetooth ---> NimBLE Options ---> Enable blufi…

计算结构体大小

计算结构体大小 目录计算结构体大小一. 结构体内存对齐1. 简介2. 嵌套结构体二. offsetof三. 内存对齐的意义四. 修改默认对齐数一. 结构体内存对齐 以字节&#xff08;bety&#xff09;为单位 1. 简介 对于结构体成员在内存里的存储&#xff0c;存在结构体的对齐规则&#…

Vue下载安装步骤的详细教程(亲测有效) 1

目录 一、【准备工作】nodejs下载安装(npm环境) 1 下载安装nodejs 2 查看环境变量是否添加成功 3、验证是否安装成功 4、修改模块下载位置 &#xff08;1&#xff09;查看npm默认存放位置 &#xff08;2&#xff09;在 nodejs 安装目录下&#xff0c;创建 “node_global…