8.python的基础语法元素_python语法进阶

朱雀 2023-06-23 14:25 83阅读 0赞
  1. #-*- coding: utf-8 -*-
  2. print("===============数据类型的底层实现===============")
  3. #列表的底层实现
  4. #引用数组的概念,列表内的元素可以分散的存储在内存中,列表存储的,实际上是这些元素的地址,这些地址的存储在内存中是连续的
  5. list_1 = [1,[22,33,44],(5,6,7),{"name":"Sarah"}]
  6. #浅拷贝只是将这些地址复制了一份,但是这些地址所指向的内容是相同的
  7. list_2 = list(list_1) #浅拷贝 与list_1.copy()功能一样
  8. #新增元素
  9. list_1.append(100) #对list_1新存储一个地址,指向100
  10. list_2.append("n")#对list_2新存储一个地址,指向n
  11. print (list_1)
  12. print (list_2)
  13. #修改元素 将地址改为已经修改元素的地址
  14. list_1[0] = 10
  15. list_2[0] = 20
  16. print("list_1: ",list_1)
  17. print("list_2: ",list_2)
  18. #对列表型元素进行操作,由于两个地址指向同一个列表行元素的地址,所以列表型元素的内容修改,两个列表内容都会修改
  19. list_1[1].remove(44)
  20. list_2[1] += [55,66]
  21. print("list_1: ",list_1)
  22. print("list_2: ",list_2)
  23. #对元组型元素进行修改,注意元组是不可变的,对元组进行操作,会生成一个新的元组,原来的元组并没有改变
  24. list_2[2] += (8,9)
  25. print ("list _1:",list_1)
  26. print ("list_2: ",list_2)
  27. #对字典进行操作,原理和对列表进行操作一样,两个列表都会改变
  28. list_1[-2]["age"] = 18
  29. print("list_1: ",list_1)
  30. print("list_2: ",list_2)
  31. #引入深拷贝 深拷贝将所有层级的相关元素全部复制,完全分开,泾渭分明,避免了上述问题
  32. import copy
  33. list_1 = [1,[22,33,44],(5,6,7),{"name":"Sarah"}]
  34. list_2 = copy.deepcopy(list_1)
  35. list_1[-1]["age"] = 18
  36. list_2[1].append(55)
  37. print("list_1: ",list_1)
  38. print("list_2: ",list_2)
  39. #神秘的字典 字典的查找操作远远快于列表
  40. #字典通过稀疏数组来实现值的存储和访问
  41. #字典的创建过程 第一步:创建一个散列表(稀疏数组 N >>需要存储的值 n)
  42. #第二步 根据计算的散列值确定其在散列表中的位置 极个别时候散列值会发生冲突,则内部有相应的解决冲突方法
  43. #第三步 在该位置上存入值 访问的同理 而列表是从头开始顺序查找 所以速度比字典慢很多
  44. #字符串的存储通过紧凑数组直接存储元素
  45. #列表遍历需要注意的问题,注意用这种方式无法删除列表中所有的d,因为每一次删除之后,列表都会改变,但是for循环还是按照顺序循环的
  46. #比如删除第一个d之后,新的列表就是["d","d","2","2","d","d","4"],但是for循环记得已经取过0个元素了,所以开始取第一个元素,于是少取了一个d
  47. alist = ["d","d","d","2","2","d","d","4"]
  48. for s in alist:
  49. if s == "d":
  50. alist.remove("d") #删除列表中第一次出现的该元素
  51. print(alist)
  52. #解决办法,使用负向索引,从-8访问到-1,先访问-8,再访问-7,以此类推,可以将所有d都删除掉
  53. alist1 = ["d","d","d","2","2","d","d","4"]
  54. for i in range(-len(alist),0):
  55. if alist[i] == "d":
  56. alist.remove(alist[i])
  57. print(alist)
  58. #多维列表的创建,注意乘以5是浅拷贝
  59. ls = [[0]*10]*5
  60. print (ls)
  61. ls[0][0] = 1
  62. print(ls)
  63. #使用解析语法创建多维列表,在中括号里面,后面是对可迭代对象的遍历,每次取一个元素,执行相应的操作
  64. #这个例子中,是每次取一个元素,就执行一次[0]*10 操作,创建一个[0]*10数组,最终生成一个5*10数组
  65. ls = [[0]*10 for i in range(5)]
  66. print (ls)
  67. ls[0][0] =1
  68. #因为各个数组是独立创建的,所有只修改其中一个
  69. print(ls)
  70. print("===================解析语法=================")
  71. #解析语法的基本结构 以列表解析为例子(也称为列表推导)
  72. #[expression for value in iterable if condition]
  73. #三要数 :表达式,可迭代对象,if条件
  74. #执行过程:从可迭代对象中拿出一个元素,通过if条件(如果有的话),对元素进行筛选,若通过筛选,则把元素传递给表达式,若未通过,则进入下一次迭代
  75. # 将表达式产生的结果作为列表的一个元素,直到迭代对象迭代结束,返回新创建的列表
  76. #等价于如下代码
  77. #result = []
  78. #for value in iterabe:
  79. # if condition:
  80. # result.append(expression)
  81. #例子 求20以内的奇数的平方
  82. squares = []
  83. for i in range(1,21):
  84. if i%2 == 1:
  85. squares.append(i**2)
  86. print(squares)
  87. print ([i**2 for i in range(1,21) if i%2 == 1])
  88. #支持多变量
  89. x = [1,2,3]
  90. y = [1,2,3]
  91. results = [i*j for i,j in zip(x,y)]
  92. print (results)
  93. #支持嵌套循环
  94. colors = ["black","while"]
  95. sizes = ["S","M","L"]
  96. tshirts = ["{} {}".format(color,size) for color in colors for size in sizes]
  97. print (tshirts)
  98. #其它解析语法的例子
  99. #解析语法构造字典(字典推导)
  100. squares = {i:i**2 for i in range(10)}
  101. for k,v in squares.items():
  102. print(k,": ",v)
  103. #解析语法构造集合(集合推导)
  104. squares = {i**2 for i in range(10)}
  105. print(squares)
  106. #生成器推导 可以进行迭代
  107. squares = (i**2 for i in range(10))
  108. for square in squares:
  109. print(square)
  110. #条件表达式 expr1 if condition else expr2 如果条件成立,就执行expr1 ,否则执行expr2
  111. #将n的绝对值赋值给x
  112. n = -10
  113. x = n if n>=0 else -n
  114. print (x)
  115. print("======================三大神器 生成器 迭代器 装饰器====================")
  116. #生成器 如果要计算列表中1到100每个数的平方,采用列表迭代的方式,占用大量内存,此时可以使用生成器
  117. #生成器采用惰性计算,海量数据,不需要存储 一边迭代一边计算 每次只算出当次需要的值,后面的值用到的时候再计算
  118. #生成器实际上一直在执行next()操作,取到下一个值,直到无值可取
  119. #squares = (i**2 for i in range(10000))
  120. #for i in squares
  121. # pass
  122. #采用生成器无需显示存储全部数据,节省内存
  123. print (sum(i for i in range(101)))
  124. #生成器函数 yield
  125. #以生成斐波那契数列为例子 数列的前两个元素为1,1,之后的元素为其前两个元素之和
  126. def fib(max):
  127. ls = []
  128. n,a,b = 0,1,1
  129. while n < max:
  130. #ls.append(a)
  131. print (a) #每次打印输出斐波那契数列就可以了
  132. a,b = b,a+b
  133. n = n+1
  134. return ls
  135. fib(10)
  136. #使用yield,遇到yield语句,会将后面的元素返回,当它执行完返回后,就会停在这里,知道进行下一次next操作,它会从停止的地方继续执行
  137. def fib(max):
  138. n,a,b = 0,1,1
  139. while n < max:
  140. yield a
  141. a,b = b,a+b
  142. n = n +1
  143. fib(10)
  144. for i in fib(10):
  145. print(i)
  146. #迭代器
  147. #可直接用于for循环的对象称为可迭代对象:iterable
  148. #列表 元组 字符串 字典 集合 文件 都是可迭代对象 我们可以使用isinstance()判断一个对象是否是iterable对象
  149. from collections import Iterable
  150. print(isinstance([1,2,3],Iterable))
  151. print(isinstance({"name":"Sarah"},Iterable))
  152. print(isinstance('Python',Iterable))
  153. #生成器也是可迭代对象
  154. squares = (i**2 for i in range(5))
  155. print(isinstance(squares,Iterable))
  156. #生成器不但可以用于for循环,还可以被next()函数调用
  157. #每调用一次next函数,取出一个元素,直到没有数据可取,抛出StopIteration
  158. print(next(squares))
  159. print(next(squares))
  160. #可以被next()函数调用并且不断返回下一个值,直到没有数据可取的对象称为迭代器: Iterator
  161. #可以使用isinstance()判断一个对象是否是iterator对象
  162. #生成器都是迭代器
  163. from collections import Iterator
  164. squares = (i**2 for i in range(5))
  165. print(isinstance(squares,Iterator))
  166. #列表 元组 字符串 字典 集合不是迭代器
  167. print(isinstance([1,2,3],Iterator))
  168. #可通过iter(iterable)创建迭代器
  169. print(isinstance(iter([1,2,3]),Iterator))
  170. #zip enumerate 等 itertools里的函数是迭代器
  171. x = [1,2]
  172. y = ["a","b"]
  173. zip(x,y)
  174. for i in zip(x,y):
  175. print(i)
  176. print(isinstance(zip(x,y),Iterator))
  177. #文件是迭代器
  178. with open("test.txt","r",encoding="utf-8") as f:
  179. print(isinstance(f,Iterator))
  180. #迭代器是可耗尽的
  181. #range()不是迭代器,它不可以被next调用 且无法被耗尽,它是一种懒序列
  182. numbers = range(10)
  183. print(isinstance(numbers,Iterator))
  184. #装饰器
  185. #适用场景 需要对已经开发上线的程序添加某些功能,不能对程序中函数的源代码进行修改,不能改变程序中函数的调用方式
  186. #函数对象 函数是python中的第一类对象 可以把函数赋值给变量 对该变量进行调用 可实现原函数的功能
  187. def square(x):
  188. return x**2
  189. print(type(square)) #square 是function类的一个实例
  190. pow_2 = square #可以理解为给这个函数起了一个别名pow_2
  191. print(pow_2(5))
  192. print(square(5))
  193. #可以将函数作为参数传递
  194. #高阶函数 接收函数作为参数,或者返回一个函数 满足这两个条件之一的函数称之为高阶函数
  195. def square1(x):
  196. return x**2
  197. def pow_2(fun): #高阶函数
  198. return fun
  199. f = pow_2(square1) #将square1这个函数作为参数赋值给pow_2,它的返回值还是square1这个函数
  200. print(f(8))
  201. print(f==square1)
  202. #嵌套函数 在函数的内部定义一个函数,并且调用
  203. def outer():
  204. print("outer is running")
  205. def inner():
  206. print("inner is running")
  207. inner()
  208. outer()
  209. #闭包
  210. #闭包是延伸了作用域的函数,如果一个函数定义在另一个函数作用域内,并且引用了外层函数的变量,则该函数称为闭包
  211. #闭包是由函数及其相关的引用环境组合而成的实体(即 闭包=函数+引用环境),即不但返回内部函数,还返回外部环境的引用
  212. def outer1():
  213. x = 1
  214. z = 10
  215. def inner():
  216. y = x + 100
  217. return y,z
  218. return inner
  219. f = outer1() #f实际上包含了inner函数本身+outer函数的环境
  220. print(f)
  221. res = f()
  222. print(res) #在inner函数中用到了outer函数的变量
  223. #一旦在内层函数重新定义了相同名字的变量,则变量成为局部变量
  224. def outer2():
  225. x = 1
  226. def inner():
  227. #x = x + 100 #这里x定义在内层函数中,默认为局部变量,内层找不到x的值,所以报错
  228. nonlocal x #用nonlocal声明x不是举报变量
  229. x = x + 10
  230. return x
  231. return inner
  232. f = outer2()
  233. f()
  234. #一个简单的装饰器
  235. #嵌套函数的实现
  236. import time
  237. #定义timer装饰器函数
  238. def timer(func):
  239. #定义嵌套函数inner
  240. def inner():
  241. print("inner run")
  242. start = time.time()
  243. #在inner中运行传递过来的函数,并且在前后用两个时间戳获得它运行的时间
  244. func()
  245. end = time.time()
  246. print("{}函数运行用时{:.2f}秒".format(func.__name__,(end-start)))
  247. return inner()
  248. #定义一个f1函数,我们希望它在运行的时候,统计一下用了多长时间
  249. def f1():
  250. print("f1 run")
  251. time.sleep(1)
  252. #将f1函数传递到timer()函数里面去,返回值是inner,此时返回值f1不单单包括inner函数,还包括timer函数的外部环境,包括参数func
  253. f1 = timer(f1)
  254. f1
  255. #语法糖
  256. @timer #相当于实现了f2 = timer(f2)
  257. def f2():
  258. print("f1 run")
  259. time.sleep(1)
  260. f2
  261. #装饰有参函数
  262. def timer1(func):
  263. #定义嵌套函数inner
  264. def inner(*args, **kwargs):
  265. print("inner run")
  266. start = time.time()
  267. #在inner中运行传递过来的函数,并且在前后用两个时间戳获得它运行的时间
  268. func(*args,**kwargs)
  269. end = time.time()
  270. print("{}函数运行用时{:.2f}秒".format(func.__name__,(end-start)))
  271. return inner()
  272. @timer1
  273. def f3(n1,n2):
  274. print("f3 run")
  275. time.sleep(n)
  276. #f3(3) 报错?
  277. #装饰器本身也要传递一些额外的参数 理解闭包是关键
  278. #何时执行装饰器 一装饰就执行 不必等调用
  279. #通过python内部装饰器 @wraps可以将掩饰掉的原函数的属性重新回来

发表评论

表情:
评论列表 (有 0 条评论,83人围观)

还没有评论,来说两句吧...

相关阅读