「码动四季·开源同行」python语言:合并表达
一、三元表达式在学习三元表达式之前我们如需比较两个值的最大值。def max2(x, y): if xY : return x else: return y res max2(10, 11) print(res)三元表达式的使用x 12 y 11 # 三元分别指的是if左边else右边和if条件语句 res x if x y else y # 注意不要有逗号或者冒号 print(res)三元表达式仅应用于条件成立返回一个值条件不成立返回一个值。def max2(x, y): return x if x y else y print(max2(10, 11))二、函数递归调用1.函数递归调用说明函数的递归调用指的是在函数调用的过程中又直接或间接地调用了函数本身是函数嵌套调用的一种特殊形式。#直接调用 def foo(): print(from foo) foo() foo() #间接调用 def bar(): print(from bar) fool() def fool(): print(from foo) bar() fool()以上这两种递归会让程序陷入死循环中为了避免程序占用大量的内存而是机器卡死Python中有一个最大递归深度所以你看到的报错其实是为了保护你的机器。import sys print(sys.getrecursionlimit()) #默认最大递归深度1000 sys.setrecursionlimit(10000) # 可以修改成10000甚至1亿但是受限于机器硬件性能限制 print(sys.getrecursionlimit())2.递归阶段性说明递归分为两个阶段1.回溯2.递推注意一定要在满足某种条件结束回溯否则的无限递归假如有这样一个小学数学题目老师询问五位学生的年龄第一位学生说他比第二位学生大两岁这时老师就要问第二个位学生第二位学生说他比第三位学生大两岁问三三说比四大两岁问四四说比五大两岁问五五说“18岁”。求这五位学生分别多少岁老师依次询问的过程就是回溯老师根据第五位学生的年龄推导出其他四位学生的年龄的过程就是递推可用如下图表示。把以上问题整理成数学表达式并使用递归来完成。def get_age(n): if n 1: return 18 return get_age(n - l) 2 # age(4)2 # 可以写成以下三元表达式形式貌似高端但是会让程序看起来不够简洁 # return 18 if n l else age(n - l) 2 print(get_age(5))正确使用递归1.递归一定要有一个明确地结束条件2.进入下一次递归之前问题的规模都应该减小3.在Python中没有尾递归优化3.递归的应用递归也有循环的效果与while循环不同的是while循环一定要有一个明确的循环的条件而递归不需要在有些场景下使用递归能够让程序设计更简洁。#要求取出列表中的123456...... items [1, [2, [3, [4, [5, [6, [7, [8, [9, [10, ]]]]]]] def tell(l): for item in l: if type(item) is not list: print(item) else: tell(item) tell(items)三、匿名函数1.匿名函数介绍匿名函数就是没有名字的函数我们以前讲过的函数都是要有一个函数名字的。#有名函数 def func() #函数名为func可以多次调用 print(from func) func() func() func() # 如果需要输出一个数的n次幂 # 使用有名函数 def foo(x, n) # foo对应函数的内存地址 return x ** n # 使用匿名函数 匿名函数使用规则 冒号左边为参数 冒号右边为返回值 不需要写return f lambda x, nx ** n # 我们强行给匿名函数赋值一个变量是为了帮助你理解 print(f) print(f(2, 3)) print(f(2, 4))2.匿名函数使用规则1.匿名的目的就是要没有名字给匿名函数赋给一个名字是没有意义的2.匿名函数的参数规则、作用域关系与有名函数是一样的3.匿名函数的函数体通常应该是一个表达式该表达式必须要有一个返回值如果一个匿名函数的函数体没有返回值那么这是没有意义的。#没有意义 f lambda x, n: print() # print肯定是没有返回值的 print(f(2, 3)) #有意义 f1 lambda x, y, z: x y z print(f1(l, 2, 3))3.匿名函数的应用(1) max min sorted匿名函数一般不会单独使用常与我们接下来讲的内置函数联用。print(max([3, 2, 5, 44, 66, 11, 13, ])) print(min([3, 2, 5, 44, 66, 11, 13, ])) print(sorted([3, 2, 5, 44, 66, 11, 13, ])) # 升序 print(sorted([3, 2, 5, 44, 66, 11, 13, ], reverseTrue)) #降序(2)匿名函数与maXminsorted联用作者 求工资最高的那个人是谁 求工资最低的那个人是谁 把这些人按薪资待遇排序 salaries { james 300000, kd: 100000, zimuge 10000, harden 90000 } print(max(salaries)) print(min(salaries)) print(sorted(salaries))显然这个结果是不对的maxmin和sorted它们的原理其实都是for循环我们比较的依据是薪资而for循环字典默认比较的字典的key所以你看到的结果是按照自己字符串的大小(字符编码表的顺序)比较的。 求工资最高的那个人是谁 求工资最低的那个人是谁 把这些人按薪资待遇排序 salaries { james 30000000, kd 10000000, zimuge: 1000000, harden9000000 } def get(k): return salaries[k] #max可以指定key代表比较依据与字典的键重名纯属巧合 print(max(salaries, keyget)) #这里需要传一个£or循环迭代而来的参数并输入一个结果 #max比较原理 for k in salaries: print(k) #告诉max比较的依据是salaries[k] #显然我们定义一个get函数是不需要的这时可以使用匿名函数 print(max(salaries, keylambda x: salaries[x])) #求工资最低的那个人是谁 print(min(salaries, keylambda x: salaries[x])) #把这些人按薪资待遇排序 salariesl sorted(salaries, keylambda x: salaries[x]) #升序 print(salaries1) salaries2 sorted(salaries, keylambda x: salaries[x], reverseTrue) #降序 print(salaries2)(3)匿名函数与mapreducefilter联用mapreduce和filter最好与匿名函数联用才能发挥作用所以我们不再单独介绍。# 1 map #数字映射 nums [1, 2, 3, 4, 5] #map第一个参数是函数即映射方式第二个参数是可以迭代对象 res map(lambda x: x ** 2, nums) #在Python2中res是一个列表Python3中是一个迭代器 print(res) #list用for循环的原理把迭代器转化成列表 print(list(res)) #字符串映射 names [James, Harden, Curry] res map(lambda x: x is super star, names) print(list(res)) names [James, Harden, Curry, Albert] res map(lambda x x is referee if x Albert else x is super star, names) print(list(res)) # 2 reduce reduce在Python2中还是一个内置函数 在Python3中需要导入一下下一章节就会讲解模块与包的导入 from functools import reduce #这样代码是导入reduce #数字合并 reduce可以传三个参数 第一个是必传项指的合并规则即函数 第二个是必传项指的可迭代对象 第三个是可选项指的初始值 #计算123100 res1 reduce(lambda x, y: x y, range(1, 101), 0) #初始值给x可迭代对象内的值给y相加之后再作为初始值给x可迭代对象内新的值给y print(res1) res reduce(lambda x, y: x y, range(1, 101)) #不指定初始值则由可迭代对象的第一个值作为初始值 print(res) #字符串合并 list1 [Today, is, the, first, day, of, the, rest, of, your, life] res reduce(lambda x, y: x y , list1) print(res) # 3 filter # 过滤出年龄不小于30的 ages [18, 19, 10, 23, 99, 30] # res filter (lambda n: True if n 3o else False ages) #filter只能过滤真假上面写写法有点啰嗦 res filter(lambda n: n 30, ages) print(list(res)) #过滤出裁判 names James is super star, Harden is super star, Albert is referee] res filter(lambda x: x.endswith(referee), names) print(list(res))四、内置函数1.format用法1format三种基本用法res {} {} {}.format(Albert, 18, male) #相当于₆s其占位符的作用 print(res) res {l} {0} {1}.format(Albert, 18, male) #按照索引对应值与索引序列相关 print(res) res {name} {age} {sex}.format(sex male, nameAlbert, age18) #按照关键字对应值只与key对应 print(res) # Albert18 male # 18 Albert 18 # Albert 18 male(2format与%s用法异同1相同点formate与%都可以用作对象属性格式化两者都是用作字符串中的占位符一般基础阶段的程序员只会用%而且不管多麻烦你都会想到用%的办法我首先为你的执着点个赞但是我要说的是简单的可以用%复杂一些我还是推荐使用formate或者说是{}。class Person(object): def __init__(self, name, age): self.name name self.age age def __str__(self): return This guy is %s, %s years old. % (self.name, self.age) p1 Person(albert, 18) print(p1) class Person(object): def __init__(self, name, age): self.name name self.age age def __str__(self): return This guy is {self.name}, {self.age} years old..format(selfself) p1 Person(albert, 18) print(p1)2不同点[1]占位形态# 定义一个坐标值 c (250, 250) # 使用%来格式化 s1 敌人坐标%s % c print(s1) 报错说明 not all arguments converted during string formatting 翻译在执行字符串格式化期间不是所有的字符串都能被转化 其实道理很简单因为执行字符串转化的时候程序以为变量c是一个字符串才去进行转化的然而一转化才发现 老兄你坑我啊你这个字符串我怎么看不明白啊用。去执行这个程序的时候默认以为c是一个字符串 从始至终程序都是为c是一个字符串其实它不是所以才会有这样的报错 #定义一个坐标值 c (250, 250) #使用format来格式化 s1 敌人坐标{}.format(c) print(s1) 区别: format本意就是变形的意思72变需要什么我就变什么 %是一个基本的占位符只能给字符串哦怕程序不理解是真正的字符串占位 [2]f-strings这里的新特性f-strings其实和format没有直接关联只是使用的format的特性来进行格式化这个新特性只在Python3.6 才有以后有没有只有龟叔知道了。name Albert print(fhe said his name is {name}) #注意字符串前面的f[3]填充与对齐填充常跟对齐一起使用^、、分别是居中、左对齐、右对齐后面带宽度冒号后面带填充的字符只能是一个字符不指定的话默认是用空格填充。print({:10}.format(18)) print({:310}.format(18)) #print({aa10}.format(18)) #写两个字符就会报错错误就是让写一个你偏要写俩老子看球不懂 print({:*^10}.format(18))补充一个字符串自带的zfilIO)方法PythonzfilI方法返回指定长度的字符串原字符串右对齐前面填充0。zfilI()方法语法str.zfilI(width)参数width指定字符串的长度。原字符串右对齐前面填充0返回指定长度的字符串。print(a.zfill(10))[4]float精度调整print({.5f}.format(3.14159265753)) #进度通常和float类型一起使用 其中.5表示长度为5的精度 #3.14159[5]千位分隔符print({:,}.format(1234567890)) #1,234,567,8901[6]进制转换b、d、o、x分別是二进制、十进制、八进制、十六进制print({:b}.format(18)) print({:d}.format(18)) print({:o}.format(18)) print({:x}.format(18))2.其他内置函数#1取绝对值 print(abs(-l)) #绝对值 #2 逻辑判断 print(all([1, a, True])) #列表中所有元素的布尔值为真最终结果才为真 print(any([0, a, None, False])) #列表中所有元素的布尔值只要有一个为真最终结果就为真 print(any([])) #传给any的可迭代对象如果为空最终结果为假 #3进制转换 print(bin(11)) #十进制转二进制 print(oct(11)) #十进制转八进制 print(hex(11)) #十进制转十六进制 #4布尔值判断 print(bool(0)) #0None空的布尔值为假 #5 bytes类型构造 #res你好albert.encode(utf-8) #unicode按照utf-8进行编码得到的结果为bytes类型 res bytes(你好albert, encodingutf-) # 同上 print(res) #6对象是否可调用 def func(): pass print(callable(func)) #判断某个对象是否是可以调用的可调用指的是可以加括号执行某个功能print(callable(abc·strip)) #判断某个对象是否是可以调用的可调用指的是可以加括号执行某个功能 print(callable(max)) #判断某个对象是否是可以调用的可调用指的是可以加括号执行某个功能 #7字符与十进制转换 print(chr(90)) #按照ascii码表将十进制数字转成字符 print(ord(z)) #按照ascii码表将字符转成十进制数字 #8查看对象下可调用的方法 print(dir(abc)) #查看某个对象下可以调用到哪些方法 #9去商和余数返回元组 print(divmod(1311, 25)) #10将字符内的表达式拿出运行一下并拿到该表达式的执行结果 res1 eval(2*3) print(resl, type(resl)) res2 eval([1,2,3,4]) print(res2, type(res2)) res3 eval({ name:Albert,age:18}) print(res3, type(res3)) #11集合添加 s {1, 2, 3} s.add(4) #集合添加一个元素 print(s) #12 不可变集合 f_set frozenset({l, 2, 3}) #不可变集合 #13名字与值的绑定关系 x 2 print(globals()) #查看全局作用域中的名字与值的绑定关系 print(dir(globals()[__builtins__])) def func(): x 1 print(locals()) #查看局部作用域中的名字与值的绑定关系 func() #14哈希 print(hash(a)) print(hash((1, 2, 3, 4))) # dict1 {[1, 2, 3]: a} #报错字典的key必须是不可变类型 #不可hash的类型listdictset 可变的类型 #可hash的类型intfloatstrtuple 不可变的类型 #15查看文档注释 def func(): 帮助信息 :return: pass print(help(max)) #查看文档注释 print(help(func)) #•l6 lennextiter等自动执行的方法 #__开头__结尾的方法都是在某种情况下自动触发执行通常我们不需要自己写 print(len({x: 1, y: 2})) #触发{x:1y:2}.__len__() print({x: 1, y: 2}.__len__()) #与上面等同 obj iter(Albert) #Albert.__iter__() print(next(obj)) #obj.__next__() # 17 2**3 % 3 print(pow(2, 3, 3)) # 2 ** 3 % 3 #18反转顺序 1 [1, 4, 3, 5] res reversed(l) print(list(res)) print(l) #19四舍五入 print(round(3.5)) print(round(3.4)) #20切片对象 sc slice(1, 5, 2) # 1:52 1 [a, b, c, d, e, f] # print(l[1:5:2]) print(l[sc]) t (1, 2, 3, 4, 5, 6, 7, 8) # print(t[1:5:2]) print(t[sc]) #21求和 print(sum([1, 2, 3, 4])) #22 拉链函数 left hello right1 {x: 1, y2, z3} right2 [1, 2, 3, 4, 5] res1 zip (left, rightl) res2 zip(left, right2) print(list(resl)) print(list(res2))五、列表生成式1.列表生成式基本使用列表生成式就是生成列表的表达式使用通常的理解是为了使我们的程序设计变得更加简洁。#要求造出来1000个蛋 1 [] for i in range(1000): l.append(eggos % i) #使用列表生成式 l1 [egg%s % i for i in range(1000)] l2 [egg%s % i for i in range(1000) if i 10] #可以有if条件注意和三元表达式的区别 print(l1) print(l2) #列表生成式语法格式 [ expression for item1 in iterable1 if condition1 for item2 in iterable2 if condition2 ... for itemN in iterableN if conditionN ] 2.使用注意事项使用列表生成式可以有多个for循环和多个if条件但是一般情况下我们只写一组就像上面代码中写的如果你在列表生成式中写了多个for循环和if条件就丧失了程序设计的简洁性这并不符合Python的语法风格。3.列表生成式提升效率从底层上讲列表生成式是在构建列表的过程中在列表中放入多个元素而我们前面普通的方式是先创建一个空列表再逐一添加元素很明显这种普通的方式会徒增插入的时间这个时间虽然并不是很多但是当数据量足够大的时候会有明显的差距。 因为我们要造的数据内容是一样的为了避免你多余的顾虑后面的代码覆盖前面的数据这其实不存在因而后面的可能会快一些这种错误的想法我们把列表生成式放到前面 import time #使用列表生成式 time1 time.time() l1 [egg%s % i for i in range(1000000)] time2 time.time() print(time2 - time1) # 使用普通方式 time3 time.time() 1 [] for i in range(1000000): l.append(egg%s % i) time4 time.time() print(time4 - time1)你可以清楚的看到使用列表生成式的执行效率明显高于普通的方式所以在合适的场景下使用列表生成式是一个不错的选择既能简化代码又能提高效率但是比如有些情况你需要优化程序而所有的优化手段都用上了还不够再优化的话就是使用比较复杂的列表生成式了这也未尝不可具体还要自己权衡。我需要告诉你的是1.如果真的要用复杂的列表生成式前提一定是你已经使用了所有的其他优化方式还不能到达预期因为列表生成式提升效率并不是按照数量级来提升的。2.提升硬件性能的优化远比从软件上深层优化容易得多提升硬件性能的花费一定会比工程师时间上的花作者费所兑换的金钱要少。六、生成器表达式列表生成式会构造出一个列表如果数据量非常大那么会构造出一个非常大的列表占用大量的内存机器就卡了建议你自己试一下以后就会深有体会(你正常使用的卡顿与机器真的卡了差别很大)卡机代码如下l1 [egg%s % i for i in range(100000000000000000000000000000000000000000)]所以我们有了生成器表达式返回的值是一个生成器可以迭代取值。#只需要把中括号改成小括号就可以了其他用法一样 l (egg%s % i for i in range(l00000000000000000000000000) if i 100000) print(next(l)) print(next(l)) print(next(l))
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2545699.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!