Python基础系列Python深入学习

python传参和赋值

2019-08-22  本文已影响2人  还请指教

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()

上一篇下一篇

猜你喜欢

热点阅读