第三章 Python基础——文件操作&函数 续

3.6函数进阶

名称空间:name space

例:若变量X=1,1存放于内存中,那存放X与1绑定关系的地方就叫做名称空间。

名称空间共三种,分别如下:

  • locals:是函数内名称空间,包括局部变量和形参
  • globals:全局变量,函数定义所在模块的名字空间
  • builtins:内置模块的名字空间

不同变量的作用域不同就是由于这个变量所在的命名空间决定的。

作用域即范围:

  • 全局范围:全局存活,全局有效
  • 局部范围:临时存活,局部有效

注:查看作用域方法 globals(),locals()

作用域查找顺序:

level=‘L0‘
n=22

def func():
      leval=‘L1‘
      n=33
      print(locals())

      def outer():
            n=44
            level=‘L2‘
            print(locals(),n)

            def inner():#此处打印n是多少?
                  level=‘L3‘
                  print(locals(),n)
            inner()
        outer()

func()

问题:在inner()里的打印n的值是多少?

LEGB代表名字查找顺序:locals->enclosing function->globals->__builtins__

  • locals是函数内的名字空间,包括局部变量和形参
  • enclosing外部嵌套函数的名字区间
  • globals全局变量,函数定义所在模块的名字空间
  • builtins内置模块的名字空间

闭包

关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数)。

详解:而且,这些内部函数可以访问他们所在外部函数中声明的所有局部变量、参数。当其中一个这样的内部函数在包含他们的外部函数被调用时,就会形成闭包。也就是说,内部函数会在外部函数返回后被执行。而当这个内部函数执行时,它仍然必须访问其外部函数的局部变量、参数以及其他内部函数。这些局部变量、参数和函数声明(最初时)的值是外部函数返回时的值,但也会会受到内部函数的影响。

def outer():
      name=‘alex‘

      def inner():
           print("在inner里打印外层函数的变量“,name)

        return inner

f=outer()
f()

闭包的意义:返回的函数对象,不仅仅是一个函数对象,在函数外还包裹了一层作用域,这使得该函数无论在何处调用,优先使得自己外层包裹的作用域

装饰器

例1:

#_*_coding:utf-8_*_

user_status = False #用户登录了就把这个改成True

def login():
    _username = "alex" #假装这是DB里存的用户信息
    _password = "abc!23" #假装这是DB里存的用户信息
    global user_status
    if user_status == False:
        username = input("user:")
        password = input("pasword:")
        if username == _username and password == _password:
            print("welcome login....")
            user_status = True
        else:
            print("wrong username or password!")
    else:
        print("用户已登录,验证通过...")

def home():
    print("---首页----")

def america():
    login() #执行前加上验证
    print("----欧美专区----")

def japan():
    print("----日韩专区----")

def henan():
    login() #执行前加上验证
    print("----河南专区----")

home()
america()
henan()

注:在软件开发中有一个原则“开放-封闭”原则,简单来说,它规定已经实现的代码不允许被修改,但可以被扩展,即:

封闭:已实现的功能代码不应该被修改

开放:对现有功能的扩展开放

def login(func): #把要执行的模块从这里传进来

    def inner():#再定义一层函数
        _username = "alex" #假装这是DB里存的用户信息
        _password = "abc!23" #假装这是DB里存的用户信息
        global user_status

        if user_status == False:
            username = input("user:")
            password = input("pasword:")

            if username == _username and password == _password:
                print("welcome login....")
                user_status = True
            else:
                print("wrong username or password!")

        if user_status == True:
            func() # 看这里看这里,只要验证通过了,就调用相应功能

    return inner #用户调用login时,只会返回inner的内存地址,下次再调用时加上()才会执行inner函数

简化上边的代码——去掉下边这行

america=login(america)#你在这里相当于把america这个函数替换了

最终简化为:

#_*_coding:utf-8_*_

user_status = False #用户登录了就把这个改成True

def login(func): #把要执行的模块从这里传进来

    def inner(*args,**kwargs):#再定义一层函数
        _username = "alex" #假装这是DB里存的用户信息
        _password = "abc!23" #假装这是DB里存的用户信息
        global user_status

        if user_status == False:
            username = input("user:")
            password = input("pasword:")

            if username == _username and password == _password:
                print("welcome login....")
                user_status = True
            else:
                print("wrong username or password!")

        if user_status == True:
            func(*args,**kwargs) # 看这里看这里,只要验证通过了,就调用相应功能

    return inner #用户调用login时,只会返回inner的内存地址,下次再调用时加上()才会执行inner函数

def home():
    print("---首页----")

@login
def america():
    #login() #执行前加上验证
    print("----欧美专区----")

def japan():
    print("----日韩专区----")

# @login
def henan(style):
    ‘‘‘
    :param style: 喜欢看什么类型的,就传进来
    :return:
    ‘‘‘
    #login() #执行前加上验证
    print("----河南专区----")

home()
# america = login(america) #你在这里相当于把america这个函数替换了
henan = login(henan)

# #那用户调用时依然写
america()

henan("3p")

带参数装饰器:

#_*_coding:utf-8_*_
user_status = False #用户登录了就把这个改成True

def login(auth_type): #把要执行的模块从这里传进来
    def auth(func):
        def inner(*args,**kwargs):#再定义一层函数
            if auth_type == "qq":
                _username = "alex" #假装这是DB里存的用户信息
                _password = "abc!23" #假装这是DB里存的用户信息
                global user_status

                if user_status == False:
                    username = input("user:")
                    password = input("pasword:")

                    if username == _username and password == _password:
                        print("welcome login....")
                        user_status = True
                    else:
                        print("wrong username or password!")

                if user_status == True:
                    return func(*args,**kwargs) # 看这里看这里,只要验证通过了,就调用相应功能
            else:
                print("only support qq ")
        return inner #用户调用login时,只会返回inner的内存地址,下次再调用时加上()才会执行inner函数

    return auth

def home():
    print("---首页----")

@login(‘qq‘)
def america():
    #login() #执行前加上验证
    print("----欧美专区----")

def japan():
    print("----日韩专区----")

@login(‘weibo‘)
def henan(style):
    ‘‘‘
    :param style: 喜欢看什么类型的,就传进来
    :return:
    ‘‘‘
    #login() #执行前加上验证
    print("----河南专区----")

home()
# america = login(america) #你在这里相当于把america这个函数替换了
#henan = login(henan)

# #那用户调用时依然写
america()

# henan("3p")

3.6生成器,迭代器

列表生成式:

例:把列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求把列表里的每个值都加1

>>> a = [i+1 for i in range(10)]
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10列表生成式]

这种写法就叫做生成式

生成式

在python中一边循环一边计算的机制称为生成器:generator

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

>>> L = [x * x for x in range(10)]>>> L[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]>>> g = (x * x for x in range(10))>>> g<generator object <genexpr> at 0x1022ef630>

Lg的区别仅在于最外层的[]()L是一个list,而g是一个generator。

我们可以直接打印出list的每一个元素,想要打印书generator的每一个元素有哦两种方法:

第一种用next()

>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>> next(g)
36
>>> next(g)
49
>>> next(g)
64
>>> next(g)
81
>>> next(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

第二种for循环,generator也是可迭送的对象

>>> g = (x * x for x in range(10))
>>> for n in g:
...     print(n)
...
0
1
4
9
16
25
36
49
64
81

迭送器

可以直接作用于for循环的数据类型有以下几种:

一类是集合数据类型,如listtupledictsetstr等;

一类是generator,包括生成器和带yield的generator function。

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

可以使用isinstance()判断一个对象是否是Iterable对象:

>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance(‘abc‘, Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False

而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

*可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。

可以使用isinstance()判断一个对象是否是Iterator对象:

>>> from collections import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance(‘abc‘, Iterator)
False

生成器都是Iterator对象,但listdictstr虽然是Iterable,却不是Iterator

listdictstrIterable变成Iterator可以使用iter()函数:

>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter(‘abc‘), Iterator)
True

Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

原文地址:https://www.cnblogs.com/cnlogs1/p/9553468.html

时间: 2024-10-07 23:17:11

第三章 Python基础——文件操作&函数 续的相关文章

萌新向Python数据分析及数据挖掘 第一章 Python基础 第八节 函数

第一章 Python基础 第八节 函数 定义函数 函数 其实就可以理解为外挂,把一些常用的.重复率比较多你又不想重复写的东西写进函数,加上开关实现简化操作 举个简单的例子 1 def greet_user(username): 2 #定义一个叫做"迎接用户"的外挂,让他能直接打印一个问候语,括号里面是函数需要输入的东西,也就是个性化的东西 3 """先是简单的问候语""" 4 print("Hello! "

python 基础(文件操作,注册,以及函数)

1,文件操作 1,文件路径: 2,编码方式:utf-8, gbk.... 3,操作方式:只读,只写,追加,读写,写读 1,只读 :r   rb   不用编码,以什么形式存储就以什么形式读出来 f = open('  文件名',mode = 'r',encoding = 'utf-8') content = f.read() print(content) f.close()  必须存在 2,只写:w     没有此文件就会创建,先将源文件的内容全部清除,再写    wb不用编码 3,追加:a 4,

第四章 python的文件操作

在python里,我们可以通过open()方法打开文件并且用内置方法处理文件内容. 需要注意的是,open() 会默认自动转换为2进制再存储(write方法执行时).所以open命令也是在2进制的基础上进行存储的. 4.1 文件基本操作 obj = open(file='路径',mode='模式',encoding='编码') obj.write() # 可写模式下 obj.read() # 可读模式下 obj.close() 4.2 打开模式 操作字符串 r/w/a r+/w+/a+ 直接操作

第三章-Python基础 课后答案

3-1 python是动态语言,它的对象的类型和内存都是运行时确定的:在创建新对象时,解释器会根据语法和右侧的操作数来决定新对象的类型. 3-2 python不用去声明函数的返回类型,是由其“若类型”的语言特性决定的.python是把储存的数据直接放到内存,然后再去用一个变量名引用这个数据. 3-3 因为python系统定义的名字是__xxx__,所以在变量名的开始和结尾使用双下划线容易引起混淆. 3-4 可以,但是要用";"分隔开. 3-5 可以,一行过长的语句可以使用反斜杠( \

课堂笔记:Python基础-文件操作

对文件操作流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 现有文件如下: 昨夜寒蛩不住鸣. 惊回千里梦,已三更. 起来独自绕阶行. 人悄悄,帘外月胧明. 白首为功名,旧山松竹老,阻归程. 欲将心事付瑶琴. 知音少,弦断有谁听. f = open('小重山') #打开文件 data=f.read()#获取文件内容 f.close() #关闭文件 注意 :在Windows系统中,hello文件是utf8保存的,打开文件时open函数是通过操作系统打开的文件,而win操

第三章 python基础

花了一个星期多看了 <learn python the hard way>,只能说掌握了皮毛的皮毛,今天开始学习看<core python programming>. 同样,也分享自己的学习笔记,督促自己,激励自己. 3.1 语句和语法Python 语句中有一些基本规则和特殊字符:?? 井号(#)表示之后的字符为 Python 注释?? 换行 (\n) 是标准的行分隔符(通常一个语句一行)?? 反斜线 ( \ ) 继续上一行?? 冒号 ( : ) 将代码块的头和体分开?? 语句(代

Python基础-文件操作

1. 文件操作流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 语法 open(filename, mode) 实例 2. 文件打开模式 r,只读模式(默认). w,只写模式.[不可读:不存在则创建:存在则删除内容:] a,追加模式.[可读:   不存在则创建:存在则只追加内容:] "+" 表示可以同时读写某个文件 r+,可读写文件.[可读:可写:可追加] w+,写读 a+,同a "U"表示在读取时,可以将 \r \n \r\n自动转换

第三章-python基础 笔记

1.一行过长的语句可以使用反斜杠( \ )分解成几行:使用闭合操作符时,单一语句也可以跨多行,例如:在含有小括号.中括号.花括号时可以书写多行.另外就是三引号包括下的字符串也可以跨行书写. 2.一般缩进四个空格宽度为最佳,如果你的代码要跨平台应用,或被不同的编辑器读写,建议不要使用制表符. 3.分号( ; )允许你将多个语句写在同一行上,语句之间用分号隔开. 4.每一个python脚本都可以被当成一个模块. 5.多元赋值最好加上括号使代码有更高的可读性. 6.python的多元赋值方式可以实现无

Python基础-----文件操作(处理)

1. 打开文件的模式有(默认为文本模式):r ,只读模式[默认模式,文件必须存在,不存在则抛出异常]w,只写模式[不可读:不存在则创建:存在则清空内容]a, 之追加写模式[不可读:不存在则创建:存在则只追加内容] 2. 对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码.图片文件的jgp格式.视频文件的avi格式)rb wbab注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不