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

#-*- coding: utf-8 -*-

print("===============数据类型的底层实现===============")
#列表的底层实现
#引用数组的概念,列表内的元素可以分散的存储在内存中,列表存储的,实际上是这些元素的地址,这些地址的存储在内存中是连续的
list_1 = [1,[22,33,44],(5,6,7),{"name":"Sarah"}]
#浅拷贝只是将这些地址复制了一份,但是这些地址所指向的内容是相同的
list_2 = list(list_1) #浅拷贝 与list_1.copy()功能一样

#新增元素
list_1.append(100) #对list_1新存储一个地址,指向100
list_2.append("n")#对list_2新存储一个地址,指向n
print (list_1)
print (list_2)

#修改元素 将地址改为已经修改元素的地址
list_1[0] = 10
list_2[0] = 20
print("list_1: ",list_1)
print("list_2: ",list_2)
#对列表型元素进行操作,由于两个地址指向同一个列表行元素的地址,所以列表型元素的内容修改,两个列表内容都会修改
list_1[1].remove(44)
list_2[1] += [55,66]
print("list_1: ",list_1)
print("list_2: ",list_2)
#对元组型元素进行修改,注意元组是不可变的,对元组进行操作,会生成一个新的元组,原来的元组并没有改变
list_2[2] += (8,9)
print ("list _1:",list_1)
print ("list_2: ",list_2)
#对字典进行操作,原理和对列表进行操作一样,两个列表都会改变
list_1[-2]["age"] = 18
print("list_1: ",list_1)
print("list_2: ",list_2)

#引入深拷贝 深拷贝将所有层级的相关元素全部复制,完全分开,泾渭分明,避免了上述问题
import copy
list_1 = [1,[22,33,44],(5,6,7),{"name":"Sarah"}]
list_2 = copy.deepcopy(list_1)

list_1[-1]["age"] = 18
list_2[1].append(55)

print("list_1: ",list_1)
print("list_2: ",list_2)


#神秘的字典 字典的查找操作远远快于列表
#字典通过稀疏数组来实现值的存储和访问
#字典的创建过程 第一步:创建一个散列表(稀疏数组 N >>需要存储的值 n)
#第二步  根据计算的散列值确定其在散列表中的位置 极个别时候散列值会发生冲突,则内部有相应的解决冲突方法
#第三步 在该位置上存入值 访问的同理 而列表是从头开始顺序查找 所以速度比字典慢很多

#字符串的存储通过紧凑数组直接存储元素
#列表遍历需要注意的问题,注意用这种方式无法删除列表中所有的d,因为每一次删除之后,列表都会改变,但是for循环还是按照顺序循环的
#比如删除第一个d之后,新的列表就是["d","d","2","2","d","d","4"],但是for循环记得已经取过0个元素了,所以开始取第一个元素,于是少取了一个d
alist = ["d","d","d","2","2","d","d","4"]
for s in alist:
    if s == "d":
        alist.remove("d") #删除列表中第一次出现的该元素
print(alist)
#解决办法,使用负向索引,从-8访问到-1,先访问-8,再访问-7,以此类推,可以将所有d都删除掉
alist1 = ["d","d","d","2","2","d","d","4"]
for i in range(-len(alist),0):
    if alist[i] == "d":
        alist.remove(alist[i])
print(alist)
#多维列表的创建,注意乘以5是浅拷贝
ls = [[0]*10]*5
print (ls)
ls[0][0] = 1
print(ls)
#使用解析语法创建多维列表,在中括号里面,后面是对可迭代对象的遍历,每次取一个元素,执行相应的操作
#这个例子中,是每次取一个元素,就执行一次[0]*10 操作,创建一个[0]*10数组,最终生成一个5*10数组
ls = [[0]*10 for i in range(5)]
print (ls)
ls[0][0] =1
#因为各个数组是独立创建的,所有只修改其中一个
print(ls)

print("===================解析语法=================")
#解析语法的基本结构 以列表解析为例子(也称为列表推导)
#[expression   for value in iterable   if condition]
#三要数 :表达式,可迭代对象,if条件
#执行过程:从可迭代对象中拿出一个元素,通过if条件(如果有的话),对元素进行筛选,若通过筛选,则把元素传递给表达式,若未通过,则进入下一次迭代
# 将表达式产生的结果作为列表的一个元素,直到迭代对象迭代结束,返回新创建的列表
#等价于如下代码
#result = []
#for value in iterabe:
#    if condition:
#        result.append(expression)
#例子 求20以内的奇数的平方
squares = []
for i in range(1,21):
    if i%2 == 1:
        squares.append(i**2)
print(squares)
print ([i**2  for i in range(1,21) if i%2 == 1])
#支持多变量
x = [1,2,3]
y = [1,2,3]
results = [i*j for i,j in zip(x,y)]
print (results)
#支持嵌套循环
colors = ["black","while"]
sizes = ["S","M","L"]
tshirts = ["{} {}".format(color,size) for color in colors for size in sizes]
print (tshirts)

#其它解析语法的例子
#解析语法构造字典(字典推导)
squares = {i:i**2 for i in range(10)}
for k,v in squares.items():
    print(k,": ",v)

#解析语法构造集合(集合推导)
squares = {i**2 for i in range(10)}
print(squares)
#生成器推导 可以进行迭代
squares = (i**2 for i in range(10))
for square in squares:
    print(square)

#条件表达式  expr1 if condition else expr2  如果条件成立,就执行expr1 ,否则执行expr2
#将n的绝对值赋值给x
n = -10
x = n if n>=0 else -n
print (x)

print("======================三大神器 生成器 迭代器 装饰器====================")
#生成器 如果要计算列表中1到100每个数的平方,采用列表迭代的方式,占用大量内存,此时可以使用生成器
#生成器采用惰性计算,海量数据,不需要存储 一边迭代一边计算 每次只算出当次需要的值,后面的值用到的时候再计算
#生成器实际上一直在执行next()操作,取到下一个值,直到无值可取
#squares = (i**2 for i in range(10000))
#for i in squares
#    pass
#采用生成器无需显示存储全部数据,节省内存
print (sum(i for i in range(101)))
#生成器函数 yield
#以生成斐波那契数列为例子 数列的前两个元素为1,1,之后的元素为其前两个元素之和
def fib(max):
    ls = []
    n,a,b = 0,1,1
    while n < max:
        #ls.append(a)
        print (a) #每次打印输出斐波那契数列就可以了
        a,b = b,a+b
        n = n+1
    return ls

fib(10)

#使用yield,遇到yield语句,会将后面的元素返回,当它执行完返回后,就会停在这里,知道进行下一次next操作,它会从停止的地方继续执行
def fib(max):
    n,a,b = 0,1,1
    while n < max:
        yield a
        a,b = b,a+b
        n = n +1
fib(10)
for i in fib(10):
    print(i)

#迭代器
#可直接用于for循环的对象称为可迭代对象:iterable
#列表 元组 字符串 字典 集合 文件 都是可迭代对象 我们可以使用isinstance()判断一个对象是否是iterable对象
from collections import Iterable
print(isinstance([1,2,3],Iterable))
print(isinstance({"name":"Sarah"},Iterable))
print(isinstance('Python',Iterable))
#生成器也是可迭代对象
squares =  (i**2 for i in range(5))
print(isinstance(squares,Iterable))
#生成器不但可以用于for循环,还可以被next()函数调用
#每调用一次next函数,取出一个元素,直到没有数据可取,抛出StopIteration
print(next(squares))
print(next(squares))
#可以被next()函数调用并且不断返回下一个值,直到没有数据可取的对象称为迭代器: Iterator
#可以使用isinstance()判断一个对象是否是iterator对象
#生成器都是迭代器
from collections import Iterator
squares = (i**2 for i in range(5))
print(isinstance(squares,Iterator))
#列表 元组 字符串 字典 集合不是迭代器
print(isinstance([1,2,3],Iterator))
#可通过iter(iterable)创建迭代器
print(isinstance(iter([1,2,3]),Iterator))
#zip enumerate 等 itertools里的函数是迭代器
x = [1,2]
y = ["a","b"]
zip(x,y)
for i in zip(x,y):
    print(i)
print(isinstance(zip(x,y),Iterator))
#文件是迭代器
with open("test.txt","r",encoding="utf-8") as f:
    print(isinstance(f,Iterator))
#迭代器是可耗尽的
#range()不是迭代器,它不可以被next调用 且无法被耗尽,它是一种懒序列
numbers = range(10)
print(isinstance(numbers,Iterator))


#装饰器
#适用场景 需要对已经开发上线的程序添加某些功能,不能对程序中函数的源代码进行修改,不能改变程序中函数的调用方式
#函数对象 函数是python中的第一类对象 可以把函数赋值给变量 对该变量进行调用 可实现原函数的功能
def square(x):
    return x**2
print(type(square)) #square 是function类的一个实例
pow_2 = square  #可以理解为给这个函数起了一个别名pow_2
print(pow_2(5))
print(square(5))
#可以将函数作为参数传递
#高阶函数 接收函数作为参数,或者返回一个函数 满足这两个条件之一的函数称之为高阶函数
def square1(x):
    return x**2

def pow_2(fun): #高阶函数
    return fun

f = pow_2(square1) #将square1这个函数作为参数赋值给pow_2,它的返回值还是square1这个函数
print(f(8))
print(f==square1)

#嵌套函数 在函数的内部定义一个函数,并且调用
def outer():
    print("outer is running")
    def inner():
        print("inner is running")
    inner()

outer()

#闭包
#闭包是延伸了作用域的函数,如果一个函数定义在另一个函数作用域内,并且引用了外层函数的变量,则该函数称为闭包
#闭包是由函数及其相关的引用环境组合而成的实体(即 闭包=函数+引用环境),即不但返回内部函数,还返回外部环境的引用
def outer1():
    x = 1
    z = 10

    def inner():
        y = x + 100
        return y,z
    return inner

f = outer1() #f实际上包含了inner函数本身+outer函数的环境
print(f)
res = f()
print(res) #在inner函数中用到了outer函数的变量
#一旦在内层函数重新定义了相同名字的变量,则变量成为局部变量
def outer2():
    x = 1
    def inner():
        #x = x + 100 #这里x定义在内层函数中,默认为局部变量,内层找不到x的值,所以报错
        nonlocal x #用nonlocal声明x不是举报变量
        x = x + 10
        return x
    return inner

f = outer2()
f()

#一个简单的装饰器
#嵌套函数的实现
import time
#定义timer装饰器函数
def timer(func):
    #定义嵌套函数inner
    def inner():
        print("inner run")
        start = time.time()
        #在inner中运行传递过来的函数,并且在前后用两个时间戳获得它运行的时间
        func()
        end = time.time()
        print("{}函数运行用时{:.2f}秒".format(func.__name__,(end-start)))
    return inner()

#定义一个f1函数,我们希望它在运行的时候,统计一下用了多长时间
def f1():
    print("f1 run")
    time.sleep(1)

#将f1函数传递到timer()函数里面去,返回值是inner,此时返回值f1不单单包括inner函数,还包括timer函数的外部环境,包括参数func
f1 = timer(f1)
f1

#语法糖
@timer    #相当于实现了f2 = timer(f2)
def f2():
    print("f1 run")
    time.sleep(1)
f2

#装饰有参函数
def timer1(func):
    #定义嵌套函数inner
    def inner(*args, **kwargs):
        print("inner run")
        start = time.time()
        #在inner中运行传递过来的函数,并且在前后用两个时间戳获得它运行的时间
        func(*args,**kwargs)
        end = time.time()
        print("{}函数运行用时{:.2f}秒".format(func.__name__,(end-start)))
    return inner()

@timer1
def f3(n1,n2):
    print("f3 run")
    time.sleep(n)
#f3(3) 报错?


#装饰器本身也要传递一些额外的参数 理解闭包是关键

#何时执行装饰器 一装饰就执行 不必等调用
#通过python内部装饰器 @wraps可以将掩饰掉的原函数的属性重新回来

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值