一、赋值、浅拷贝与深拷贝
-
直接赋值:其实就是对象的引用(别名)。
-
浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象。
-
深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象。
赋值实例:
# 赋值运算 变量指向同一个内存地址 l1 = [1,2,3] l2 = l1 l3 = l2 l1.append(666) print(l1,l2,l3) print(id(l1),id(l2),id(l3)) # 运行结果: # [1, 2, 3, 666] [1, 2, 3, 666] [1, 2, 3, 666] # 1543171498568 1543171498568 1543171498568 赋值运算 变量指向同一个内存地址
浅拷贝实例:
# copy一个新列表(dict),列表在内存中是新的,但是列表里面的元素,完全沿用之前的元素。 l1 = [1, 2,{'alex':23},4,[22,33]] l2 = l1.copy() l1[-1].append(44) l1[2]['taibai'] = 18 l2[-1].append(55) l2[2]['egon'] = 36 print(id(l1),id(l2)) #1583337071240 1583337553800 print(id(l1[-1]),id(l2[-1])) #1583337071176 1583337071176 print(l1,l2)#[1, 2, {'alex': 23, 'taibai': 18, 'egon': 36}, 4, [22, 33, 44, 55]] [1, 2, {'alex': 23, 'taibai': 18, 'egon': 36}, 4, [22, 33, 44, 55]] l1[0] = 2 l1[-1].append(88) l2[-1].append(99) l1.append(666) l2.append(999) print(l1,l2)#[2, 2, {'alex': 23, 'taibai': 18, 'egon': 36}, 4, [22, 33, 44, 55, 88, 99], 666] [1, 2, {'alex': 23, 'taibai': 18, 'egon': 36}, 4, [22, 33, 44, 55, 88, 99], 999] print(id(l1[0]),id(l2[0])) #140721386935360 140721386935328 print(id(l1),id(l2))#1866099286664 1866099769224
l1 = [1, 2, 3, [22, 33]] l2 = l1[:] # 切片 是 浅copy l1[-1].append(666) print(id(l1),id(l2)) #不是赋值关系 2304312369800 2304312852040 print(l1,l2) #[1, 2, 3, [22, 33, 666]] [1, 2, 3, [22, 33, 666]]
x = ['lily', '20', 'hr',['a']] y = x x[0] = 'lucy' z = list(x) #列表实例化对象也是前拷贝 x[0] = 'lilei' x[-1].append('b') z[-1].append('c') print(x,y,z)#['lilei', '20', 'hr', ['a', 'b', 'c']] ['lilei', '20', 'hr', ['a', 'b', 'c']] ['lucy', '20', 'hr', ['a', 'b', 'c']] print(id(x),id(y),id(z))#1744470303368 1744470303368 1744502045704
图片解析赋值、浅拷贝和深拷贝原理
1、b = a: 赋值引用,a 和 b 都指向同一个对象。
2、b = a.copy(): 浅拷贝, a 和 b 是一个独立的对象,但他们的子对象还是指向统一对象(是引用)。
3、b = copy.deepcopy(a): 深度拷贝, a 和 b 完全拷贝了父对象及其子对象,两者是完全独立的。
深拷贝实例:深度拷贝需要引入 copy 模块
import copy # 总结:深copy则会在内存中开辟新空间,将原列表以及列表里面的可变的数据类型重新创建一份, # 不可变的数据类型则沿用之前的。 l1 = [1, 2, 3, [22, 33]] l2 = copy.deepcopy(l1) print(id(l1), id(l2)) print(id(l1[0]),id(l2[0])) print(id(l1[-1]),id(l2[-1])) l1[0] = 2 l1[-1].append(666) print(l1,l2) # 运行结果: # 2522273468936 2522273389832 # 140732471497760 140732471497760 # 2522273604680 2522273605000 # [2, 2, 3, [22, 33, 666]] [1, 2, 3, [22, 33]] # # 小知识点: # id 测试对象的内存地址 # == 比较 比较两边的数值是否相等 # print(2 == 2) # is 判断 判断的两边对象的内存地址是否是同一个
03 文件操作
之前对文件进行的任何操作,都必须依赖一个文件编辑器,word wps等等
假设一个场景:
现在世界上没有任何个文件编辑器的产生。
'空姐护士白领学生联系方式'.txt
设计这个软件必要的三要素:
path:文件的路径。
encoding:文件以什么编码方式存储,就以什么编码方式读取。
mode:读,写,写读,读写,追加,改等等。
三个大方向:
带b的模式操作对象都是非文字类的文件:视频,音频,图片。
读(r rb r+ r+b)
r模式
rb
r+ 读写
写 w wb w+ w+b
w
wb
追加(a ab a+ a+b)
a
文件操作的其他方法:
f.read()
f.write()
f.readline()
f.readlines()
f.close()
f.seek()
f.tell()
改
二、文件操作
之前对文件进行的任何操作,都必须依赖一个文件编辑器,word wps等等
假设一个场景:
现在世界上没有任何个文件编辑器的产生。
'空姐护士白领学生联系方式'.txt
设计这个软件必要的三要素:
path:文件的路径。
encoding:文件以什么编码方式存储,就以什么编码方式读取。
mode:读,写,写读,读写,追加,改等等。不写mode默认是r
例子:
f1 = open(r'd:\美女护士空姐联系方式.txt', encoding='utf-8', mode='r')
content = f1.read()
print(content)
f1.close()
"""
f1 f f_h file_handler 变量,文件句柄。
open 内置函数 底层调用的操作系统的操作文件功能的接口。
windows: 默认编码gbk,linux utf-8 ios: utf-8.
操作文件总共3步;
1,打开文件,产生文件句柄。
2,对文件句柄进行操作。
3,关闭文件句柄。
"""
错误示范:
# 1,UnicodeDecodeError: 'gbk' codec can't decode... 编解码错误。
# 2,路径错误。路径分隔符 与后面的字符产生特殊的意义。 解决方式 r 或者 \
# 绝对路径:从根目录开始。
# 相对路径:同一个工作目录(文件夹)下。
例子:
f1 = open('log', encoding='utf-8', mode='r')
content = f1.read()
print(content)
f1.close()
三个大方向:
带b的模式操作对象都是非文字类的文件:视频,音频,图片。
1、读:r(只读) rb(bytes类型只读) r+(读写) r+b)
r模式 默认就是r模式
# 1.1 read()
f1 = open('log', encoding='utf-8',)
content = f1.read()
print(content,type(content))
# 1.2 read(n)
# r模式下,n代表字符。
f1 = open('log', encoding='utf-8',)
content = f1.read(3)
print(content)
# 1.3 readline() 按行读取
f1 = open('log', encoding='utf-8',)
print(f1.readline().strip())
print(f1.readline().strip())
f1.close()
# 1.4 readlines() 返回一个列表,列表里面的元素是原文件每一行
f1 = open('log', encoding='utf-8',)
content = f1.readlines()
print(content)
f1.close()
# 1.5 for循环
f1 = open('log', encoding='utf-8',)
for line in f1: # ['老男孩教育是最好的培训学校\n', '太白金星是最好的司机,老师\n', '深圳分校\n', '上海分校\n', '北京校区']
print(line.strip())
f1.close()
rb模式
f1 = open('log', mode='rb')
content = f1.read()
print(content)
print(content.decode('utf-8'))
f1.close()
r+ 读写模式
f = open('log',encoding='utf-8',mode='r+')
print(f.read())
f.write('666')
f.close()
# 先读后写会出问题(会从光标开始替换原来的内容)
# f = open('log',encoding='utf-8',mode='r+')
# f.write('松岛岛')
# print(f.read())
# f.close()
2、第二写模式 写 w wb w+ w+b
# w模式
没有文件创建文件写入内容,有文件,先清空内容后写入。
f = open('log1',encoding='utf-8',mode='w')
f.write('林志玲 fjdsklafjsd;flj太白金星')
f.write('深圳校区 ~~~')
f.write('深圳校区 ~~~')
f.write('深圳校区 ~~~')
f.write('深圳校区 ~~~')
f.write('深圳校区 ~~~')
f.close()
# wb模式
f1 = open('timg.jpg', mode='rb')
content = f1.read()
print(content)
f2 = open('time2.jpg',mode='wb')
f2.write(content)
f2.close()
# w+ 写读
f = open('log1',encoding='utf-8',mode='w+')
f.write('老男孩教育...')
f.seek(0)
print(f.read())
f.close()
3、追加(a ab a+ a+b)模式 a 追加 没有文件创建文件追加内容,有文件,在文件最后追加内容。
f = open('log3',encoding='utf-8',mode='a')
f.write('老男孩')
f.close()
文件操作的其他方法:
# seek 调整光标位置 按照字节 所以会有问题因为除了acsll码都是多个字节一个字符
# seek(0) 将光标移动到开始 seek(0,2) 将光标移动到最后。
# tell 获取光标位置 按照字节。
# readable() writable() 是否可以读?可以写?
例子:
f = open('log3',encoding='utf-8')
f.seek(1)
print(f.read())
print(f.tell())
f.seek(0) # 将光标移动到开始
print(f.tell())
f.seek(0,2) # 将光标移动到最后。
print(f.tell())
print(f.read())
print(f.writable())
if f.writable():
f.write('111')
f.close()
# flush 刷新 保存
f = open('log3',encoding='utf-8',mode='w')
f.write('fjdsklafjdfjksa')
f.flush()
f.close()
# truncate 截断截取
f = open('log3',encoding='utf-8',mode='r+')
f.truncate(3)
f.close()
文件的改
'''
1,以读的模式打开原文件。
2,以写的模式打开新文件。
3,读取原文件对源文件内容进行修改形成新内容写入新文件。
4,将原文件删除。
5,将新文件重命名成原文件。
'''
# 方法一 小文件可以。
# import os
#
# # 1,以读的模式打开原文件。
# # 2,以写的模式打开新文件。
# with open('alex个人简历',encoding='utf-8') as f1,\
# open('alex个人简历.bak',encoding='utf-8',mode='w') as f2:
# # 3,读取原文件对源文件内容进行修改形成新内容写入新文件。
# old_content = f1.read()
# new_content = old_content.replace('alex','SB')
# f2.write(new_content)
#
# # 4,将原文件删除。
# os.remove('alex个人简历')
# # 5,将新文件重命名成原文件。
# os.rename('alex个人简历.bak','alex个人简历')
# 方法二:
import os
# 1,以读的模式打开原文件。
# 2,以写的模式打开新文件。
# with open('alex个人简历',encoding='utf-8') as f1,\
# open('alex个人简历.bak',encoding='utf-8',mode='w') as f2:
# # 3,读取原文件对源文件内容进行修改形成新内容写入新文件。
# for old_line in f1:
# new_line = old_line.replace('SB','alex')
# f2.write(new_line)
#
# # 4,将原文件删除。
# os.remove('alex个人简历')
# # 5,将新文件重命名成原文件。
# os.rename('alex个人简历.bak','alex个人简历')
三、函数的初识
什么是函数
函数的结构
函数的返回值
函数的参数
05 函数的进阶
名称空间
作用域
加载顺序
取值顺序
内置函数 locals() globals()
高阶函数(函数的嵌套)
nonlocal global
函数名的作用
1、函数(结构、作用、返回值)
# 面向过程编程
s1 = 'fjksdfjsdklf'
count = 0
for i in s1:
count += 1
print(count)
l1 = [1, 2, 3, 4, 5]
count = 0
for i in l1:
count += 1
print(count)
# 缺点:
# 1,代码重复太多。
# 2,代码的可读性差。
# 面向函数式编程:
def my_lf_len(s):
count = 0
for i in s:
count += 1
print(count)
s1 = 'fjdsklafsdkalfjsda'
l1 = [1,2,3,3,5,56,6,6]
my_lf_len(s1)
my_lf_len(l1)
# 函数是什么?
# 功能体,一个函数封装的一个功能,
# 结构:
'''
def 函数名():
函数体
'''
# 函数什么时候执行?
def my_lf_len(s):
count = 0
for i in s:
count += 1
print(count)
my_lf_len('fdskfjskdlf')
# 函数的返回值
def Tantan():
print('搜索')
print('左滑动一下')
print('右滑动一下')
# return
print('发现美女,打招呼')
# return '美女一枚'
# return ['恐龙一堆']
return '小萝莉', '肯德基', '御姐'
# 调用一次执行一次
Tantan()
# Tantan()
# Tantan()
'''
return:
1,终止函数。
2,给函数的调用者(执行者)返回值。
return ---> 函数名() None
return 单个值 ---> 函数名() 单个值
return 多个值 ---> 函数名() (多个值,)
'''
ret = Tantan()
print(ret)
print(type(ret))
2、函数(参数)
def Tantan(sex): #函数的定义:sex形式参数,形参
print('搜索')
print('左滑动一下')
print('右滑动一下')
print('发现美女,打招呼')
return '小萝莉', '肯德基', '御姐'
# 函数的参数
Tantan('女') # 函数的执行:'女' 实际的数据, 实参。
# 实参
# 位置参数。 从左至右,一一对应
def Tantan(sex,age):
print('筛选性别%s,年龄%s左右' %(sex,age))
print('搜索')
print('左滑动一下')
print('右滑动一下')
print('发现美女,打招呼')
Tantan('女',28,)
# 练习:
# # n = 3 if 你看到卖西瓜 :n = 1
def max_(a,b): return a if a > b else b
# # if a > b:
# # return a
# # else:
# # return b
# # return a if a > b else b
print(max_(100,200))
# 三元运算符
# a = '饼'
# b = '西瓜'
# ret = a if 3 > 2 else b
# print(ret)
# 关键字参数。 一一对应。
# 函数参数较多 记形参顺序较麻烦时,需要关键字参数。
def Tantan(sex,age,area):
print('筛选性别%s,%s 附近,年龄%s左右的美女' %(sex,area,age))
print('搜索')
print('左滑动一下')
print('右滑动一下')
print('发现美女,打招呼')
Tantan(sex='女',area='南山区',age='28')
# 混合参数 : 一一对应,关键字参数必须要在位置参数后面。
def Tantan(sex,age,area):
print('筛选性别%s,%s 附近,年龄%s左右的美女' %(sex,area,age))
print('搜索')
print('左滑动一下')
print('右滑动一下')
print('发现美女,打招呼')
Tantan('女',28,area='南山区')
# 形参。
# 位置参数。 从左至右,一一对应。
def Tantan(sex,age):
print('筛选性别%s,年龄%s左右' %(sex,age))
print('搜索')
print('左滑动一下')
print('右滑动一下')
print('发现美女,打招呼')
Tantan('女',28,)
# 默认参数 : 使用最多的一般不更改的参数,默认参数一定放在位置参数后面
def Tantan(area,age,sex='girl'):
print('筛选性别%s, %s 附近,年龄%s左右的美女' %(sex,area,age))
print('搜索')
print('左滑动一下')
print('右滑动一下')
print('发现美女,打招呼')
Tantan('南山区',28,'laddboy')
# 万能参数 *args, **kwargs
def Tantan(*args,**kwargs):
# 函数的定义: * 代表聚合。
# * 将实参角度所有的位置参数放到一个元祖中,并将元组给了args
# ** 将实参角度所有的关键字参数放到一个字典中中,并将子弹给了kwargs
# print('筛选性别%s, %s 附近,年龄%s左右的美女' %(sex,area,age))
# print(args)
# print(kwargs)
print('筛选地域:%s,年龄%s' % args)
print('搜索')
print('左滑动一下')
print('右滑动一下')
print('发现美女,打招呼')
# # Tantan('南山区','28', '性格好','身材好', '家境好')
Tantan('南山区','28',body='身材好',voice='萝莉音',money='白富美')
例子:
def Tantan(*args,**kwargs):
# 函数的定义: * 代表聚合。
# * 将实参角度所有的位置参数放到一个元祖中,并将元组给了args
# ** 将实参角度所有的关键字参数放到一个字典中中,并将子弹给了kwargs
print(args)
print(kwargs)
Tantan('南山区','28',body='身材好',voice='萝莉音',money='白富美')
l1 = [1,2,3]
l2 = (4,5,6)
Tantan(*l1,*l2) # 函数的执行:*iterable 打散 **dic 将所有的键值对添加到kwargs。
Tantan(1, 2, 3, 4, 5, 6)
dic1 = {'name':"alex"}
dic2 = {'age':46}
Tantan(**dic1,**dic2)
# 形参的最终顺序
# 位置参数 *args 默认参数 **kwargs
def func(a,b,*args,sex='女',):
print(a,b,sex,args)
func(1,2,4,5,6,sex='男')
def func(a,b,*args,sex='女',**kwargs):
print(a,b,sex,args,kwargs)
func(1,2,4,5,6,name='alex',age=73)
3、函数进阶
name = 'barry'
def func():
name = 'alex'
func()
print(name)
func()
# python的空间三种:
# 全局名称空间
# 局部名称空间
# 内置名称空间
# python中的作用域:
# 全局作用域:内置名称空间 全局名称空间
# 局部作用域:局部名称空间
# 取值顺序: 就近原则
# 局部名称空间 ——————> 全局名称空间 ——————> 内置名称空间
# 加载顺序
# 内置名称空间 -------> 全局名称空间 -------> 局部名称空间
input = 'barry'
def func():
# input = 'alex'
print(input)
func()
print(input)
def func():
print(111)
def func1():
print(222)
func()
def func3():
print(333)
func1()
print(444)
func()
print(555)
# 444 111 555
def func():
print(111)
def func1():
print(222)
func()
def func3():
print(333)
func1()
print(444)
func3()
print(555)
# 444 333 222 111 555
def wraaper():
print(222)
def inner():
print(111)
print(444)
inner()
print(333)
wraaper()
# 222 444 111 333
#globals() locals()
name = 'alex'
age = 46
def func():
sex = '男'
hobby = '女'
print(globals()) # 返回一个字典:全局作用域的所有内容
print(locals()) # 当前位置的内容
func()
print(globals()) # 返回一个字典:全局作用域的所有内容
print(locals()) # 当前位置的内容
# 函数名的运用
# def func():
# print(666)
# 1,函数名是一个特殊的变量 函数名() 执行此函数
# func()
# 2,函数名可以当做变量进行赋值运算。
# def func():
# print(666)
# age1 = 12
# age2 = age1
# age3 = age2
# print(age3)
# f = func
# f()
# 下面不能执行
# age1 = 33
# age1()
print(globals())
# 3,函数名可以作为容器型数据的元素。
def func():
print(666)
def func1():
print(777)
def func2():
print(888)
def func3():
print(999)
a = 1
b = 2
c = 3
d = 4
l1 = [a, b, c, d]
l1 = [func, func1, func2, func3]
# for i in l1:
# i()
dic = {
1: func,
2: func1,
3: func2,
4: func3,
}
dic[1]()
dic[2]()
dic[3]()
# # while 1:
# # num = input('请输入序号:').strip()
# # if num == '1':
# # func()
# # elif num == '2':
# while 1:
# num = input('请输入序号:').strip()
# num = int(num)
# dic[num]()
# 4,函数名可以作为函数的参数。
# def func1():
# print(111)
# def func2(x):
# x()
# print(222)
# 5,函数名可以作为函数的返回值。
# def func1():
# print(111)
# def func2(x):
# print(222)
# return x
# ret = func2(func1)
# ret()
# 函数名的应用:问题
# def func():
# print(1111)
# func()
# f = func
# func = 1
# print(func)
# print(f)
# age1 = 12
# age2 = age1
# age3 = age2
# age2 = 46
# print(age1,age2,age3) # 12 46 12
# age1 = [1,2,3]
# age2 = age1
# age1.append(666)
# print(age1,age2)
# global nonlocal
# global
#1,声明一个全局变量。
# def f():
# print(name)
# def func():
# global name
# name = 'alex'
# func()
# f()
# print(name)
# print(globals())
# 2,修改一个全局变量。
# 原因:局部作用域只能引用全局变量而不能改变全局变量。
count = 1
def func1():
global count
count += 1
print(count)
func1()
print(count)
# nonlocal: 子级函数可以通过nonlocal修改父级(更高级非全局变量)函数的变量。
# 现象:子级函数可以引用父级函数的变量但是不能修改。
def func():
count = 1
def func1():
def inner():
nonlocal count
count += 1
print(count) # 2
print(count) # 1
inner()
print(count) # 2
func1()
func()
count = 1
def func1():
def inner():
nonlocal count
count += 1
print(count)
inner()
func1()