range作用于对象global失败_类的临时作用域与名字空间

类的临时作用域与名字空间

类定义时,类体在一个新的栈帧中执行,当类体结束执行时,其执行帧将被丢弃,而其局部命名空间会被保存。执行帧只是一个临时作用域。 一个类对象随后会被创建,在其全局名字空间中,类名绑定到该类对象。定义过程中创建的局部名字空间就成了类对象的属性。

虽然类定义会创建一个作用域,但这个作用域是临时的,它与类方法的作用域没有嵌套关系,类方法不能引用类作用域中的变量,但可以引用类外模块的全局变量。

x = 0class X(object):    y = x    x = x + 1       z = x    defmethod(self):       print(self.x) # -> 1        print(x)     # ->0, the global x       print(y)      # -> NameError: global name 'y' is notdefinedinst = X()print(inst.x, inst.y, inst.z, x)  # ->(1, 0, 1, 0)inst.method()运行一下:1 0 1 010NameError: name  'y' is not defined

类体中的语句可以引用类作用域的局部变量(y,z),但方法内的语句不能引用变量y,但可以引用类外的全局变量x。

正是因为类中的方法不能直接引用类体中的变量,所以在类实例化后,方法只能加上限定词(比如self.x)才能引用这些变量,通常,这些类变量被称做类的属性,可以由类的实例使用,也可以由其子类继承。

类中的列表推导式:

来看一个例子:

>>> class A():        a = 3        b = [a + i for i in range(10)]NameError: name 'a' is not defined # 列表推导式中的名字‘a’没有定义

我们知道,在Python3+中,函数包括:匿名函数,列表推导式,字典推导式及生成器表达式。推导式是定义后紧跟着就会执行,这点与函数颇为不同。

由于方法内的语句不能引用类变量a,类外也没有定义a,所以一直查找不到它,因而报错。

需要注意的是,在Python2+中,列表推导式并不是函数,因而上面的类可以定义。但因为这些旧的版本已经不再维护,所以这里不做过多探讨。而生成器表达式或其它推导式,无论在Python2+或Python3+版本中,它们都是函数。

那么怎样解决上面的错误呢?

可以用匿名函数lambda,它有自己的作用域。当它想引入类域的变量时,通常使用默认值参数,这是因为默认值参数的求值是在函数创建时发生的,也即在类域中求值:

>>> class A(object):        a =3        b =(lambda a=a: [a + i for i in range(3)])( )>>> A.b[3, 4, 5]

列表推导式使用类作用域变量的情况

看了上面的解释,是不是感觉关于作用域的知识已经学习得很透彻了?别急,看看下面的坑:

>>> class A(object):        a = 3        b = [i for i inrange
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值