#函数
#函数的定义(定义的过程就是将函数体以字符串的形式存于内存空间中)
TIPS:
#函数的定义要在调用之前
#函数的名字本身的值为存放函数的内存地址,函数名后加()代表运行函数内存空间中存放的字符串
#函数的作用域跟定义的位置有关,跟调用函数的位置无关,且嵌套在函数中的函数不能直接被调用
a = '111'
def test() :
a = '222'
def test1() :
a = '333'
def test2() :
print(a)
return test2
return test1
test()()() --> 333
#分全局变量和局部变量(局部变量小写,全局变量大写)
#函数中没有定义局部变量的话默认寻找上一级的同名变量
a = (11,22,33)
def text() :
a = 3
def textt() :
print(a)
return 0
textt()
text() --> 3
#子程序也就是函数中的 pass 用作占位置(若函数主体为空会报错),不执行任何操作
# 载入time模块 time.sleep(1) 代表延时1秒
import time
print(11)
time.sleep(1)
print(22)
#pycharm里点击左边选择断点,然后右键选择Debug,可以用来一步步执行代码
#函数定义
def sum1(x,y) : --> 也可不传参数或传入多个参数
'this function is used in caculation' --> 注释,可以说明此函数的信息
x = x + y
return x --> 若没有返回值则(返回None)成为过程
(此说明python中没意义,别的程序语言可能就有用)
return 1,2,['adsf',11] 这样返回的是一个元组(1,2,['adsf',11])
#形参和实参
形参 : def sum1(x,y) 里面的 x , y就是形式参数,每次被调用时才有值,调用结束后取消指向的内存空间
实参 : a = 0 之类的参数
#一个参数不能传两次值
#位置参数(必须一一对应)
sum1(1 , 2) -->其中的 1 ,2 就叫位置参数, 跟调用函数的形参一一对应
#关键字参数(无序一一对应,但参数数量得相同)
sum1(x = 1 , y = 2)
#两者混用时位置参数一定要在关键字参数的左边
sum1(1 , y = 2)
#直接定义值
def name(x , y = 'alex') :
#参数组 *列表
def test(x,*args) :
print(args)
return ()
test(1,2,3,4,'dsfds',{'name': 'alex'},*[111,222]) --> (2, 3, 4, 'dsfds',{'name': 'alex'},111,222)
元组形式
#参数组 **字典
def test(x,*args,**kwargs) : -->*args 得在 **kwargs 左边
print(kwargs)
return 0>
test(1,*[1,2,3],name = 'alex' ,b = 3) --> {'name': 'alex', 'b': 3}
或
test(1,*[1,2,3],**{'name': 'alex', 'b': 3})
#在函数中修改全局变量
a =1
def test() :
global a #此声明后下面所有有关变量a的定义全为全局变量 (本质上是一个指针指向了全局变量a的内存地址,如果没有此声明,下面定义的a的内存地址其实不是全局变量的a内存地址,相当于开辟新地址)
a =2 #在定义的global声明之前 ,不许再定义局部变量(因为一个指向局部开辟的新内存,一个指向全局变量的内存,会报错)
return 0
print(a) --> 2
#在函数中修改上一级变量
a = (11,22,33)
def text() :
a = 3
def textt() :
nonlocal a
a = [1,2,3]
return 0
textt()
print(a)
text() --> [1,2,3]
#递归函数(函数中嵌套自己),需要满足以下条件
#必须有一个明确的结束条件
#用递归函数执行循环功能
#每进行更深一层的递归时,问题规模要有所减少
#递归效率不高,递归层次过多会导致内存空间被占满
n = input('输入一个整数\n')
a = 0
def sum1(x) :
global a
a = a + x
if x == 0 :
return a
return (sum1(x-1))
account = sum1(int(n))
print(account) --> n = 100 --> 5050
#匿名函数(lambda)
#没有名字的函数,本身的值为函数地址
#定义
a = lambda x,y,z:(x+y+z,x-y) --> 形参:返回值
print(a(1,2,3)) --> (6,-1)
#主流的编程方法:函数式、面向过程、面向对象
#函数式编程(精简但可读性差)
1、不可变:不用变量保存状态,不修改变量(右为面向过程)
def test(x) : | def test(x :)
return x+1 | res = x + 1
| return res
2、第一类对象,函数即'变量'(函数本身即为内存地址,可以把函数当做一个参数传给另一个函数)
def a(x) :
print(x)
def b(y) :
pass
a(b(123)) --> None
3、高阶函数 --> 满足一下两点之一
#函数接受的参数是函数
#返回值中包含函数
#尾调用优化
#尾调用指函数运行的最后一步(并非是函数的最后一行)为调用另一函数
def text(x) : def text(x) :
return text(x)+1 -->不为尾调用,实际= res = text(x) + 1
return res
#由于函数中调用其他函数,系统会保存原函数的状态在去执行下一个函数,如果嵌套的函数多了,占用内存空间大、效率低。因此在函数式编程的时候,最好进行尾调用优化,即函数运行的最后一步为调用下一个函数,这样就能保证前一个函数完全运行完,在不继续占用内存空间的情况下运行下一个函数。
—————————————三个函数式编程的内置函数—————————————
#map函数
#对列表的每个元素逐一用指定函数处理,返回一个迭代器
a = map(lambda x : (x+1),[9,2,3]) --> map的值a为一个迭代器(只能迭代一次)的地址 print(list(a))
print(a) --> list命令将可迭代对象依次添加成列表 (但在python2中,map的处理结果就是一个列表)
#以上map函数的功能也可以用以下代码实现
add1 = lambda x : (x+1) def test(func,array) : list1 = [] for i in array : list1.append(func(i)) return list1 print(test(add1,[9,2,3]))
#filter函数
#用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
#该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。
#用于筛选出列表中含'alex的元素'
list1 = ['sssf' , 'alex' , " 11 alex's friends "] a = filter(lambda x:x.count('alex'),list1) print(a) print(list(a))
#以上map函数的功能也可以用以下代码实现
list1 = ['sssf' , 'alex' , " 11 alex's friends "] def find_new(x) : return x.count('alex') def filter_new(func,array) : listt = [] for i in array : if func(i) : listt.append(i) return listt print(filter_new(find_new,list1))
#reduce函数 (reduce(function,iterable,initializer))
#对参数序列中元素进行累积 --> 将序列中的1、2个元素交给function处理,处理的结果在跟第3个元素一起交给fuction处理,以此类推
function -- 函数,有两个参数
iterable -- 可迭代对象
initializer -- 可选,初始参数
#python2 中可以直接用 ,python3 中需要导入模块
from functools import reduce
#将列表中的元素相乘,这里的初始参数100代表添加一个100到序列的第一位后处理
from functools import reduce a = [1,2,3,4,5,6] print(reduce(lambda x,y:x*y,a,100))
#此功能也可以表示为以下代码
a = [1,2,3,4,5,6] def multify(x,y) : return x*y def reduce_new(func,array) : res = array.pop() for i in array : res = func(res,i) return res print(reduce_new(multify,a))
——————————————————————————————————
#一些内置函数
abs() -->取绝对值
all(可迭代对象) --> 判断布尔值,所有元素为True则输出True,否则为False,如果可迭代对象为空则也返回True : e.g. all('')
any() --> 用法同all,or逻辑(all为and逻辑)
bin() -->十进制转二进制 注(进制前缀): 0x 十六进制 0b 二进制 0 八进制 0d 十进制
hex() -->十进制转十六进制
oct() -->十进制转八进制
bool() --> 判断布尔值
bytes('你',encoding='utf-8') -->将字符串用指定编码方式编码(e.g. utf-8) \x 代表16进制
b'\xc4\xe3'.decode('gbk') -->用指定编码(不写默认为utf-8)方式解码
chr(97) --> 得到指定ascii码的字符
ord('a') --> 得到字符的ascill码
dir() --> 列出对象中有什么方法
divmod(10,3) --> (3,1) 取商和余数 (可做分页功能)
eval() -->将字符串str转换成有效的表达式(e.g. eval('123') + 1 --> 124)
(e.g. eval('5+3**2') --> 14)
globals() -->以字典形式返回所有全局变量
locals() -->以字典形式返回当前代码块下的局部变量
vars() -->无参数默认以字典形式输出当前代码块下的变量
hash()
#hash() 函数就是对某数据进行一种运算,具有以下特点
#1 可hash的均为不可变数据类型
#2 无法通过hash运算后的结果反推原数据
#3 可用于检测文件的完整型
help()
isinstance('abc',str) -->判断一个数据是否是指定类型(这里是判断'abc'是否为字符串类型)
list(zip([1,2,3],('a','b','c','d'))) --> [(1, 'a'), (2, 'b'), (3, 'c')] 将两个可迭代对象一一对应 放入元组中 (不对应的元素会被舍弃e.g. 'd')
#max()
a = {'a1': 11 , 'a2' : 22 , 'a3' : 1} b = list(zip(a.keys(),a.values())) print(b) -->[('a1', 11), ('a2', 22), ('a3', 1)] print(max(b)) -->('a3', 1)
#迭代a中的每一个元素,用 ' key= '里的函数处理,返回的值比较大小,输出最大的那一个元素
a = [ {'name':'alex' , 'age' : 18} , {'name' : 'lalalal' , 'age' : 1000} ] print(max(a,key=lambda x:x['age']))
min()
pow(2,2, 3) --> 相当于 2**2%3
reversed('abcde') --> 反转一个可迭代对象,返回一个迭代器
round() -->四舍五入
slice() --> 定义一个切片,相当于一个切片变量
s1 = slice(0,3)
s2 = slice(0,3,2) a = 'abcde' print(a[0:3],a[s1],a[s2]) -->abc abc ac
s1.start -->查看切片变量的开始 、结束 、步长
s1.stop
s1.step
sorted() --> 排序(只能同种数据类型比较)
type() --> 查看数据类型(多用于变量类型判断)
import -->导入模块(_import_导入名字是字符串类型的模块名,e.g. 'test')
注: 调用import的过程图 : import -->sys -->_import_()