중첩 클래스를 생성 할 때 예기치 않은 종료가 발생했습니다. 나는 이것이 메타 클래스, 수퍼 또는 둘다와 관련된 것이라고 생각합니다. 이것은 클로저가 어떻게 생성되는지와 분명히 관련이 있습니다. 나는 python2.7을 사용하고있다.(Python) 기대하지 않았을 때 Closure가 생성되었습니다.
예 1 :
class Metaclass(type):
def __init__(self, name, bases, dict):
self.CONST = 5
class Base(object):
__metaclass__=Metaclass
def __init__(self):
"Set things up."
class Subclass(Base):
def __init__(self, name):
super(Subclass, self).__init__(self)
self.name = name
def other(self, something): pass
class Test(object):
def setup(self):
class Subclass(Base):
def __init__(self, name):
super(Subclass, self).__init__(self)
self.name = name
def other(self, something): pass
self.subclass = Subclass
class Subclass2(Base):
def __init__(self, name):
super(Subclass, self).__init__(self)
self.subclass2 = Subclass2
"0x%x" % id(Metaclass)
# '0x8257f74'
"0x%x" % id(Base)
# '0x825814c'
t=Test()
t.setup()
"0x%x" % id(t.subclass)
# '0x8258e8c'
"0x%x" % id(t.subclass2)
# '0x825907c'
t.subclass.__init__.__func__.__closure__
# (<cell at 0xb7d33d4c: Metaclass object at 0x8258e8c>,)
t.subclass.other.__func__.__closure__
# None
t.subclass2.__init__.__func__.__closure__
# (<cell at 0xb7d33d4c: Metaclass object at 0x8258e8c>,)
Subclass.__init__.__func__.__closure__
# None
예 2 :
class Test2(object):
def setup(self):
class Subclass(Base):
def __init__(self, name):
self.name = name
def other(self, something): pass
self.subclass = Subclass
t2=Test2()
t2.setup()
t2.subclass.__init__.__func__.__closure__
# None
는 여기에 내가보고하고 같은 문제 (모두가 우선 구축)를 보여 다섯 가지 간단한 예입니다
실시 예 3 :
class Test3(object):
def setup(self):
class Other(object):
def __init__(self):
super(Other, self).__init__()
self.other = Other
class Other2(object):
def __init__(self): pass
self.other2 = Other2
t3=Test3()
t3.setup()
"0x%x" % id(t3.other)
# '0x8259734'
t3.other.__init__.__func__.__closure__
# (<cell at 0xb7d33e54: type object at 0x8259734>,)
t3.other2.__init__.__func__.__closure__
# None
예 4 :
class Metaclass2(type): pass
class Base2(object):
__metaclass__=Metaclass2
def __init__(self):
"Set things up."
class Base3(object):
__metaclass__=Metaclass2
class Test4(object):
def setup(self):
class Subclass2(Base2):
def __init__(self, name):
super(Subclass2, self).__init__(self)
self.subclass2 = Subclass2
class Subclass3(Base3):
def __init__(self, name):
super(Subclass3, self).__init__(self)
self.subclass3 = Subclass3
class Subclass4(Base3):
def __init__(self, name):
super(Subclass4, self).__init__(self)
self.subclass4 = Subclass4
"0x%x" % id(Metaclass2)
# '0x8259d9c'
"0x%x" % id(Base2)
# '0x825ac9c'
"0x%x" % id(Base3)
# '0x825affc'
t4=Test4()
t4.setup()
"0x%x" % id(t4.subclass2)
# '0x825b964'
"0x%x" % id(t4.subclass3)
# '0x825bcac'
"0x%x" % id(t4.subclass4)
# '0x825bff4'
t4.subclass2.__init__.__func__.__closure__
# (<cell at 0xb7d33d04: Metaclass2 object at 0x825b964>,)
t4.subclass3.__init__.__func__.__closure__
# (<cell at 0xb7d33e9c: Metaclass2 object at 0x825bcac>,)
t4.subclass4.__init__.__func__.__closure__
# (<cell at 0xb7d33ddc: Metaclass2 object at 0x825bff4>,)
예 5 :
- 메타 클래스는 상속, 그래서
Subclass
이Base
의 메타 클래스를 가져옵니다 여기class Test5(object): def setup(self): class Subclass(Base): def __init__(self, name): Base.__init__(self) self.subclass = Subclass t5=Test5() t5.setup() "0x%x" % id(t5.subclass) # '0x8260374' t5.subclass.__init__.__func__.__closure__ # None
내가 (참조 예) 이해하는 것입니다.
__init__
만 영향을받습니다.Subclass.other
방법은 (# 1)이 아닙니다.Subclass.other
을 제거해도 차이는 없습니다 (1 번).Subclass.__init__
에서self.name=name
을 제거해도 차이는 없습니다 (1 번).- 클로저 셀의 개체가 함수가 아닙니다.
- 개체가
Metaclass
또는Base
이 아니지만 이 (# 1) 인 것처럼Metaclass
유형의 개체가 있습니다. - 개체는 실제로 중첩 된 (# 1) 유형의 개체입니다.
t1.subclass.__init__
과t1.subclass2.__init__
에 대한 폐쇄 셀은 두 개의 서로 다른 클래스 (# 1)에서 같지만 동일합니다.Subclass
(# 1)의 생성을 중첩하지 않으면 생성 된 클로저가 없습니다.super(...).__init__
을Subclass.init__
에 전화하지 않으면 폐쇄가 생성되지 않습니다 (# 2).__metaclass__
을 할당하지 않고object
에서 상속하는 경우 동일한 동작이 나타납니다 (# 3).t3.other.__init__
의 폐쇄 셀에있는 객체는t3.other
(# 3)입니다.- 메타 클래스에
__init__
(# 4)이없는 경우에도 동일한 문제가 발생합니다. Base
에__init__
(# 4)이없는 경우에도 동일한 문제가 발생합니다.- 예제 4의 세 하위 클래스에 대한 클로저 셀은 모두 다르며 각각은 해당 클래스 (# 4)와 일치합니다.
super(...).__init__
을Base.__init__(self)
으로 대체하면 클로저가 사라집니다 (# 5). 여기
내가 이해하지 못하는 것입니다 :
- 은 왜 폐쇄는
__init__
설정됩니까? - 다른 항목에 대해 클로저가 설정되지 않는 이유는 무엇입니까?
- 클로저 셀의 객체가
__init__
이 속한 클래스로 설정된 이유는 무엇입니까? super(...).__init__
을 호출 할 때만 이런 이유가 발생합니까?Base.__init__(self)
을 호출 할 때 왜 이런 일이 발생하지 않습니까?- 메타 클래스를 사용하는 것과 실제로 아무 관계가 없습니까 (기본 메타 클래스가
type
이므로)?
도움을 주셔서 감사합니다! 여기에 (제이슨의 통찰력을 기반으로) 그때 발견 뭔가
-Eric
(업데이트) :
def something1():
print "0x%x" % id(something1)
def something2():
def something3():
print "0x%x" % id(something1)
print "0x%x" % id(something2)
print "0x%x" % id(something3)
return something3
return something2
something1.__closure__
# None
something1().__closure__
# 0xb7d4056c
# (<cell at 0xb7d33eb4: function object at 0xb7d40df4>,)
something1()().__closure__
# 0xb7d4056c
# (<cell at 0xb7d33fec: function object at 0xb7d40e64>, <cell at 0xb7d33efc: function object at 0xb7d40e2c>)
something1()()()
# 0xb7d4056c
# 0xb7d4056c
# 0xb7d40e9c
# 0xb7d40ed4
는 먼저, 함수의 이름은 자신의 몸에서 범위에있다. 둘째, 함수는 함수를 참조 할 경우 정의 된 함수에 대한 클로저를 얻습니다.
함수 이름이 그와 같은 범위에 있다는 것을 알지 못했습니다. 수업에도 마찬가지입니다. 클래스가 함수의 범위 내에서 정의 될 때, 클래스의 메소드 내부 클래스 이름에 대한 참조는과 같이, 그 방법의 기능에 폐쇄에 바운드로 클래스의 원인 :
def test():
class Test(object):
def something(self):
print Test
return Test
test()
# <class '__main__.Test'>
test().something.__func__.__closure__
# (<cell at 0xb7d33c2c: type object at 0x825e304>,)
그러나 폐쇄를 생성 할 수 없기 때문에 기능이없는 경우 다음 오류가 발생합니다.
def test():
class Test(object):
SELF=Test
def something(self):
print Test
return Test
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# File "<stdin>", line 2, in test
# File "<stdin>", line 3, in Test
# NameError: free variable 'Test' referenced before assignment in enclosing scope
좋은 물건!
가 클래스 정의를 다음과 같이 작동 그것은 나에게 이상한. 예기치 않은. –
"[...]베이스가 글로벌 이니?" 예. –
흥미 롭습니다. 함수의 이름이 함수의 몸체의 범위에 있다는 것을 결코 깨닫지 못했을 것입니다. –