文章目录
Python学习
函数也是对象,内存底层分析
python中,一切都是对象,实际上,执行def定义函数后,系统就创建了相应的函数对象。
下面是Demo
# 测试函数也是对象
def test01():
print('sssssss')
test01()
c = test01
c()
print(id(test01))
print(id(c))
变量的作用域(全局变量和局部变量)
变量器作用的范围成为变量的作用域,不同作用域内同名变量之间互相不影响
全局变量:1.在函数和类定义之外生命的变量,作用域为定义的模块,从定义位置开始到模块结束 2.全部变量降低了函数的通用性和可读性,尽量少使用全局变量 3.全部变量一般作为常量使用 4.函数内要改变全部变量的值,使用global声明一下
局部变量:1.在函数体中(包含形式参数)生命的变量 2.局部变量的引用比全部变量快,优先考虑使用 3.如果局部变量和全局变量同名,则在函数内隐藏全局变量,只使用同名局部变量
下面是Demo
#测试全局变量 局部变量
a = 3 #全局变量
def test01():
b = 4 #局部变量
global a #如果要在函数内改变全局变量的值,增加global关键字生命
a = 300
print(b*10)
print(locals()) #打印输出的局部变量
print('#'*22)
print(globals()) #打印输出的全局变量
test01()
print(a)
#效率测试
import math
import time
def tets01():
start = time.time()
for i in range(10000):
math.sqrt(300)
end = time.time()
print('耗时{0}'.format(end-start))
def tets02():
b = math.sqrt
start = time.time()
for i in range(10000):
b(30)
end = time.time()
print('耗时{0}'.format(end - start))
tets02()
tets01()
参数的传递
实参到形参怎么赋值
下面是Demo
#参数的传递,传递可变对象
a = [10,20]
print(id(a))
print(a)
print('----------------------------')
def test01(m):
print(id(m))
m.append(300)
print(id(m))
test01(a)
print(a)
传递不可变对象
传递参数时不可变对象(例如:int ,float,字符串,元组,布尔值),实际传递的还是对象的引用
下面是Demo
a = 100
def f1(n):
print('n',id(n))
n = n + 200
print('n',id(n))
print(n)
f1(a)
print('a',id(a))
浅拷贝和深拷贝
浅拷贝:不拷贝子对象的内容,只是拷贝子对象的引用。copy(浅拷贝)
深拷贝:会连子对象的内存也拷贝一份,对子对象的修改不会影响源对象,deepcopy(深拷贝)
下面是Demo
#测试浅拷贝和深拷贝
import copy
a = [10,20,[5,6]]
b = copy.copy(a)
print('a0',a)
print('b',b)
b.append(30)
b[2].append(7)
print('浅拷贝')
print('a',a)
print('b',b)
def testcopy():
c = [10,20,[5,6]]
d = copy.deepcopy(a)
print('c',c)
print('d',d)
d.append(30)
b[2].append(7)
print('深拷贝')
print('c',c)
print('d',d)
testcopy()
传递不变对象时浅拷贝
下面是Demo
#传递不可变对象时,
# 不可变对象里面包含的子对象是可变的,则方法内修改了这个可变对象,源对象也发生了变化
a = (10,20,[5,6])
print('a',id(a))
def test01(m):
print('m',id(m))
m[2][1]= 20
print(m)
print('m',id(m))
test01(a)
print(a)
参数的类型
位置参数:函数调用时,实参默认按位置顺序传递,需要个数和形参匹配,按位置传递的参数,称为位置参数
默认值参数:我们可以未某些参数设置默认值,这样这些参数在传递时就是可选的,称为默认值参数,默认值参数放到位置参数后面
命名参数:我们也可以按照形参的名称传递参数,称为命名参数,也称为关键字参数
可变参数:可变参数指的是可变数量的参数分两种情况:1.*param(一个星号),将多个参数收集到一个元组对象中 2.**param(两个星号),将多个参数收集到一个字典对象中
强制命名参数:在带星号的可变参数后面增加新的参数,必须在调用时强制命名参数
下面是Demo
#测试参数类型:位置参数,默认值参数,命名参数
def test01(a,b,c,d):
print('{}-{}-{}-{}'.format(a,b,c,d))
def test02(a,b,c=10,d=15):
print('{}-{}-{}-{}'.format(a, b, c, d))
test01(10,20,30,40) #位置参数
# credits(10,20) #参数个数不匹配,报错
test01(a=10,b=20,c=30,d=100) #命名参数,通过形参名称来匹配
test02(2,3)
test02(2,3,4)
#测试可变参数,强制命名参数
def f1(a,b,*c):
print(a,b,c)
f1(8,9,19,20)
def f2(a,b,**c):
print(a,b,c)
f2(8,9,name='gaoqi',age=18)
def f3(a,b,*c,**d):
print(a,b,c,d)
f3(8,9,20,30,name='gaoqi',age=18)
lambda表达式和匿名函数
lambda表达式可以用来声明匿名函数,lambda函数是一种简单的,在同一行中定义函数的方法,lambda函数实际生成了一个函数对象
lambda表达式只允许一个表达式,不能包含复杂豫剧,该表达式的计算结果就是函数的返回值
下面是Demo
#lambda表达式和匿名函数的测试
f = lambda a,b,c,d:a*b*c/d
def test01(a,b,c,d):
return a*b*c/d
# print(f(2, 3, 4, 5))
test01(2,3,4,5)
g = [lambda a:a*3,lambda b:b/2,lambda c:c*6]
print(g[0](6),g[1](25),g[2](9))
h =[test01,test01]
print(h[0](3, 4, 5, 6))
eval函数
功能:将字符串STR当成有效的表达式来求值并返回计算结果
下面是Demo
#测试eval函数
s = "print('abcde')"
eval(s)
a = 10
b = 20
c = eval('a+b')
print(c)
dict1 = dict(a=100,b=200)
d = eval('a+b',dict1)
print(d)
递归函数
递归函数指的是:自己调用自己的函数,在函数体内直接或间接的自己调用自己,递归类似于中学学习过的数学归纳法,每个递归函数必须包含两个部分:1. 终止条件:表示递归什么时候结束,一般用于返回值,不再调用自己 2. 递归步骤:把第N步的值和第N-1步相关联
递归函数由于会创建大量的函数对象,过量的消耗内存和运算能力,在处理大量数据时,谨慎使用
下面是Demo
#测试递归函数的基本原理
def tset01(n):
print('tset01',n)
if n ==0:
print('over')
else:
tset01(n-1)
print('test01****',n)
def tset02():
print('tset02')
tset01(5)
递归函数案例
综合练习。
下面是Demo
#使用递归函数计算阶乘综合练习
def factorial(n):
if n==1:
return 1
else:
return n*factorial(n-1)
result = factorial(5)
print(result)