python_DAY06

一、测试函数也是对象

def test01():
    print('我爱你,你爱我,蜜雪冰城甜蜜蜜')
    pass
test01()
c=test01
c()
print(id(test01))
print(id(c))
print(type(c))

输出结果:
我爱你,你爱我,蜜雪冰城甜蜜蜜
我爱你,你爱我,蜜雪冰城甜蜜蜜
140582443420688
140582443420688
<class 'function'>

二、变量的作用域(全局变量和局部变量)

  • 变量起作用的范围称为变量的作用域,不同作用域内同名变量之间互不影响。变量分为:全局变量、局部变量。
  • 全局变量:
  1. 在函数和类定义之外声明的变量。作用域为定义的模块,从定义位置开始直到模块 结束。
  2. 全局变量降低了函数的通用性和可读性。应尽量避免全局变量的使用。
  3. 全局变量一般做常量使用。
  4. 函数内要改变全局变量的值,使用 global 声明一下
  • 局部变量:
  1. 在函数体中(包含形式参数)声明的变量。
  2. 局部变量的引用比全局变量快,优先考虑使用。
  3. 如果局部变量和全局变量同名,则在函数内隐藏全局变量,只使用同名的局部变量

1. 全局变量作用的测试

a=3
def test01():
    global a # 如果要在函数内改变全局变量的值,增加 global 关键字声明
    print(a) #打印全局变量 a 的值
    a=300
test01()
print(a)

执行结果: 
3
300 

2. 全局变量、局部变量同名测试

a=100 
def f1(): 
	a = 3 #同名的局部变量 
	print(a) 
f1() 
print(a) #a 仍然是 100,没有变化 

执行结果: 
3
100 
  • print(locals()) #打印输出的局部变量
  • print(globals())#打印输出的全局变量

3. 局部变量和全局变量的效率测试

import math
import time
def test01():
    start=time.time()
    for x in range(10000000):
        math.sqrt(30)
        pass
    end=time.time()
    print('所用时间为{0}'.format(end-start))
test01()
def test02():
    start=time.time()
    a=math.sqrt
    for x in range(10000000):
        a(30)
        pass
    end=time.time()
    print('所用时间为{0}'.format(end-start))
test02()

运行结果:
所用时间为0.020941734313964844
所用时间为0.013962745666503906

三、传递对象

1. 传递可变对象

b = [10,20] 
print(id(b))
def f2(m): 
	print("m:",id(m)) #b 和 m 是同一个对象 
	m.append(30) #由于 m 是可变对象,不创建对象拷贝,直接修改这个对象 
f2(b) 
print("b:",id(b)) 
print(b) 

运行结果:
2644773456256
m: 2644773456256
b: 2644773456256
[10, 20, 30]
  • 传递参数是不可变对象(例如:int、float、字符串、元组、布尔值),实际传递的还是对象的引用。在”赋值操作”时,由于不可变对象无法修改,系统会新创建一个对象。

2. 传递不可变对象的引用

a = 100 
def f1(n): 
	 print("n:",id(n)) #传递进来的是 a 对象的地址 
	n = n+200 #由于 a 是不可变对象,因此创建新的对象 n 
	print("n:",id(n))  #n 已经变成了新的对象 
	print(n) 
f1(a) 
print(a). #a还是100
print("a:",id(a)) 

执行结果: 
n: 1663816464 
n: 46608592 
300 
100
a: 1663816464 

三. 浅拷贝(copy)和深拷贝(deepcopy)

  • 浅拷贝:不拷贝子对象的内容,只是拷贝子对象的引用。
  • 深拷贝:会连子对象的内存也全部拷贝一份,对子对象的修改不会影响源对象
import copy
def test01(): #浅拷贝
	a=[1,2,[3,4]]
	b=copy.copy(a)
	print('a:',a)
	print('b:',b)
	b.append(30)
	b[2].append(5) #引用a中的对象了,所以a跟着改变
	print('a:', a)
	print('b:', b)
test01()

运行结果:
a: [1, 2, [3, 4]]
b: [1, 2, [3, 4]]
a: [1, 2, [3, 4, 5]]
b: [1, 2, [3, 4, 5], 30]



import copy
def test01(): #深拷贝
a=[1,2,[3,4]]
b=copy.deepcopy(a)
print('a:',a)
print('b:',b)
b.append(30)
b[2].append(5)
print('a:', a)
print('b:', b)
test01()

运行结果:
a: [1, 2, [3, 4]]
b: [1, 2, [3, 4]]
a: [1, 2, [3, 4]]
b: [1, 2, [3, 4, 5], 30]

四、参数的类型

  • 位置参数:函数调用时,实参默认按位置顺序传递,需要个数和形参匹配。按位置传递的参数,称为: “位置参数”。
  • 默认值参数:我们可以为某些参数设置默认值,这样这些参数在传递时就是可选的。称为“默认值参数”。 默认值参数放到位置参数后面。
  • 命名参数:我们也可以按照形参的名称传递参数,称为“命名参数”,也称“关键字参数”。
#参数类型 位置参数,默认值参数,命名参数
def f(a,b,c):
    print(a,b,c)
f(2,3,4)  #位置参数,三个参数就要对应三个值,多了少了都报错
f(b=10,c=7,a=6)   #命名参数
def f(a,b=2,c=10):
    print(a,b,c)
f(2,3,4)
f(2,3)
f(2)  #默认值参数命名

运行结果:
2 3 4
6 10 7
2 3 4
2 3 10
2 2 10
  • 可变参数:可变参数指的是“可变数量的参数”。分两种情况:
  1. *param(一个星号),将多个参数收集到一个“元组”对象中。
  2. **param(两个星号),将多个参数收集到一个“字典”对象中。
def f1(a,b,*c,**d):
    print(a,b,c,d)
f1(1,2,3,4,565,67,name='zfloss',age=18)

运行结果:
1 2 (3, 4, 565, 67) {'name': 'zfloss', 'age': 18}
  • 强制命名参数
    在带星号的“可变参数”后面增加新的参数,必须在调用的时候“强制命名参数”。
def f2(*a,b,c):
    print(a,b,c,)
f2(1,2,3,4,b=565,c=67)

运行结果:
(1, 2, 3, 4) 565 67
  • lambda表达式和匿名函数
    ambda 表达式的基本语法如下:
      lambda arg1,arg2,arg3… : <表达式>
    arg1/arg2/arg3 为函数的参数。<表达式>相当于函数体。运算结果是:表达式的运算结果。
#测试lambda表达式,匿名函数 
q=lambda a,b,c:a*b*c
def test01(a,b,c):   #二者作用相同
    print('#################')
    return a*b*c
    pass
print(q(2,3,4))
print(test01(2,3,4))
p=[lambda a:a*2,lambda b:b*3,lambda c:c*4]
print(p[0](6),p[1](6),p[2](6))  #中括号中取的是第几个数,小括号是说的乘几
h=[test01,test01] #函数也是对象
print(h[0](2,3,4))

运行结果:
24
#################
24
12 18 24
#################
24
  • eval()函数
    功能:将字符串 str 当成有效的表达式来求值并返回计算结果。
    语法: eval(source[, globals[, locals]]) -> value
    参数:
    source:一个 Python 表达式或函数 compile()返回的代码对象
    globals:可选,必须是 dictionary
    locals:可选,任意映射对象
#eval()函数测试
s ="print('abcde')"
eval(s)  #s是一个python表达式
a=10
b=20
c=(eval('a*b'))
print(c)
test01=dict(a=100,b=200)
d=eval('a*b',test01)
print(d)

运行结果:
abcde
200
{'a': 100, 'b': 200}
20000

五、递归函数

  • 递归函数指的是:自己调用自己的函数,在函数体内部直接或间接的自己调用自己。递归类 似于大家中学数学学习过的“数学归纳法”。
  • 每个递归函数必须包含两个部分:
  1. 终止条件:表示递归什么时候结束。一般用于返回值,不再调用自己。
  2. 递归步骤:把第 n 步的值和第 n-1 步相关联。
  • 递归函数由于会创建大量的函数对象、过量的消耗内存和运算能力。在处理大量数据时,谨 慎使用。
#测试递归函数的基本原理
def test01(n):
    print('n:',n)
    if n==0:
        print('over')
    else:
        test01(n-1)
    print('test**:',n)
test01(4)
#使用递归函数计算阶乘
def test01(n):
    if n==1:
        return 1
    return n*test01(n-1)

for x in range(1,6):
    print('{0}!={1}'.format(x,test01(x)))

运行结果:
1!=1
2!=2
3!=6
4!=24
5!=120
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值