python传参和赋值

℡╲_俬逩灬. 提交于 2020-01-16 16:46:50

python的赋值

Assignment statements are used to (re)bind names to values and to modify attributes or items of mutable objects ------官方文档

赋值语句用于(重新)将名称绑定到值,并修改可变对象的属性或项

python中一切皆对象,数字是对象,列表是对象,函数是对象

简单理解,python的变量可以看作一个简简单单的“标签”,除了变量名没有任何意义,直到它被一个有意义的实体(对象)所赋值,赋值的过程其实就是一个变量绑定对象的过程,可以看作是给对象贴了个标签(这个比喻相对严谨)

赋值过程

无论是可变类型(如list)的对象或是不可变类型(如int)的对象, 给变量赋值的过程都意味着绑定或重新绑定

绑定过程不是只有一次,绑定过对象的变量仍可以重新绑定其它对象(包括其它类型的对象),没有被变量绑定的对象将可能被垃圾回收

赋值int

绑定整数对象池中的一个整形对象

a = 1
b = a
c = 1
d = 2
print("a",id(a))
print("b",id(b))
print("c",id(c))
print("d",id(d))

1是一个对象,在整数对象池中是固定的(即一个特定的内存位置存储着1),如上一三两行实现了ac均绑定了整数对象1,第二行意为将a绑定的对象也绑到b上,如此,abc均绑定了对象1,所以显示相同的地址

小整数对象池和大整数对象池

整数在程序中的使用非常广泛,Python为了优化速度,使用了小整数对象池, 避免为整数频繁申请和销毁内存空间。

Python 对小整数的定义是 [-5, 256] 这些整数对象是提前建立好的,不会被垃圾回收。在一个 Python 的程序中,无论这个整数处于LEGB中的哪个位置,所有位于这个范围内的整数使用的都是同一个对象。同理,单个字母也是这样的。

大整数对象池。说明:终端是每次执行一次,所以每次的大整数都重新创建,而在pycharm中,每次运行是所有代码都加载都内存中,属于一个整体,所以这个时候会有一个大整数对象池,即处于一个代码块的大整数是同一个对象。

------引自:python中小整数对象池和大整数对象池

is是判断是否是同一个对象的操作符,返回值是布尔型;类似于:两个人是一个人等价于两个人的身份证号码相同(如果都有身份证),两个变量绑定了相同的对象 <==> id(变量1) == id(变量2)

赋值list

绑定一个list对象给变量

# 1
a = []
b = []
print("a is b?",a is b)
#2
goo = [1,2,3]
gll = [1,2,3]
gtt = [1,2,3,4]
print(id(goo),id(gll),id(gtt))
#3
c = b
print("c is b?",c is b)
#4
c.append(1)
print("c:",c)
print("b:",b)

#1 和 #2展示了:对于构造一个可变类型的对象并绑定给变量,无论当前是否有和其暂态相同的对象,都会创建新的对象,而不使用旧的对象。因为它是可变类型,有无限的可能(增删改),暂态相同并不代表永远相同,所以是否相同是不确定的事情,而python或是说程序永远不会去做不确定的事儿。这是与不可变对象的区别。

#3 是将b绑定的对象给c绑定上,即bc绑定了同一个对象,那么对c的操作必定会影响对b的操作

#4 是对c进行了操作,进而影响了b, 因为对c的append()追加元素操作,实际上是bc共同绑定的对象的追加变更,很多人称python可变对象的这个特点跟C++的引用一样,其实是不准确和错误的。学python的确可以借鉴C++,但不应照单全收,因为两者的机制有非常大的区别。

高级赋值操作

批量赋值

a,b,c = 1,2,3
print(a)
print(b)
print(c)

拆包与装包

# 装包:按位置将变量赋值后多余的装列表里
a,b,*c,d = 1,2,3,4,5,6
print(a,b,c,d)
# 拆包:打开列表取出值
print(*c)

python传参

python的传参过程与赋值过程类似(更像是实参给形参批量赋值),实质也是对象的绑定

C++有传值,传引用,python的参数传递是?就叫他 传对象 吧!

传不可变对象

def give_me_a_num(a):
    a = a+1
    print("give_me_a_num's a:",a)

def main():
    a = 1
    print("main's origin a:",a)
    give_me_a_num(a)
    print("main's a:",a)
    
main()

a在main里是绑定的整数1,传过去给give_a_num的a, 说你也绑定这个对象吧,于是give_me_a_num里的a的值是1,

接着give_me_a_num里发生了状况,里面的a不喜欢1这个对象了,舍弃,重新绑定了对象a+1,也就是2,

而main里的a一直对1不离不弃,所以这个a一直是1

这样一气呵成,并没什么不妥;但很多人看了这个以后断定:python的参数传递和C++的值传递一样

传可变对象

def give_me_a_girl(girl):
    girl["lover"] = "Mike"
    print("give_me_a_girl's girl:\n\t",girl)

def main():
    girl = {"name":"Mark","age":20,"lover":"Tim"}
    print("main's origin girl:\n\t",girl)
    give_me_a_girl(girl)
    print("main's girl:\n\t",girl)
    print("\nTim:\"Mark,you changed!You don't love me anymore.\"")
main()

这里girl是一个字典,是一个可变对象,main里面的变量girl绑定了这个对象,传给了give_me_a_girl里的girl,它也绑定了这个对象,并且对所绑定的对象做了相应的修改,因为main和give_me_a_gril里的girl绑定的是同一个对象,所以main's girl也是改变了的,本质是其绑定的对象发生了改变。

这是python传可变对象的实质,如果give_me_a_girl里面的girl重新绑定了新的对象,再做变化,就不会再影响到main's girl了;但是很多人看了这种实例,就断言:python传参方式和C++里的引用传递一样

默认值参数

def make_cake(cream,butter = 0,fruit = 3):
    print("做了蛋糕")
    print("奶油{}斤,黄油{}两,水果{}块".format(cream,butter,fruit))
make_cake(1,3)
make_cake(1,2,4)
make_cake(4)
make_cake(2,fruit = 8) #python比较高级的地方

make_cake()的使用比较方便,有两个默认参数,传参时第一个实参不可省,确认是给cream的,剩下两个可以按顺序给或不给(默认),使用key=value的方式可以打破顺序

拆包装包实现可变参数的函数

def get(git_id,*args,**kwargs): #git_id要写前面,否则贪婪匹配,不会给它剩
    print("装包后:")
    print("git_id:",git_id)
    print("args:",args)
    print("kwargs:",kwargs)
    print("对传过来的参数拆包:".format())
    print("*args:",*args)
    print("kwargs拆包后传给fun:",end="")
    fun(**kwargs) #相当于fun(a=1,b=2)
    
def fun(b,a): #注意键名和参数名对应
    print(a,b)

get(1,2,3,4,5,6,a=1,b=2) #调用时前面第一个之后装包给元组,剩下给字典

*args作为形参时是用来接收多余的未命名参数,而**kwargs是用来接收key=value这种类型的命名参数,args是元组,kwargs是字典。

拆装包实现对象的拷贝

# 方便的使用方法
def rich(*money):
    print("今天赚了{}元钱".format(sum(money)))
    
rich(2,3,4,5)

def rich(*money):
    print(id(money))
    print("今天赚了{}元钱".format(sum(money)))
    
def main():
    today_come = [1,2,3,4,5,6]
    print(id(today_come))
    rich(*today_come)
    
main()

可以看到rich()‘s money和 main()’s today_come 的id不一样,也就是两者没有绑定一样的对象了,因为拆包后会装到一个新的包里,这样互相就不影响了

想到这里,,,

def give_me_a_girl(**girl):
    girl["lover"] = "Mike"
    print("give_me_a_girl's socalled girl:\n\t",girl)

def main():
    girl = {"name":"Mark","age":20,"lover":"Tim"}
    print("Tim's origin girl:\n\t",girl)
    give_me_a_girl(**girl)
    print("Tim's normal girl:\n\t",girl)
    print("\nTim: \"I love you,Mark!\"")

main()

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!