python学习笔记_第10天(函数)

全局变量和局部变量

全局变量:
  1. 在函数和类定义之外声明的变量。作用域为定义的整个模块,从定义位置开始直到模块结束。
  2. 全局变量会降低函数的通用性和可读性。应尽量避免全局变量的使用。
  3. 全局变量一般做常量使用。
  4. 函数内要改变全局变量的值,需要使用global 声明。
局部变量:
  1. 在函数体中声明的变量(包含形式参数)。
  2. 局部变量的引用比全局变量快,优先考虑使用。
  3. 如果局部变量和全局变量同名,则在函数内就近使用同名的局部变量。
a = 100  # 在函数和类定义之外声明的全局变量,整个模块都能调用

def variable():
    b=2  # 在函数体中声明的变量
    print(a*b) #打印全局变量a 的值

variable()  # 局部变量b,仅调用函数时可使用
print(b)  # 报错,【name 'b' is not defined】
# 全局变量和局部变量同名
a = 100

def variable1():
    a = 3  # 同名局部变量
    print(a)

variable1()  # 3,函数就近使用内部同名局部变量
print(a)  # 100,外部定义的同名全局变量不受影响

def variable2():
	global a  # 使用globl关键字,在函数内部改变全局变量
    print(a)  # 函数内未定义a,调用全局变量a
	a = 300  # 改变全局变量

variable2()  # 100
print(a)  # 300
# 输出当前局部变量和全局变量
a = 100

def variable3(a,b,c):
    print(a,b,c)
    print(locals())  # 打印输出当前函数的局部变量
    print(globals())  # 打印输出整个模块的全局变量

variable3(2, 3, 4)
局部变量和全局变量效率测试

局部变量的查询和访问速度比全局变量快,在特别强调效率或循环次数很多的代码内,优先考虑使用局部变量提高运行速度。

import math
import time

def variable1():
    # math和time都是全局变量
    start = time.time()
    for i in range(10000000):
        math.sqrt(30)
    end = time.time()
    print("variable1,耗时{0}".format((end - start)))

def variable2():
    a = time.time
    b = math.sqrt
    start = a()
    for i in range(10000000):
        b(30)
    end = a()
    print("variable2,耗时{0}".format((end - start)))

variable1()  # variable1,耗时1.7957453727722168
variable2()  # variable2,耗时1.3006963729858398

参数的传递

函数的参数传递本质上就是:从实参到形参的赋值操作。Python中一切皆对象,参数的传递都是“引用传递”,不是“值传递”。具体操作时分为两类:

  1. 对可变对象进行写操作,即直接作用于原对象本身,地址指向不变。可变对象有 – 字典、列表、集合、自定义的对象等。
  2. 对不可变对象进行写操作,则会产生一个新的对象存储新的值,地址指向改变。不可变对象有 – 数字、字符串、元组、function 等
传递可变对象的引用

传递参数是可变对象(列表、字典、自定义的其他可变对象等),实际传递的是对象的引用。在函数体中不创建新的对象拷贝,而是可以直接修改所传递的对象。

a = [10, 20]
print('a指向对象:', id(a))  # 2721719603592
print(a)  # [10, 20]

def function(m):
    print("m指向对象:", id(m))  # a 和 m指向同一个对象
    m.append(30)
    print('对m更改后,m指向对象:', id(m))  # m是可变对象,不创建对象拷贝,直接修改这个对象

function(a)
print("调用函数后,a指向对象:",id(a))
print('调用函数后,a的值',a)  # m直接在原对象更改,调用函数a更改
传递不可变对象的引用

传递参数是不可变对象(int、float、字符串、元组、布尔值),实际传递的还是对象的引用。由于不可变对象无法修改,函数体中会新创建一个对象。

a = 100
print('a的地址', id(a))  # 140722612186608

def function1(n):
    print("n:", id(n))  # 140722612186608,传递进来不可变对象,与a指向相同地址
    n = n + 200  # int为不可变对象,创建新的对象,n指向新创建的地址
    print("n:", id(n))  # 218633954832,n已指向新的对象,与a指向不同对象
    print(n)  # 300

function1(a)  
print('a的地址:', id(a))  # 140722612186608,调用函数a不改变
传递不可变对象包含的子对象是可变
a = (10, 20, [5, 6])
print("a:", id(a))  # 2572238684312

def function2(m):
    print("m:", id(m))  # 2572238684312
    m[2][1] = 666 
    print(m)  # (10, 20, [5, 666])
    print("m:", id(m))  # 2572238684312

function2(a)
print(a)  # (10, 20, [5, 666])

元组对象不可变,但元组内子对象有可变对象列表m[2][0]。可变子对象任然可变,但元组的地址指向不变。
在这里插入图片描述

浅拷贝和深拷贝

用内置函数:copy(浅拷贝)、deepcopy(深拷贝)
浅拷贝 – 不拷贝子对象的内容,只是拷贝子对象的引用。
深拷贝 – 会连子对象的内存也全部拷贝一份,对子对象的修改不会影响源对象

import copy

def Copy():
    '''测试浅拷贝'''
    a = [10, 20, [5, 6]]
    b = copy.copy(a)
    print("a", a)
    print("b", b)
    b.append(30)
    b[2].append(7)
    print("浅拷贝......")
    print("a", a)
    print("b", b)

def DeepCopy():
    '''测试深拷贝'''
    a = [10, 20, [5, 6]]
    b = copy.deepcopy(a)
    print("a", a)
    print("b", b)
    b.append(30)
    b[2].append(7)
    print("深拷贝......")
    print("a", a)
    print("b", b)

Copy()
print("*************")
DeepCopy()

浅拷贝内存示意图:
在这里插入图片描述

深拷贝内存示意图:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值