• Python基础知识补充(重要)-作用域、特殊语法


    Python作用域

    python代码内部块如if语句内声明变量,在if代码段后在调用此变量并未报如“undefinded name"此类错误,例子如下:

    if 1 == 1:
        name = 'Jason'
    print(name)
    
    ##result
    Jason

    如果在java和c#中,会抛出异常,而在python和javascript中均无报错,这正是因为python和javascript中无块级作用域

    • 在有块级作用域的语言中,比如java/c#,代码中的name只在当前作用域下生效。
    • 在没有块级作用域的语言中,比如python/javascript中,代码中的name变量,不仅在代码块中生效,在代码块外面也一样生效

    python中函数中定义变量,函数执行后,外部调用,是怎样的情况呢?例子如下:

    def func():
        name = 'Jason'
    
    func()
    print(name)
    
    ##result
        print(name)
    NameError: name 'name' is not defined

    在函数的作用域中,变量无法生效的。

    python中有作用域链,对于变量的查找方式是由内向外查找的,当前作用域中有,使用当前变量设置,如果没有,往外查找,直到找到最后找不到而报错。

    看个例子能更为直观些:

    name='outer'
    def f1():
        name='f1'
        def f2():
            name = 'f2'
            print(name)
        f2()
    f1()
    
    ##result
    f2

    按照上面所说的查找规则,先从f2中查找name,f2中name的值为f2,正如执行结果,若果f2内没有name变量,则向外查f1内是否有,若没有则在f1外查找,找到为止,未找到则报错

    python/javascript中作用域与函数的关系

    对于作用域来说,在函数没有执行之前,他的作用域、作用域链均已经确定。
    看下例子:

    name = 'Jason'
    
    
    def f2():
        name = 'eric'
        f1()
    def f1():
        print(name)
    f2()
    ##result
    Jason
    def f1():
        print(name)
    def f2():
        name = 'eric'
        return f1
    ret = f2()
    ret()
    ##result
    Jason
    以上两段代码,执行结果一致,这是Python一个很容易掉进的坑,在作用域1中,作用域会直接用使用全局变量name='Jason',但在作用域2中,虽然有一个局部变量name,但在程序最终执行之前,python已经从上到下把作用域和作用域链确定了,就是f1()的执行结果肯定是Jason,不受其他因素的影响。
     

    Python特殊用法tip

    li=[x+100 for x in range(10)]   #在0-9循环,并且每次循环+100
    print(li)
    lis=[x+100 for x in range(10) if x > 6]     #只有x>6时,x+100
    print(lis)
    
    li1=[lambda: x for x in range(10)] #首先li是一个列表,列表中的元素都是函数
    print(li1)
    # print(type(li1))
    r=li1[0]()      #函数加括号执行lambda表达式
    print(r)        #最后x为9,所以每个元素都是return 9
    output:
    [100, 101, 102, 103, 104, 105, 106, 107, 108, 109]
    [107, 108, 109]
    [<function <listcomp>.<lambda> at 0x0000019EC393D598>, <function <listcomp>.<lambda> at 0x0000019EC393D620>, <function <listcomp>.<lambda> at 0x0000019EC393D6A8>, <function <listcomp>.<lambda> at 0x0000019EC393D730>, <function <listcomp>.<lambda> at 0x0000019EC393D7B8>, <function <listcomp>.<lambda> at 0x0000019EC393D840>, <function <listcomp>.<lambda> at 0x0000019EC393D8C8>, <function <listcomp>.<lambda> at 0x0000019EC393D950>, <function <listcomp>.<lambda> at 0x0000019EC393D9D8>, <function <listcomp>.<lambda> at 0x0000019EC393DA60>]
    9

     python lamda函数用于定义一些简单函数,如加减等,例子如下:

    def lambda():
        return x
    ##li中lambda函数只是如上面定义的函数,返回x,与后面的for循环无直接联系,当for循环结束后,x值为9,付给lambda函数,最终li列表的第一个值为9
    li = [lambda :x for x in range(10)]

    其实把他拆开,我们可以这么写一行:

    li = []
    for i in range(10)
        def f1():
            return i
        li.append(f1)
    print(li[1]())
    ##result
    9
    首先for 循环已完成,i已经赋予9,然后f1()执行时,按照作用域链查找,i=9,那么返回就是9了。
    那么如果对f1中的x赋值会怎样:
    li = []
    for i in range(10)
        def f1(x=i):
            return x
        li.append(f1)
    print(li[0]())
    print(li[1]())
    print(li[2]())

     output:

    0
    1
    2

    为什么呢,因为x=i是一个表达式,表达式是执行了函数。所以还是要看他的本质,要看函数是否被执行

    总结
    总结下这篇的重要的三句话吧:
    
    python中是以函数作为作用域的,并且python中无块级作用域
    对于作用域来说,在函数没有执行之前,他的作用域、作用域链均已经确定。,并且:对于变量的查找方式是由内向外查找的,当前作用域中有,使用当前变量设置,如果没有,往上查找,知道找到最后找不到而报错。
    函数在没执行前,内部代码不执行。在碰到lambda时候需要注意!!!
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    重拾安卓_01_安卓开发环境搭建(eclipse)
    重拾安卓_01_安卓开发环境搭建(android studio)
    【BZOJ】1038: [ZJOI2008]瞭望塔
    【BZOJ】2178: 圆的面积并
    【UR #4】元旦三侠的游戏(博弈论+记忆化)
    【BZOJ】1027: [JSOI2007]合金(凸包+floyd)
    【POJ】1151 Atlantis(线段树)
    【POJ】1228 Grandpa's Estate(凸包)
    【POJ】1556 The Doors(计算几何基础+spfa)
    【POJ】1113 Wall(凸包)
  • 原文地址:https://www.cnblogs.com/jasonwang-2016/p/5664450.html
Copyright © 2020-2023  润新知