实验目的

Python中没有指针,但是我们可以探究:
1、分别向Python的类或者函数传递数值,list,类对象三种参数,然后在类和函数内部改变参数,观察原始参数是否会一起发生变化。

实验代码:

  • 给函数或类传递数值参数:
# -*- coding: utf-8 -*-
class A(object):
    def __init__(self, value):
        value = - value
        self.value = value


def func(value):
    value = - value
    return value


if __name__ == '__main__':
    data1 = 100
    a = A(data1)
    print(data1)
    print(a.value)

    print('------------------')
    data2 = 200
    b = func(data2)
    print(data2)
    print(b)
100
-100
------------------
200
-200

对于给函数或类传递数值参数:
给函数传递数值参数,在函数内部改变参数的值,都不会影响原始参数,可以理解为Python在函数内部重新申请了一块内存来保存传递进来的数据,在函数内部对该参数的操作,都是在这块新的内存上进行的,等函数执行完毕之后,Python又释放了这块内存;若想在函数内部改变函数外面的变量,可以考虑使用全局变量。

  • 给函数或类传递list参数
# -*- coding: utf-8 -*-
class A(object):
    def __init__(self, value):
        self.value = value
        self.value.append(300)


def func(value):
    data = value
    data.append(300)
    return data


if __name__ == '__main__':
    data1 = [100]
    a = A(data1)
    print(data1)
    print(a.value)

    print('------------------')
    data2 = [200]
    b = func(data2)
    print(data2)
    print(b)

    print('------改变原始list参数--------')
    data1.append(400)
    print(data1)
    print(a.value)
[100, 300]
[100, 300]
------------------
[200, 300]
[200, 300]
------改变原始list参数--------
[100, 300, 400]
[100, 300, 400]

对于给函数或类传递list参数:
list类型的参数传递的是原始参数的地址,所以在函数内部或者类的内部改变参数,会导致原始参数跟着改变;同理,在类外部改变原始list参数,类内部的list参数也会发生改变。

  • 给函数或类传递类参数
# -*- coding: utf-8 -*-
class B(object):
    def __init__(self, a):
        self.a = a


class A(object):
    def __init__(self, value):
        self.value = value


def func(value):
    data = value
    data.a = 300
    return data


if __name__ == '__main__':
    data1 = B(100)
    obj = A(data1)
    obj.value.a = 200
    print(data1.a)
    print(obj.value.a)

    print('------------------')
    data2 = B(400)
    b = func(data2)
    print(data2.a)
    print(b.a)

    print('------改变原始类参数--------')
    data1.a = 500
    print(data1.a)
    print(obj.value.a)
200
200
------------------
300
300
------改变原始类参数--------
500
500

对于给函数或类传递类对象参数:
类对象类型的参数传递的是原始参数的地址,所以在函数内部或者类的内部改变参数,会导致原始参数跟着改变;同理,类外部改变原始类参数,类内部的类参数也会发生改变。

实验结论:

  • 对于给函数和类传递参数:
    由此可知,数值类型参数传递的是原始参数的值,而list和类对象类型的类参数传递的是原始参数的地址;Python中没有指针,所以向函数和类传递参数到底传的是地址还是值应该和传递的类型有关。
  • 同理,对list和类对象进行复制时,复制的是其地址,而数值类型复制的是数值,这在Python编程时需要特别注意,示例如下:
# -*- coding: utf-8 -*-
class A(object):
    def __init__(self, value):
        self.value = value


if __name__ == '__main__':
    print('----类对象之间赋值------')
    a = A(100)
    b = a
    print(a.value)
    print(b.value)
    a.value = 200
    print(a.value)
    print(b.value)
    b.value = 300
    print(a.value)
    print(b.value)

    print('----list之间赋值------')
    list1 = [1]
    list2 = list1
    print(list1)
    print(list2)
    list1.append(2)
    print(list1)
    print(list2)
    list2.append(3)
    print(list1)
    print(list2)

    print('----数值之间赋值------')
    a = 1
    b = a
    print(a)
    print(b)
    a = 2
    print(a)
    print(b)
    b = 3
    print(a)
    print(b)

	print('----字典之间赋值------')
    a = {'a': 1, 'b': 2}
    b = a
    print(a)
    print(b)

    a['a'] = 3
    print(a)
    print(b)

    b['b'] = 4
    print(a)
    print(b)
"""
----类对象之间赋值------
100
100
200
200
300
300
----list之间赋值------
[1]
[1]
[1, 2]
[1, 2]
[1, 2, 3]
[1, 2, 3]
----数值之间赋值------
1
1
2
1
2
3
----字典之间赋值------
{'a': 1, 'b': 2}
{'a': 1, 'b': 2}
{'a': 3, 'b': 2}
{'a': 3, 'b': 2}
{'a': 3, 'b': 4}
{'a': 3, 'b': 4}
"""

对字典进行直接复制(浅拷贝)时,复制的也是其地址。对于list和字典的拷贝,若是只想拷贝数值,我们可以使用以下方法:

  • list
# list
list1 = [1, 2, 3, 4]
list2 = list1[:]  # 使用切片的方法
  • 字典
    copy方法:
>>> dict1 = {'a': 1, 'b':2, 'c':[1, 2]}
>>> dict2 = dict1.copy()
>>> dict1['a'] = 2
>>> dict2
{'a': 1, 'b': 2, 'c': [1, 2]}

但是还留一个坑,继续往下看:

>>> dict1['c'].append(3)
>>> dict2
{'a': 1, 'b': 2, 'c': [1, 2, 3]}

copy方法对多层的字典的复制表示无能为力,这个地方很容易掉坑。

这种情况,可以使用python自带copy模块,使用dict2 = copy.deepcopy(dict3):

>>> dict1 = {'a': 1, 'b':2, 'c':[1, 2]}
>>> import copy
>>> dict2 = copy.deepcopy(dict1)
>>> dict1['a'] = 2
>>> dict1['c'].append(3)
>>> dict2
{'a': 1, 'b': 2, 'c': [1, 2]}