Python 类,对象,数据分类,函数参数传递详解


Posted in Python onSeptember 25, 2021

最近在基于python写的接口自动化脚本,从Excel表中读取所有数据,每一行数据保存为字典,再将很多行的字典数据保存到一个列表里,运行时发现,列表中的字典均相同,且一直是excel最后一行的数据,情况类比如下:

dd = {"a":1,"b":10}
i = 2
list1 = []
while i< 5:
    dd["a"] = i
    i+=1
    list1.append(dd)
print("list1:{}".format(list1))

运行结果如下图,打印结果并不是预期的 list1:[{'b': 10, 'a': 2}, {'b': 10, 'a': 3}, {'b': 10, 'a': 4}] ,为什么呢??

Python 类,对象,数据分类,函数参数传递详解

问题的关键在于,数据分为可变及不可变类型,python中字典是可变类型,列表实际保存的是字典所指向的那片内存,而这片内存的内容,保存的是最后一次修改的值。  

为加深理解,重新温故下python关于类、对象、数据分类、函数传递参数的相关知识。

1、基本概念

1.1 类与对象的关系

对象:包含属性(特征)和方法(行为)。例如,狗作为一个对象,有年龄、眼睛等特征,有走路、觅食等行为。

:即把有相同属性和方法的对象进行提取(抽象化),是对象的模板。例如,对狗这个对象进行抽象化,把具有觅食行为,具有年龄等相同特征的对象,抽象一个Animal类。1.2 self的作用

class Animal():
    self.age = 0    #类属性
    def Eat(self):      #类方法
        print ("觅食")
dog = Animal()   #类的实例化,即对象
cat = Animal()   #类的实例化,即对象
dog.Eat()   #相当于Animal.Eat(dog)

在python里,当对象调用类中的方法时,需要先把对象作为参数传入方法中,相当于告诉类,“老子来调用这个方法啦,留个名”。而对象把自己传入方法,就是通过self。  

如上图,dog对象调用Eat(self)方法,执行dog.Eat()时,先用self接收dog对象,等同于执行Animal.Eat(dog)。  

正是因为self参数接收的是对象本身,而self的英文翻译就是“自己,自个”,所以大家都约定俗成的用了这个单词,它并不是python的关键字,如果换成把self缓存that,here等,其实也一样。

1.3 对象的创建与引用  

在python中,一切都是对象。对象均具备三个属性:地址,类型,值。  

当"左边 = 右边"时,实际是创建、引用对象的过程。  

如a = 3, 3实际上是一个对象,且对象的值为3,对象创建后存储在内存中,被a所引用。

Python 类,对象,数据分类,函数参数传递详解

如果对象中的值可以更改,该值属于可变类型;  

如果对象中的值不能更改,该值属于不可变类型;  

如果对象中又包含对其他对象的引用,该对象就是容器,如d={},list1[0]=d,list1就是容器。

2、数据的分类  

数据可变不可变,指的是存储在内存的内容,即对象的值,是否可以被修改,分为俩大类:

  • 不可变类型:例如整型,浮点型,字符串类型;
  • 可变类型:例如字典,列表。

2.1 不可变类型  

不可变类型,即对象本身的值不可以改变。  

python在引用不可变类型的对象时,会寻找该对象是否创建过,若该对象已创建,则变量会直接引用该对象,不会再申请新的内存空间。

a = 3
b = 3
print(id(a))
print(id(b))
a = 4
print(id(a)) 
>> 502853488
>> 502853488
>> 502853520

3这个对象创建后,a、b都引用了它,所以打印出来的地址是相同的。  

当a = 4后,因为3属于不可变类型,因此又创建了一个4的对象,将a指向这个新创建的对象。

2.2 可变类型  

可变类型,即在对象本身的值允许改变,而内存地址不需要改变,如 列表.append。  

python在引用不可变类型的对象时,会先申请新的内存空间,来存储这个对象,有别于不可变类型。

a = [1,2,3]
b = [1,2,3]
print(id(a))
print(id(b))
a.append(4)
print(id(a)) 
>> 48751048
>> 48751560
>> 48751048

a、b创建了俩个相同内容的列表,但是其指向的内存地址不相同。当对a指向的可变对象增加元素后,a所引用的对象内容已改变,但地址依旧不变。

3、函数传递参数的方式

3.1 值传递  

主函数向调用函数传递的参数是不可变类型时,实际上只是将实参的拷贝(即临时副本)传递给了被调用函数,并不是实参本身,这样被调函数不能直接修改主调函数中变量的值,而只能修改其私有的临时副本的值。

def ChangeList(list1):
    list1[1] = 5
li = [1,1,1]
print (li)
ChangeList(li)
print (li)
>> [1, 1, 1]
>> [1, 5, 1]

如代码所示,s是字符串,属于不可变类型,传递给ChangeString(s)时,是将s实际的值传入,s本身不会被改变。

3.2 引用传递  

主函数向调用函数传递的参数是可变类型时,实际上是将实参的引用传入了调用函数,对引用的操作等于对其指定的对象进行操作。

def ChangeList(list1):
    list1[1] = 5li = [1,1,1]
print (li)
ChangeList(li)
print (li)
>> [1, 1, 1]
>> [1, 5, 1]

如代码所示,li是列表,属于可变类型,传递给ChangeList(list1)时,list1也指向了li所引用的同一片内存。

总结

1、类是对象的抽象化,对象是类的实例化,在python中一切都是对象。  

2、self代表的是对象本身,将对象作为一个参数传入方法中执行。  

3、内存中的内容按是否可以修改,分为可变类型和不可变类型,所对应的可变对象和不可变对象,创建和引用方式也不同。  

4、不可变类型参数被函数调用时,是值传递,可变类型参数被函数调用时,是引用传递。

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注三水点靠木的更多内容!

Python 相关文章推荐
python刷投票的脚本实现代码
Nov 08 Python
Python调用命令行进度条的方法
May 05 Python
Python实现队列的方法
May 26 Python
Python脚本实现自动发带图的微博
Apr 27 Python
Python实现 多进程导入CSV数据到 MySQL
Feb 26 Python
Python语言描述随机梯度下降法
Jan 04 Python
python读写csv文件并增加行列的实例代码
Aug 01 Python
Python 安装 virturalenv 虚拟环境的教程详解
Feb 21 Python
在Python中使用K-Means聚类和PCA主成分分析进行图像压缩
Apr 10 Python
tensorflow 2.0模式下训练的模型转成 tf1.x 版本的pb模型实例
Jun 22 Python
详解Python中openpyxl模块基本用法
Feb 23 Python
python简单验证码识别的实现过程
Jun 20 Python
Python实现简单的俄罗斯方块游戏
Python实现滑雪小游戏
利用python实时刷新基金估值(摸鱼小工具)
Sep 15 #Python
Python极值整数的边界探讨分析
Sep 15 #Python
Python办公自动化PPT批量转换操作
Sep 15 #Python
Python办公自动化解决world文件批量转换
Sep 15 #Python
Python函数式编程中itertools模块详解
Sep 15 #Python
You might like
咖啡店都有些什么常规豆子呢?有什么风味在里面
2021/03/04 咖啡文化
一些需要禁用的PHP危险函数(disable_functions)
2012/02/23 PHP
PHP中extract()函数的妙用分析
2012/07/11 PHP
php获取网页标题和内容函数(不包含html标签)
2014/02/03 PHP
PHP Static延迟静态绑定用法分析
2016/03/16 PHP
PHP中explode函数和split函数的区别小结
2016/08/24 PHP
magento后台无法登录解决办法的两种方法
2016/12/09 PHP
laravel-admin自动生成模块,及相关基础配置方法
2019/10/08 PHP
免费空间广告万能消除代码
2006/09/04 Javascript
让div层随鼠标移动的实现代码 ie ff
2009/12/18 Javascript
ExtJS 工具栏 分页事件参数
2010/03/05 Javascript
artDialog 4.1.5 Dreamweaver代码提示/补全插件 附下载
2012/07/31 Javascript
jquery焦点图片切换(数字标注/手动/自动播放/横向滚动)
2013/01/24 Javascript
jQuery创建平滑的页面滚动(顶部或底部)
2013/02/26 Javascript
Javascript aop(面向切面编程)之around(环绕)分析
2015/05/01 Javascript
jquery validate.js表单验证入门实例(附源码)
2015/11/10 Javascript
基于javascript html5实现多文件上传
2016/03/03 Javascript
JavaScript编码风格指南(中文版)
2016/08/26 Javascript
Vue集成Iframe页面的方法示例
2017/12/12 Javascript
Javascript数组方法reduce的妙用之处分享
2019/06/10 Javascript
原生JS实现顶部导航栏显示按钮+搜索框功能
2019/12/25 Javascript
[16:19]教你分分钟做大人——风暴之灵
2015/03/11 DOTA
[55:54]FNATIC vs EG 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
django框架使用views.py的函数对表进行增删改查内容操作详解【models.py中表的创建、views.py中函数的使用,基于对象的跨表查询】
2019/12/12 Python
使用Python FastAPI构建Web服务的实现
2020/06/08 Python
Windows下Sqlmap环境安装教程详解
2020/08/04 Python
Python3中小括号()、中括号[]、花括号{}的区别详解
2020/11/15 Python
英国户外玩具儿童游乐设备网站:TP Toys(蹦床、攀爬框架、秋千、滑梯和游戏屋)
2018/04/09 全球购物
戴尔荷兰官方网站:Dell荷兰
2020/10/04 全球购物
四风存在的原因分析
2014/02/11 职场文书
《童趣》教学反思
2014/02/19 职场文书
公司采购主管岗位职责
2014/06/17 职场文书
硕士生找工作求职信
2014/07/05 职场文书
综治维稳工作承诺书
2014/08/30 职场文书
采购内勤岗位职责
2015/04/13 职场文书
mysql优化
2021/04/06 MySQL