Python:类和对象

注意:本文引用自专业人工智能社区Venus AI

更多AI知识请参考原站 ([www.aideeplearning.cn])

面向对象编程 VS 面向过程编程


在使用计算机语言进行代码编写时,常见的两种思路是面向对象编程和面向过程编程:


(1)面向过程:根据业务逻辑从上到下写代码。
(2)面向对象:将数据与函数绑定到一起,分类进行封装,每个程序员只要负责分配给自己的分类,这样能够更快速地开发程序,减少了重复代码。


举一个生活中吃北京烤鸭的例子来解释这两种思路:


第一种方式(面向过程):第一步养鸭子;第二步鸭子长成;第三步杀鸭子;第四步配置佐料;第五步腌制烤鸭;第六步烤制烤鸭;第七步吃。
第二种方式(面向对象):第一步找个养烤鸭的农户;第二步找个厨子;第三步吃。


面向对象的思维解决问题的重点是当遇到一个需求的时候,不用自己去实现。例如之后要学习的PyTorch就是一种深度学习中面向对象编程的思想。读者甚至不需要知道深度学习中常见的诸如卷积算法等操作如何用代码编写,因为PyTorch深度学习框架已经把这些基础功能封装成了函数,想使用的时候直接调用函数名字即可,这为初学者们入门深度学习提供了极大的便利。

类与对象

1. 类的创建


类是对具有相同特征的对象进行抽象的概念,这些特征包含静态的和动态的,分别对应类的属性和方法。例如,鸟类的静态特征是长着一双翅膀,动态特征是会飞;而狗类的静态特征是嗅觉灵敏,动态特征是会“汪汪”叫。因此,再加上类的名字,这三个成分就组成的类的概念。


举例:
(1)狗类的设计:
类名:狗(Dog);
属性:品种、毛色、性别、名字、腿的数量等;
方法:(行为/功能):叫、跑、咬人、吃、摇尾巴等。


如何把日常生活中的事物抽象成程序中的类?实际上,拥有相同(或者类似)属性和行为的对象都可以抽象出一个类。常用的一个方法为名词提炼法:一般名词都是类。


举例:
(1)飞机发射7颗炮弹轰掉了一个舰队。
飞机:可以抽象成“飞机类”;
炮弹:可以抽象成“武器类”;
舰队:可以抽象成“船类”。
(2)小美在公园中牵着一条叼着热狗的狗。
小美:人类;
公园:场景类;
热狗:食物类;
狗:狗类。

详细代码示例

一般,使用class语句来创建一个新类,class之后为类的名称(通常首字母大写)并以冒号结尾,代码如下:

#lei.py
class Car():    # 方法    def getCarInfo(self):    print('车轮子个数:%d, 颜色%s'%(self.wheelNum, self.color))    def move(self):    print("车正在移动...")

在类中,可以定义所使用的方法,类中的方法与普通的函数只有一个特别的区别:它们必须有一个额外的第一个参数名称, 按照惯例它的名称是self。它表示类创建的实例本身,指向当前创建对象的内存地址。某个对象调用其方法时,Python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可。

#lei.py
# 定义类    
class Car():    # 定义移动方法    def move(self):    print('车在行驶...')    # 定义鸣笛方法    def toot(self):    print("车在嘟嘟..")    
# 创建一个对象,并用变量Wuling来保存它的引用    
Wuling = Car()    
Wuling.color = 'white' #使用‘.’符号的方法添加类属性:车的颜色    
Wuling.wheelNum = 4 #使用‘.’符号的方法添加类属性:轮子数量    
Wuling.move() #使用‘.函数名()’的语法调用类中函数:车的行驶    
print(Wuling.color) #打印实例五菱的颜色属性    
print(Wuling.wheelNum) #打印实例五菱的车轮数量属性
车在行驶...
white
4

在上面的实例中,我们给五菱神车添加了两个对象属性:wheelNum和color,试想一下,如果再次创建一个对象的话,创建之后需要重新进行属性添加,这样做是很麻烦的。那么是否可以在创建对象时,就顺便把属性也给予了呢? 这就是init()函数的作用。代码如下:

#lei.py
# 定义汽车类    
class Car():    # 初始化函数,对象属性有默认值:4和white;也可以通过传参的方法对对象属性进行重新赋值    def __init__(self, wheelNum=4, color='white'):    self.wheelNum = wheelNum    self.color = color    # 定义类方法    def move(self):    print('车在行驶')    
# 创建对象五菱神车,不传参时,属性使用默认值    
Wuling = Car()     
print('五菱车的颜色为:',  Wuling.color)    
print('五菱车轮胎数量为:', Wuling.wheelNum)
# 创建对象自行车,传参时,新的传参值代替默认值    
Bicycle = Car(2, 'black')    
print('自行车的颜色为:',  Bicycle.color)    
print('自行车轮胎数量为:', Bicycle.wheelNum)  
五菱车的颜色为: white
五菱车轮胎数量为: 4
自行车的颜色为: black
自行车轮胎数量为: 2


注意:
(1)当创建“Wuling对象”后,在没有调用方法的前提下,Wuling就默认拥有了2个属性:wheelNum和color,原因是方法是在创建对象后,就立刻被默认调用了init()函数,不需要手动调用。
(2)init(self)中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么除了self作为第一个形参外还需要2个形参,例如init(self, x, y)。
(3)init(self)中的self参数,不需要开发者传递,Python解释器会自动把当前的对象引用传递进去。

2. 魔法方法

魔法方法是在Python的类中被双下划线前后包围的方法。这些方法在类或对象进行特定的操作时会自动被调用,读者可以使用或重写这些魔法方法,给自定义的类添加各种特殊的功能来满足自己的需求。3.5.2节已经介绍过初始化魔法方法init,也是在定义类时最常见的魔法方法。除此之外,还有一些常见的魔法方法如下。

构造类的魔法方法


我们都知道一个最基本的魔术方法,init。通过此方法可以定义一个对象的初始操作。但init并不是第一个被调用的方法。

实际上,还有new方法,来实例化这个对象。然后,在创建时给初始化函数传递参数。在对象生命周期的另一端,也有del方法。

接下来看一看这三个方法。
new(cls, […])是在一个对象实例化的时候所调用的第一个方法,所以它才是真正意义上的构造方法。它的第一个参数是这个类,其他的参数是用来直接传递给init方法。


new 决定是否要使用该init方法,因为new可以调用其他类的构造方法或者直接返回别的实例对象来作为本类的实例,如果new没有返回实例对象,则init不会被调用。代码如下:

#lei.py
class Person(object):    def __new__(cls, *args, **kwargs):    print("__new__()方法被调用了")    print('这个是*agrs', *args)    print('这个是kwagrs', **kwargs)    # cls表示这个类,剩余所有的参数传给__init__()方法,    # 若不返回,则__init__()不会被调用    #return object.__new__(cls)  def __init__(self, name, age):    print("__init__()方法被调用了")    self.name = name    self.age = age    print(self.name, self.age)    
p = Person("张三", 20)  
__new__()方法被调用了
这个是*agrs 张三 20
这个是kwagrs

new()方法在什么场景使用呢? 当我们需要继承内置类时。例如,想要继承int、str、tuple,就无法使用init来初始化了,只能通过new来初始化数据。实际上,在日常的编写中,new()和del()这两个魔法函数一般都不常见,保持默认就好,经常编写的是init()函数。del()函数代码如下:

#lei.py
class Washer:    # 当一个实例被销毁时自动调用的方法。    def __del__(self):    """  当删除对象时,解释器会自动调用del方法  """    print('对象已删除!')    
haier = Washer()  

3. 类属性和类方法

3.1 类属性和实例属性

在了解了类的基本的信息之后,下面看一下类属性和实例属性这两个概念。 类属性顾名思义就是类所拥有的属性,分为共有属性和私有属性,私有属性通过“__属性名称”的方法进行定义。对于公有的类属性,可以在类外进行访问,私有属性在类外不可以直接访问,代码如下:

#lei.py
class People(object):    name = 'VenusAI'  #公有的类属性    __age = 7     #私有的类属性    def __init__(self):    pass    
p = People()    
print(p.name)           #正确    
print(People.name)     #正确    
#print(p.__age)          #错误,不能在类外通过实例对象访问私有的类属性    
#print(People.__age)    #错误,不能在类外通过类对象访问私有的类属性    
print(p._People__age) #这种特殊的访问方法可以在类外访问私有的类属性
VenusAI
VenusAI
7


注意:类属性是声明在类的内部,实例方法的外部的属性,即在class内,__init__(self)方法之前。


实例属性是从属于实例对象的属性,也称为“实例变量”,要点如下:


(1)实例属性一般在init()方法中通过如下代码定义“self.实例属性名 = 初始值”。


(2)在本类的其他实例方法中,也是通过self进行访问“self.实例属性名”。


(3)实例属性可修改、新增、删除。


需要注意的是,如果在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用修改,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性。当类属性与实例属性同名时,一个实例访问这个属性时实例属性会覆盖类属性,但类访问时不会。代码如下:

#lei.py
class People(object):    country = 'China' #类属性    
# 访问类属性    
print(People.country)    
# 实例化对象    
p = People()    
# 访问实例属性    
print(p.country)    
# 修改实例属性    
p.country = 'Japan'    
# 访问实例属性,实例属性会屏蔽掉同名的类属性    
print(p.country)       
# 访问类属性,会发现没有改变    
print(People.country)    
#通过类对象去引用修改类属性    
People.country = "UK"       
# 访问类属性    
print(People.country)
China
China
Japan
China
UK
3.2 实例方法、类方法和静态方法
1)实例方法

之前的例子中,在类中以def关键字定义的都可以称之为实例方法,不仅如此,类的初始化方法init()理论上也属于实例方法,只不过它比较特殊。实例方法最大的特点就是,它最少也要包含一个self参数,用于绑定调用此方法的实例对象“Python 会自动完成绑定”。实例方法通常会用类对象直接调用。

2)类方法

Python类方法和实例方法相似,它最少也要包含一个参数,只不过类方法中通常将其命名为cls,类方法是类对象所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数,可以通过实例对象和类对象去访问。类方法还有一个用途就是可以对类属性进行修改。代码如下:

#lei.py
class People(object):    country = 'China'    #类方法,用classmethod来进行修饰    @classmethod    def getCountry(cls):    return cls.country    @classmethod    def setCountry(cls,country):    cls.country = country    
p = People()    
print(p.getCountry())    #可以通过实例对象引用    
print(People.getCountry())    #可以通过类对象引用    
p.setCountry('Japan')     
print(p.getCountry())       
print(People.getCountry()) 
'''
China
China
Japan
Japan
'''
China
China
Japan
Japan

Out[8]:

'\nChina\nChina\nJapan\nJapan\n'


类方法什么时候使用呢?我们可以考虑一个场景。
假设有一个学生类和一个班级类,需实现的功能为:学生类继承自班级类,每实例化一个学生,班级人数都会增加。最后,需要实例化一些学生,并获取班级中的总人数。
思考:这个问题用类方法做比较合适,为什么?
我们要实例化的是学生,但是从学生实例中获取班级总人数,在逻辑上显然是不合理的。如果要获得班级总人数,生成一个班级实例是没有必要的。因此,编写一个类方法最为合适,这个方法能够访问并更新班级的总人数,而不需要创建班级实例。

3)静态方法


静态方法需要通过修饰器@staticmethod来进行修饰。静态方法是类中的函数。静态方法主要是用来存放逻辑性的代码,逻辑上属于类,但是和类本身没有关系,也就是说在静态方法中,不会涉及类中的属性和方法的操作。可以理解为,静态方法是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护。例如,笔者想定义一个关于时间操作的类,其中有一个获取当前时间的函数,代码如下:

#lei.py
import time    
class TimeTest(object):    def __init__(self, hour, minute, second):    self.hour = hour    self.minute = minute    self.second = second    @staticmethod    def showTime():    return time.strftime("%H:%M:%S", time.localtime())    
# 使用类对象调用静态方法    
print(TimeTest.showTime())    
# 实例化对象    
t = TimeTest(2, 10, 10)    
# 使用实例对象调用静态方法     
print(t.showTime())

 14:22:56

14:22:56

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

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

相关文章

SQLiteC/C++接口详细介绍sqlite3_stmt类(十一)

返回:SQLite—系列文章目录 上一篇:SQLiteC/C接口详细介绍sqlite3_stmt类(十) 下一篇: SQLiteC/C接口详细介绍sqlite3_stmt类(十二) 43、sqlite3_reset sqlite3_reset 函数用于重置已经编…

uniapp安装axios

先npm安装 npm i axios然后在项目里面建一个utils文件,再建一个index.js 以下是index.js代码: import axios from axios; const service axios.create({baseURL: //xxxx.xxxxx.com///你的请求接口域名, timeout: 6000, // request timeoutcrossDomai…

【C++】1599. 米老鼠偷糖果

问题:1599. 米老鼠偷糖果 类型:基本运算、整数运算 题目描述: 米老鼠发现了厨房放了 n 颗糖果,它一次可以背走 a 颗,请问米老鼠背了 x 次之后还剩多少颗?(假设 x 次之后一定有糖果剩下&#x…

Redis中的缓存击穿

缓存击穿 缓存击穿问题也叫热点key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大压力。 🤔现象分析: 当线程1查询缓存时,未命中,于是从数据…

transformer的自注意力模型如何实现自注意力

Transformer | 鲁老师 所有参考来自以上的文章,简单来说,要实现自注意力,就得去完成 自己点乘自己的操作,然后得到的结果就能够通过调整矩阵参数完成训练了。 简单来说,构造了三个矩阵 ,这三个矩阵就是为…

界面控件DevExpress ASP.NET Ribbon组件 - 完美复刻Office 365体验!

无论用户是喜欢传统工具栏菜单外观、样式,还是想在下一个项目中复制Office 365 web UI,DevExpress ASP.NET都提供了所需要的工具,帮助用户打造更好的应用程序界面。 P.S:DevExpress ASP.NET Web Forms Controls拥有针对Web表单&a…

基于python+vue的O2O生鲜食品订购flask-django-nodejs-php

近年来互联网络的迅猛发展和电子终端设备的普及,赋予了各行业充足的发展空间。微信小程序的O2O生鲜食品订购相比于传统信息技术,时效性是它最大的特色,已经在电子娱乐、经济等中发挥着举足轻重的作用。短时间内迅速扩大了线上管理系统的规模。…

【PHP】通过PHP实时监控Apache、MySQL服务运行状态

一、前言 有些时候我们需要监控一些服务的运行状态,比如说Apach或MySQL的运行状态,最近工作中也开发了这方面的功能,记录下来怎样使用PHP语言来实时监控Apache、MySQL服务的运行状态。 如果想一键开启Apache或MySQL等其他服务可以看这篇文章…

CSS color-mix() 函数

CSS color-mix() 函数是近年来CSS色彩模块新增的一项强大功能,允许开发者在样式表中直接混合两种或多种颜色。这一特性为设计师和开发者带来了更多创作空间,让网页的颜色设计变得更加生动和丰富。本文将带你了解 color-mix() 函数的使用方法及其在实际项…

计网--网络层个人笔记

网络层的IP分组由路由器转发,而每一个路由器有很多接口,那么从哪一个接口转发便需要转发表。 一、网络层基本功能 二、SDN基本概念 2.1 路由器 数据平面:转发的过程。一个分组如何从一个端口到达另一个端口。 控制平面:路由选择…

JAVA 8 新特性 Lamdba表达式(二)

一、Lamdba的语法 (参数类型1 参数1,参数类型2 参数2,…) -> { 方法体 }; Lambda表达式就是一个匿名函数,不关注方法名,只关注参数和方法体。 Lambda表达式组成三要素:括号(),箭头->,代码…

ES 8.x的多实例集群搭建与角色规划

ES 8 多实例集群搭建与角色规划 ES 8版本与之前版本存在较大改变,第一个区别就是启动时默认开启了安全模式,也就是即便是测试环境也需要用户名密码和https传输层安全证书。此外,集群节点的角色也与之前不同,除了新增角色外在配置…

Unity 获取鼠标滚轮信息的一些方法

Unity获取鼠标滚轮信息有以下一些方法: 1、使用Input.GetAxis(“Mouse ScrollWheel”)来获取鼠标滚轮的信息,如: //法一:float scrollWheelInput Input.GetAxis("Mouse ScrollWheel");if (scrollWheelInput > 0f){…

机器学习的概念、步骤、分类和实践

作为资深人工智能专家,对机器学习有着深入的研究和实践经验。以下是对机器学习概念、步骤、分类和实践的逐步分析: 一、机器学习概念 机器学习是人工智能的一个子集,它让计算机从数据中学习并改进其性能,而无需进行明确的编程。…

使用专属浏览器在国内直连GPT教程

Wildcard官方推特发文说他们最近推出了一款专门为访问OpenAI设计的浏览器。 根据官方消息,这是一款专门为访问OpenAI优选网络设计的浏览器,它通过为用户提供专用的家庭网络出口,确保了快速、稳定的连接。 用这个浏览器的最大好处就是直接用浏…

【测试开发学习历程】MySQL增删改操作 + 备份与还原 + 索引、视图、存储过程

前言: SQL内容的连载,到这里就是最后一期啦! 如果有小伙伴要其他内容的话,我会追加内容的。(前提是我有学过,或者能学会) 接下来,我们就要开始python内容的学习了 ~ ~ 目录 1 …

Github 2024-03-22 开源项目日报Top10

根据Github Trendings的统计,今日(2024-03-22统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目3C#项目1Java项目1Rust项目1Go项目1Shell项目1非开发语言项目1TypeScript项目1Colossal-AI:使大型人工智能模型更加实惠和快速训练的…

吴恩达机器学习笔记 二十六 决策树学习过程 独热编码one-hot

决策树的学习过程 1. 所有样本都在根结点 2.计算所有可能的特征的信息增益,选择信息增益最大的那个 3.根据选择的特征分离数据集,创造左右两支子树 4.继续进行分裂直到达到停止标准。停止标准有:一个节点只有一类样本;分裂一…

[ABC206E] Divide Both 解题记录

[ABC206E] Divide Both 解题记录 题意简述 给定整数 L , R L,R L,R,求满足以下条件的数对 ( x , y ) (x,y) (x,y) 的数量。 x , y x,y x,y 不互质 x ∤ y x \nmid y x∤y 且 y ∤ x y \nmid x y∤x 题目分析 正难则反,考虑用所有的满足第一条性质的…

javascript中Date相关方法

Date 对象用于处理日期和时间 序号方法描述1new Date()获取当前时间2parse()返回毫秒数(从 1970-1-1 00:00:00开始)3getDate()返回月中的第几天(从 1 到 31)4getFullYear()返回年份5getMonth()返回月份(从 0-11&#x…