python day14 深浅拷贝,集合,函数

深浅拷贝

a=[[1,2],1,2,3]
b=a.copy()

就是把a的值赋给b

按常理说,我修改a或b,对另一个变量不会有任何影响

但是!

如果进行下列操作

b[0][0]=3

 则a输出的结果是[[3,2],1,2,3]

这就是传说中的浅拷贝(只拷贝了第一层)

为了理解这一原理,我们需要掌握一点关于内存的知识

variable1=1这一赋值操作,是先在内存中给予数字1一个内存地址(一般比较小的整数都有固定地址的,这里把1作为一个例子),再把这个内存地址赋予变量variable1

若在进行variable2=variable1的赋值,则是把variable1得到的内存地址赋予变量variable2

但是对于列表来说,比如a=[1,2],则是生成一个列表的内存地址赋予变量a,在列表的内存地址里赋予数字1和2的内存地址从而达到从列表取数的能力

回到我们发现的问题,b[0][0]=3这一操作,b[0]的内存地址没有变(和a[0]一样),但是b[0]里的b[0][0]的内存地址变了(被赋予了数字3的内存地址),而a和b的内存地址也同样没发生变化,所以我们调用a[0][0],它的内存地址和b[0][0]是一样的,即a[0][0]=3

如果是

a=[[1,1,2,3]
b=a.copy()
b[0]=4

根据之前的解答再分析一便,b[0]的内存地址变了,但是影响不到a[0],所以a依旧是[1,1,2,3] 

那怎么深拷贝呢?

import copy
a=[[1,2,3],1]
b=copy.deepcopy(a)
b[0][1]=8

 a的输出结果依旧是原来的!这就是深拷贝

集合set 

把不同的元素(不重复的成员)组合在一起

s=set('wawa')
print(s)

输出结果为{'w','a'}

s=set(['wawa','dada','wawa'])
print(s)

输出结果为{'wawa','dada'}
set最大的作用就是去重

set内元素要求可哈希(即不可修改!),列表和字典这两种数据类型就不满足

然而set这一数据类型是非哈希的,他不能作为字典的键(key)

set操作

s.add(),相当于列表的append

s.update(),用法和add不同,是把update内的数据类型拆分成单个元素放入集合,比如update('123'),添加的是‘1’,‘2’,‘3’。update(['a','b','ccc']),添加的是'a','b','ccc'

s.pop(),随机删除里面一个元素

s.clear(),把元素清空

s.intersection(s2),两个集合求交集,等同于s&s2,注意,这不是对集合s的修改(下面union和difference都一样)

s.union(s2),两个集合求并集,等同于s|s2

s.difference(s2),求s里面有,s2里面没有的集合,等同于s-s2

s.symmertic_difference(s2),对称差集,s和s2相互没有的集合的总和,等同于s^s2

s.issuperset(s2) 查看s是否为s2的真父集,等同于s>s2

s.issubset(s2) 查看s是否为s2的真子集,等同于s<s2

set中and,&和or,|之间的关系

首先声明,and!=&, or!=|

因为and 和 or 是逻辑运算符用于判断正误,而&和|是位运算符用于并集或交集

所以set1 & set2输出的是他俩的并集,|同理

但是对于逻辑运算符:

and只有两边都是True的才会输出True结果如果我们把and前后的True分别叫做True1和True2,输出的其实是最后的那个True2。如果and两边都是真值(有值就算是真值,a=1,a=[1,2,3],True都算真值),则输出的也和前面情况一样,输出后面的真值,所以

set1 and set2==set2

or,如果or前面的值为True,则结果一定为True,就不会管后面的值了,对于真值也一样,如果是set1 or XXX (XXX为任意数据类型)输出的结果一定是set1

函数

减少重复代码,方便修改,更易修改,保持代码一致性+

使用方法

def function_name():
    print('ok')
function_name()

输出结果为ok

注意,如果只写function_name不加括号,输出的是此函数所被赋予的内存地址

函数名写法准则

1. 按照函数功能命名(要有描述性)

2. 必须以下划线和字母开头,后面包含任意字母数字下划线(和变量命名一样))

函数的参数

一般函数都是带参数的

def function_name(parameter1,parameter2):
    print(parameter1+parameter2)
function_name('a','b')

输出结果为ab

或者可以用形参=实参的方式

def function_name(parameter1,parameter2):
    print(parameter1+parameter2)
function_name(parameter1='a',paramter2='b')

如果有些参数一般不需要改动,可以设置默认参数,想改的时候再加(注意,默认参数一定要在非默认参数后面)

def function_name(parameter1,parameter2='b'):
    print(parameter1+parameter2)
function_name('a')

输出结果为ab 

如果想给函数加一组不定长的无命名参数,就在参数前面加一个星号*

def function_name(*parameters):
    print(parameters)
function_name(1,2,3,4,5)

输出的是一个元组(1,2,3,4,5)

 如果想给函数加一组不定长的有命名的参数,就在参数前面加两个星号**,猜猜这个参数是什么数据类型?

答:字典!

def function_name(*parameters1,**parameters2):
    print(parameters1,parameters2)
function_name(1,2,3,4,num1=1,num2=2)

输出结果为(1,2,3,4),{'num1':1,'num2':2} 

 注意,对于不定长参数的位置*parameters得放左边,**parameters得放右边

那如果要再加一个默认参数呢?

def a(a='wa',*b,**c):
    print(a,b,c)
a(1,2,3,aa=1,cc=2)

输出结果为

1 (2, 3) {'aa': 1, 'cc': 2}

很明显1作为默认参数a的替代把原来的'wa'给替换掉了

然而默认参数不能放在**的后面,否则报错

总体顺序为

def function(a,b=1,*c,**d)

函数的返回值

返回某个对象给调用者function()

def function():
    return None

如果函数末尾不加return,系统默认添加了return None来结束函数

return作用

1.结束函数

2.返回某个对象

def function(*a):
    Sum=0
    for i in a:
        Sum+=i
    return Sum
print(function(1,2))

输出结果为3 

return也可以返回多个对象,以元组形式给予

作用域

python的作用域分4种情况:

L:local,局部作用域,函数中定义的变量

E:enclosing,嵌套的父级函数的局部作用域,但不是全局的,比如

def outer():
    outer_para=1#enclosing变量
    def inner():
        inner_para=2#local变量

G:global,全局变量,就是模块级别定义的变量,比如a=0,b=1

B:built-in,系统固定模块里面的变量,比如int,sum

LEGB,越往右层越浅,即调用一个变量,先从B找起,再依次GEL

如果上层作用域已经定义了一个变量,下层作用域不能修改这个变量

我们会遇到这个情况

a='global'
def f():
    print(a)
    a='local'
f()

这组代码运行的时候会报错,因为在函数中print(a)这一步已经把a作为全局变量,再把a作为一个局部变量赋值就产生了报错问题,这是因为函数中有对局部变量a的赋值,所以程序默认整个函数内的a都是局部变量,然而print(a)前面没有任何给局部变量a赋值的语句,因此导致报错

但是对于下面代码

a='global'
def f():
    a='local'
    print(a)
f()
print(a)

输出结果为

local

global

因为在函数f中,a一开始就在函数中(仅在函数中)定义为一个局部变量并赋值为‘local’,而外部的全局变量a是不会受影响的。 

所以牢记,全局变量和局部变量重名,局部变量可以调用但只能在函数内部调用且必须先赋值,全局变量不会因为局部变量的赋值而改变

如果想要函数内部的某个变量作为全局变量的赋值,也可以在函数内部给相应变量赋值前添加语句

global a

若要想要嵌套函数子级的某个变量作为父级变量赋值,也可以在函数内部给相应变量赋值前添加语句

nonlocal a

函数的递归

 函数也可以调用自身,这样我们便可以达到递归的效果

例:

编写一个阶乘函数

def fac(n):
    
    return n*fac(n-1)

自己调用自己并赋值进行下一步递归,看起来很不错,但是停不下来,所以我们再给它加一个条件

def fac(n):
    if n==1
        return 1
    return n*fac(n-1)

便得到了一个用于阶乘的函数

关于递归的特性:

1.调用自身函数

2.有一个结束条件

但凡是递归可以实现的,循环也可以

但是递归相对循环来说不过灵活,很容易把事情变麻烦 

内置函数

all()

判断元组,列表内是否有空元素,若有则输出False

bool()

判断一个表达式是False还是True

enumerate()

遍历,详情可看python day5

eval()

把字符串变成代码

frozenset()

不可变集合,就是不能增删改的set 

几种重要的内置函数

filter()

filter(函数,可迭代对象)

序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。

def ff(n):
    return n<3
print(filter(ff,[1,2,3,4,5]))

然而filter是一个迭代器,输出结果为

<filter object at 0x0000022EC66BB128>

这样可以节省内存

可以list()以下把filter的数据转化为list即可

也可以用循环来把内部元素一个一个拿出来

map()

map(函数,可迭代对象),把可迭代对象内元素一个一个置入函数并处理,并把return值返回

def ff(n):
    return n=3
print(map(ff,[1,2,3]))

输出结果为[4,5,6] 

reduce()

reduce(函数,可迭代对象)    用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。

reduce函数需要先调用

from functools import reduce
def ff(x,y):
    return x+y
print(map(ff,[1,2,3]))

 输出结果为6,是通过1+2=3,再3+3=6

lambda

lambda 变量:表达式

lambda是一种比较简单的定义函数的方法

cal=lambda x,y:x+y
print(cal(1,2))

输出结果为3 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值