函数global nonlocal 应用 可迭代对象 迭代器

day11

一丶关键字:global,nonlocal

global 声明全局变量:

1. 可以在局部作用域声明一个全局变量

2. 可以修改全局变量

# 解释器认为: 如果你在局部作用域对一个变量进行修改,局部作用域已经定义了好这个变量
# 异常:
# UnboundLocalError: local variable 'count' referenced before assignment

####相当于局部声明的变量,剪切到全局
count=0
print(locals())      # count:0
def func():
   global  count    #定义成全局变量
   count+=1         # 修改全局count的值
   print(locals())  # 查看当前(现在就是局部空间)空间的变量和值,   没count变量
func()
print(locals())      # 查看当前(现在就是全局空间)空间的变量和值 ,count:1

 

nonlocal 局部作用域如果想对父级作用域的变量(python3x新加的功能):

1.可以对父级别作用域的变量进行修改,并且在当前作用域创建 ​ 2.不能操作全局作用域

####复制  , 共用一块内存地址
def func():
   count=0         #局部变量
   def inner():
       nonlocal  count      #inner函数内 修改 count 变量, 需要nonlocal声明
       count+=3
       print(count)        
       print(id(count))      #id() 查看这个inene函数中count变的内存地址 -->1952940208(内存地址)
       print(locals())  #查看当前作用域中的变量和值 {'count': 3}
   inner()
   print(locals()) #{'inner':<function func.<locals>.inner at 0x00000140E1ABBD90>, 'count': 3}
   print(id(count))  #id() 查看这个func函数中count变的内存地址 1952940208(内存地址)
func()

 

二丶形参中---默认参数的坑

###当你的默认参数的数据类型是可变的数据类型时   千万注意,使用的是同一个可变类型数据的内存地址 so看代码👇

#默认参数是字典
def func(a,b={}):
   b[a+1]=a
   return b
print(func(1,))
print(func(2,))
print(func(3,))
print(func(5,))



#默认参数是列表类型
def func(a,b=[]):
   b.append(a)
   return b
print(func(1,))
print(func(1))
print(func(1))
func(1,2)

 

三丶函数名的应用

函数名:就是一个特殊的变量 , 别称:第一类对象

函数名指向的是一个函数的内存地址,函数名加上()就能够执行函数

###废话不多说,上代码👇

## 1. 函数名可以当做一个变量 ,具有变量的赋值功能
def func():
   print('in func ')
print(func)  #打印函数func的内存地址 自己打
a=func # 将函数的内存地址给了a
c=a #相当于c变量拿到 a 或者 func的函数内存地址
c()                    #相当于 c()=func(), 执行函数func()


## 2. 函数名容器类类型的元素
def func1():
   print('in func1')
def func2():
   print('in func2')
def func3():
   print('in func3')
li=[func1,func2,func3]

for el in li:   # 循环每个元素, el就是函数的内存地址
   el()        # 执行每个函数      
#拓展👆:你要是有2000个函数,你总不能写2k个"函数明()". 用for循环执行2k个函数   so easy


# 3. 函数名 可以作为函数的实参
def func(argv):            
   argv()                  #接收传来的函数名+() --->执行这个函数
   print('in func')
def inner():
   print('in inner')
func(inner)             #把其他的函数的名作为参数传给func函数的argv


# 4.函数名可以作为函数的返回值
def func():
   print('in func')
   return inner             #返回 其他函数的函数名,
def inner():
   print('in inner')          
func()()                     # 相当于func()=inner --->inner() 执行inner函数

 

四丶python新特性字符串输出:f-string

新特性:f-strings 是python3.6 格式化输出新的写法,效率高,更简化,好用

####看代码👇
#### 用法格式
name='宇宙盖世无敌小keNai,😳嘻嘻'
s=f'我叫 {name}'        # {变量,函数名(),表达式} ,除了特殊的字符如: ;分号 :冒号 ,逗号(变量前) !


#用法①: 直接操作字符串
s1='李四'
s2=f'哒哒哒哒哒{s1.upper()}'
print(s2)

#用法②: 放置列表元素
li=['太白',18,176]
s1=f'{li[0]},{li[1]} ,{li[2]}'
print(s1)

#用法③: 可以结合函数
def func(a,b):
    return a+b
s=f'{func(1,2)}'
print(s)

 

五丶可迭代对象

含义:

可以重复的迭代的实实在在的东西

专业角度:

内部_ _ iter _ _ 方法的对象,就是可迭代对象

#常见的可迭代对象: list , tuple ,dict ,str 

# 内置函数 ,查看所有方法,属性
print(dir(str))

#验证是不是 可迭代对象
s1 = '不打广告'
i = 100
print('__iter__' in dir(i))  # False
print('__iter__' in dir(s1))  # True

#常用的方法验证 xx 是不是一个可迭代对象
print('__iter__' in dir(str))


#可迭代对象的优缺点
#优点:
1.直观
2.操作方法多
#缺点:
1. 消耗内存较大
2. 不能迭代取值(索引)

 

 

六丶迭代器

含义:

是一个可以迭代取值的工具

专业角度:

内部含有 "__ iter__ " 并且含有 "__next__" 就是迭代器

#迭代器是看不到内存地址

####可迭代对象转化成迭代器:
#可迭代对象转化成迭代器 , 内置函数iter() 和 __iter__() 两种方式
li=[1,2,3]
obj=iter(li)   #把迭代对象转换成迭代器
objg=li.__iter__()          #把迭代对象转换成迭代器
print(type(obj),type(objg))     #<class 'list_iterator'>
print(obj)  # <list_iterator object at 0x000002075D219518> 迭代器



####迭代器可以迭代取值, 利用内置函数next()进行取值 . 取完值,值就消失了
li=[1,2,3]
obj=iter(li)
print(next(obj)) # 迭代一次,取值一次,值取完就没了.销毁
print(next(obj))
print(next(obj))
print(next(obj)) # 当迭代器中没有值可取了 ,会把报错 StopIteration  



####利用while 模拟 for 循环内部循环可迭代对象的机制
#1.先将可迭代对象转换成迭代器
#2.利用next对迭代对象进行取值
#3.利用异常处理try一下 防止报错~~

#方法1
try:
   li = [1, 2, 3, 4, 5]
   li_itera = iter(li)
   while 1:
       print(li_itera.__next__())
except StopIteration:
   pass

#方法2
li = [1, 2, 3, 4, 5]
li_itera = iter(li)
while 1:
   try:
       print(next(li_itera))
   except:
       break
       
       
       
#迭代器是一条路走到底(记录位置)    
li=[1,2,3,4,]
obj=iter(li)
for index in range(2):          # 1 2 ,取完值,值就销毁
    print(obj.__next__())
for index in range(1):          # 3
    print(obj.__next__())

 

七丶可迭代对象与迭代器的对比

####可迭代对象: 
可迭代对象是一个操作比较灵活(比如列表,字典的增删改查,字符串的常用操作方法等),直观,效率相对高,
但是占用内存,而且不能直接通过循环迭代取值的这么一个数据集。
####迭代器:  
可以记录取值位置,以直接通过循环+next方法取,迭代器是一个非常节省内存,满足惰性机制,
但是相对效率低,操作方法比较单一的数据集。(可参考为什么python把文件句柄设置成迭代器)

 

posted on 2020-01-11 15:19  向往1  阅读(220)  评论(0)    收藏  举报

导航

……