2

为了在我的代码中获得某种顺序,我将一个类放在另一个类中,内部类根本不需要外部类(至少我之前是这么想的)。

作为代码的行为:

class A:
    def __init__(self):
        self.a=10
    def do(self):
        print(self.a)
        return A()
a=A()
print(a.do())
#this runs as expected with the output:
#10
#<__main__.A object at 0x01234567>

#cleaning up
del A

class B:
    #same code for class A
    class A:
        def __init__(self):
            self.a=10
        def do(self):
            print(self.a)
            return A()
a=B.A()
print(a.do())
#This raises for the line 'return A()' a NameError: global name 'A' is not defined

我不明白为什么在这种情况下不能从其内部访问 A 。

这是另一件类似且运行良好的事情:

def f():
    a=10
    class C:
        def __init__(self):
            pass
        def do(self):
            print(a)
            return C()
    return C().do()
print(f())

附加问题:为什么在这种情况下类的行为与功能不同,我们从中得到什么好处?

4

2 回答 2

1

你应该使用这个:

return B.A()

由于 classA不是全局变量,它是 class 的属性B。类本身就是命名空间,即类中定义的所有对象实际上都成为它的属性。

class B:
    #same code for class A
    class A:
        def __init__(self):
            self.a=10
        def do(self):
            print(self.a)
            return B.A()

>>> B.A
<class __main__.A at 0x9f3ea1c>
>>> a = B.A()
>>> print(a.do())
10
<__main__.A instance at 0x9fd7aec>

代码2:

def f():
    a=10
    class C:
        def __init__(self):
            pass
        def do(self):
            print(a)
            return C()
    return C().do()
print(f())

此代码与嵌套类 1 完全不同。函数不会创建一个新的命名空间,它们只是创建一个新的作用域。

所以, classC只是 function 的局部变量,这就是为什么在里面f()调用会正常工作的原因。return C()do()

教程 :

http://docs.python.org/2/tutorial/classes.html

http://docs.python.org/2/tutorial/controlflow.html#defining-functions

于 2013-06-29T20:27:24.837 回答
1

类变量只能从类主体中直接访问。

当查找变量名称时,该过程以这种方式工作(假设没有globalnonlocal声明):

  1. 查看当前范围(类或函数或全局)
  2. 如果没有找到,递归查找外层函数范围
  3. 如果找不到,请在全局范围内查找
  4. 如果找不到,请查看内置范围

块执行过程中,无论是函数定义还是类体,对象本身还不存在,所以显然不能引用。

让我们看看如果在绑定算法中将类计算为封闭范围会发生什么:

x=3
class A:
    def __init__(self):
        A.x = 5

    def foo(self):
        print(x)

a=A()
a.foo()

类定义中没有绑定A.x,所以print(x)必须引用全局 x,对吗?但是当a.foo()被调用时,有一个可以引用A.x。这不直观。与类作用域不同,函数作用域是不可变的(实际上是不可访问的)。

此外,classvar除了globaland之外,您还需要声明nonlocal。它只适用于当前班级,所以你也需要nonlocal classvar声明......

我认为类不被视为“封闭范围”的另一个原因是允许使用元类自定义类创建。但我不确定,

于 2013-06-29T20:37:57.010 回答