python(持续更新中)

Scroll Down

Python:万物皆对象,本质是引用(指针)

python中的赋值 =

从变量与数据角度理解python中变量(名)与数据分离存储,对变量名的调用,例如:a=1 然后print(a)print(a) 实际是先引用数据存储的位置,然后再打印。因此可以简单理解为a和数字1都是对象,1赋值给a则是将地址赋给a。

从对象角度理解,这里的a1 实际上都是对象,执行a=1 本质上是把a 指向1 所在的地址。此时,如果将a赋值为2 ,则a 的地址会重新指向2 所在的地址。例如:

#id()用于获取对象的内存地址
x = 1
print("x   id:",id(x),"\n数值id:",id(1),"x:",x)
print("~~~~~~~~~~~~~~~~~~~~~~~")
x = 2
print("x   id:",id(x),"\n数值id:",id(1),"x:",x)
x *=1 
print("原地操作:",id(x),"\tx:",x)
x +=1 
print("非原地操作:",id(x),"\tx:",x)#对象已经改变,不在是数值2
y = x
x_pre = id(x)
print("y:",y,"\tx:",x)
print("y id:",id(y),"\nx id:",id(x))
print("~~~~~~~~~~~~修改x的值~~~~~~~~~~~")
x = 1
x_after = id(x)
print("y:",y,"\tx:",x)
print("y id:",id(y),"\nx id:",id(x))
print("x之前的id:",x_pre)
print("x重新赋值为1的id:",x_after)
print("x由重新指向了最开始的数值对象:1")
x   id: 140704650404256 
数值id: 140704650404256 x: 1
​~~~~~~~~~~~~~~~~~~~~~~~
x   id: 140704650404288 
数值id: 140704650404256 x: 2
原地操作: 140704650404288 	x: 2
非原地操作: 140704650404320 	x: 3
y: 3 	x: 3
y id: 140704650404320 
x id: 140704650404320
​~~~~~~~~~~~~修改x的值~~~~~~~~~~~
y: 3 	x: 1
y id: 140704650404320 
x id: 140704650404256
x之前的id: 140704650404320
x重新赋值为1的id: 140704650404256
x由重新指向了最开始的数值对象:1
print("~~~~~~~~~~~~列表对象~~~~~~~~~~~")
a = [1,2,3]
pre_a = id(a)
print("a id:",pre_a,"\ta:",a)
a *= 2
after_a = id(a)
print("a id:",after_a,"\ta:",a)
b = a
pre_b = id(b)
print("a id:",id(a),"\nb id:",pre_b)
b *=3
after_b = id(b)
print("a id:",id(a),"\nb id:",pre_b)
print("a:",a,"b:",b)
print(a==b)
print("b[1] id:",id(b[1]))
b[1] = 100
print("b id:",id(b),"after_b id:",after_b)
print("b[1] id:",id(b[1]))
b[1] = 3
print("b[1] id",id(b[1]),"\nb[2] id",id(b[2]))
​~~~~~~~~~~~~列表对象~~~~~~~~~~~
a id: 2340823783240 	a: [1, 2, 3]
a id: 2340823783240 	a: [1, 2, 3, 1, 2, 3]
a id: 2340823783240 
b id: 2340823783240
a id: 2340823783240 
b id: 2340823783240
a: [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3] b: [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
True
b[1] id: 140704650404288
b id: 2340823783240 after_b id: 2340823783240
b[1] id: 140704650407424
b[1] id 140704650404320 
b[2] id 140704650404320

小结:

python中万物皆对象,无论是什么数据类型(数值、字符串、列表等等本质都是对象),只要产生后就会给该对象分配一个内存空间。区别在于这些对象能都修改,例如数值对象1 就不能修改(指直观上通过变量进行+1这样的操作),而列表元素可以修改(对列表元素值进行改变后,列表id不会变换,但是列表元素的id会变),但是列表的每一个元素又是对象。

两句话概括:本质就是无限套娃,直到套到最底层的数据int、char这些为止。变量id是否会随数据的变化而改变,得看数据对象是什么类型。

基本语法:

1.***

1.1* 在传递参数的时候使用,表示将列表元素解开,例如:

x = [1,2,3]
def fn(a,b,c):
    print(a,b,c)
    return a+b+c
fn(*x)
1 2 3
6

1.2* 函数定义时(出现在参数中),表示将传进来的参数转为一个元组,例如:

x = [1,2,3]
def fn(*args):
    print(args)
    return args
fn(*x)
(1, 2, 3)
(1, 2, 3)

1.3** 在传递参数的时候使用,表示将字典元素解开,例如:

x = {
    "a":1,
    "b":2,
    "c":3
}
def fn(a,b,c):
    print(a,b,c)
fn(**x)
1 2 3

1.4** 函数定义时(出现在参数中),表示将传进来的参数转为字典,例如:

def fn(**kwargs):
    for key, value in kwargs.items():
        print("key:",key,",value:",value)
        print(type(key),type(value))
fn(a=1,b=2,c=3,d=4,e=5,f=6)
key: a ,value: 1
<class 'str'> <class 'int'>
key: b ,value: 2
<class 'str'> <class 'int'>
key: c ,value: 3
<class 'str'> <class 'int'>
key: d ,value: 4
<class 'str'> <class 'int'>
key: e ,value: 5
<class 'str'> <class 'int'>
key: f ,value: 6
<class 'str'> <class 'int'>

注意点:

1.定义函数的时候,参数列表中出现有参数给定初始值时,其后边的参数必须给定初始值,否则会报错,例如:
def fn(a,b,c=1,d):#会报错
    print(a,b,c,d)
def fn(a,b,c=1,d=2):#不会报错
    print(a,b,c,d)