我有这样的情况......
class Outer(object):
def some_method(self):
# do something
class Inner(object):
def __init__(self):
self.Outer.some_method() # <-- this is the line in question
如何从Outer
班级访问Inner
班级的方法?
修改 - 感谢您的回复。我的结论是,我需要重新评估我是如何设计这个实现的,并提出一种更强大的方法。
答案 0 :(得分:49)
嵌套类的方法不能直接访问外部类的实例属性。
请注意,即使您创建了内部类的实例,也不一定存在外部类的实例。
事实上,通常建议不要使用嵌套类,因为嵌套并不意味着内部类和外部类之间存在任何特定的关系。
答案 1 :(得分:42)
您正在尝试从内部类实例访问Outer的类实例。所以只需使用factory-method构建Inner实例并将Outer实例传递给它。
class Outer(object):
def createInner(self):
return Outer.Inner(self)
class Inner(object):
def __init__(self, outer_instance):
self.outer_instance = outer_instance
self.outer_instance.somemethod()
def inner_method(self):
self.outer_instance.anothermethod()
答案 2 :(得分:24)
也许我很生气,但这看起来确实非常容易 - 那就是让你的内部类在外部类的方法中...
def do_sthg( self ):
...
def messAround( self ):
outerClassSelf = self
class mooble():
def do_sthg_different( self ):
...
outerClassSelf.do_sthg()
Plus ...“self”仅按惯例使用,因此您可以这样做:
def do_sthg( self ):
...
def messAround( outerClassSelf ):
class mooble():
def do_sthg_different( self ):
...
outerClassSelf.do_sthg()
可能有人反对说,你不能从外部类之外创建这个内部类......但事实并非如此:
class Bumblebee():
def do_sthg( self ):
print "sthg"
def giveMeAnInnerClass( outerClassSelf ):
class mooble():
def do_sthg_different( self ):
print "something diff\n"
outerClassSelf.do_sthg()
return mooble
然后,在几英里外的地方:
blob = Bumblebee().giveMeAnInnerClass()()
blob.do_sthg_different()
甚至将船推出一点并扩展这个内部类(NB以获得super()工作你必须将mooble的类签名改为“class mooble(object)”
class InnerBumblebeeWithAddedBounce( Bumblebee().giveMeAnInnerClass() ):
def bounce( self ):
print "bounce"
def do_sthg_different( self ):
super( InnerBumblebeeWithAddedBounce, self ).do_sthg_different()
print "and more different"
ibwab = InnerBumblebeeWithAddedBounce()
ibwab.bounce()
ibwab.do_sthg_different()
<强> 后 强>
mrh1997提出了一个关于使用这种技术传递的内部类的非公共继承的有趣观点。但似乎解决方案非常简单:
class Fatty():
def do_sthg( self ):
pass
class InnerFatty( object ):
pass
def giveMeAnInnerFattyClass(self):
class ExtendedInnerFatty( Fatty.InnerFatty ):
pass
return ExtendedInnerFatty
fatty1 = Fatty()
fatty2 = Fatty()
innerFattyClass1 = fatty1.giveMeAnInnerFattyClass()
innerFattyClass2 = fatty2.giveMeAnInnerFattyClass()
print ( issubclass( innerFattyClass1, Fatty.InnerFatty ))
print ( issubclass( innerFattyClass2, Fatty.InnerFatty ))
答案 3 :(得分:4)
你的意思是使用继承,而不是像这样嵌套类?你正在做的事情并没有在Python中发挥作用。
你可以通过在内部类的方法中引用Outer
来访问Outer.some_method
的some_method,但它不会像你期望的那样工作。例如,如果您尝试这样做:
class Outer(object):
def some_method(self):
# do something
class Inner(object):
def __init__(self):
Outer.some_method()
...初始化Inner
对象时会出现TypeError,因为Outer.some_method
期望接收Outer
实例作为其第一个参数。 (在上面的示例中,您基本上是尝试将some_method
称为Outer
的类方法。)
答案 4 :(得分:3)
我已经创建了一些Python代码来使用内部类来自内部类,基于来自另一个answer的好主意来解决这个问题。我认为它简短易懂。
class higher_level__unknown_irrelevant_name__class:
def __init__(self, ...args...):
...other code...
# Important lines to access sub-classes.
subclasses = self._subclass_container()
self.some_subclass = subclasses["some_subclass"]
del subclasses # Free up variable for other use.
def sub_function(self, ...args...):
...other code...
def _subclass_container(self):
_parent_class = self # Create access to parent class.
class some_subclass:
def __init__(self):
self._parent_class = _parent_class # Easy access from self.
# Optional line, clears variable space, but SHOULD NOT BE USED
# IF THERE ARE MULTIPLE SUBCLASSES as would stop their parent access.
# del _parent_class
class subclass_2:
def __init__(self):
self._parent_class = _parent_class
# Return reference(s) to the subclass(es).
return {"some_subclass": some_subclass, "subclass_2": subclass_2}
主要代码,“生产就绪”(没有评论等)。请记住使用所需的值替换尖括号中的所有值(例如<x>
)。
class <higher_level_class>:
def __init__(self):
subclasses = self._subclass_container()
self.<sub_class> = subclasses[<sub_class, type string>]
del subclasses
def _subclass_container(self):
_parent_class = self
class <sub_class>:
def __init__(self):
self._parent_class = _parent_class
return {<sub_class, type string>: <sub_class>}
创建一个名为_subclass_container
的函数作为包装器来访问变量self
,这是对更高级别类的引用(来自函数内部运行的代码)。
创建一个名为_parent_class
的变量,它是对此函数的变量self
的引用,_subclass_container
的子类可以访问(避免与其他名称冲突)子类中的self
个变量。)
将子类/子类作为字典/列表返回,因此调用_subclass_container
函数的代码可以访问其中的子类。
在更高级别类(或其他需要的地方)内的__init__
函数中,将函数_subclass_container
中返回的子类接收到变量subclasses
。< / p>
将存储在subclasses
变量中的子类分配给更高级别的属性。
使代码将子类分配给更高级别的类更容易复制,并在从更高级别类派生的类中使用 __init__
函数已更改:强>
在主码的第12行之前插入:
def _subclass_init(self):
然后插入此功能行5-6(主代码)并用以下代码替换4-7行:
self._subclass_init(self)
当有许多/未知数量的子类时,可以将子类分配给更高级别的类。
使用以下代码替换第6行:
for subclass_name in list(subclasses.keys()):
setattr(self, subclass_name, subclasses[subclass_name])
创建名为“a”(class a:
)的类。它有需要访问它的子类(父类)。一个子类称为“x1”。在此子类中,运行代码a.run_func()
。
然后从类“a”(class b(a):
)创建另一个名为“b”的类,派生。之后,一些代码运行b.x1()
(调用b的子函数“x1”,派生子类)。该函数运行a.run_func()
,调用类“a”的函数“run_func”,不其父级的函数“run_func”,“b”(因为它应该),因为函数在类“a”中定义的类被设置为引用类“a”的函数,因为它是它的父类。
这会导致问题(例如,如果函数a.run_func
已被删除)并且没有重写类a.x1
中的代码的唯一解决方案是重新定义子类x1
并更新从类“a”派生的所有类的代码,显然很难并且不值得。
答案 5 :(得分:2)
另一种可能性:
class _Outer (object):
# Define your static methods here, e.g.
@staticmethod
def subclassRef ():
return Outer
class Outer (_Outer):
class Inner (object):
def outer (self):
return _Outer
def doSomething (self):
outer = self.outer ()
# Call your static mehthods.
cls = outer.subclassRef ()
return cls ()
答案 6 :(得分:2)
您可以使用元类轻松访问外部类:创建外部类后,检查它的任何类的属性dict(或应用您需要的任何逻辑 - 我只是简单的例子)并设置相应的值:
import six
import inspect
# helper method from `peewee` project to add metaclass
_METACLASS_ = '_metaclass_helper_'
def with_metaclass(meta, base=object):
return meta(_METACLASS_, (base,), {})
class OuterMeta(type):
def __new__(mcs, name, parents, dct):
cls = super(OuterMeta, mcs).__new__(mcs, name, parents, dct)
for klass in dct.values():
if inspect.isclass(klass):
print("Setting outer of '%s' to '%s'" % (klass, cls))
klass.outer = cls
return cls
# @six.add_metaclass(OuterMeta) -- this is alternative to `with_metaclass`
class Outer(with_metaclass(OuterMeta)):
def foo(self):
return "I'm outer class!"
class Inner(object):
outer = None # <-- by default it's None
def bar(self):
return "I'm inner class"
print(Outer.Inner.outer)
>>> <class '__main__.Outer'>
assert isinstance(Outer.Inner.outer(), Outer)
print(Outer().foo())
>>> I'm outer class!
print(Outer.Inner.outer().foo())
>>> I'm outer class!
print(Outer.Inner().outer().foo())
>>> I'm outer class!
print(Outer.Inner().bar())
>>> I'm inner class!
使用这种方法,您可以轻松地在彼此之间绑定和引用两个类。
答案 7 :(得分:1)
我找到this。
调整以解决您的问题,答案是:
class Outer(object):
def some_method(self):
# do something
class _Inner(object):
def __init__(self, outer):
outer.some_method()
def Inner(self):
return _Inner(self)
我相信你可以以某种方式为这个或者其他东西写一个装饰者:) /编辑:kinda
答案 8 :(得分:1)
扩展@ tsnorri的有力思考,外部方法可能是static method:
md-icon
现在,有问题的行应该在实际调用时起作用。
上面代码中的最后一行为Inner类提供了一个静态方法,它是外部静态方法的克隆。
这利用了两个Python功能,functions are objects和scope is textual。
在我们的案例中,通常,本地范围引用(文本)当前函数的本地名称。
...或当前的类。所以对象&#34;本地&#34;外部类的定义(class Outer(object):
@staticmethod
def some_static_method(self):
# do something
class Inner(object):
def __init__(self):
self.some_static_method() # <-- this will work later
Inner.some_static_method = some_static_method
和Inner
)可以在该定义中直接引用。
答案 9 :(得分:1)
晚了几年。...,但为了进一步探讨@mike rodent
的精彩答案,我在下面提供了自己的示例,展示了他的解决方案有多灵活是,以及为什么它应该(或者应该已经)被接受。
Python 3.7
class Parent():
def __init__(self, name):
self.name = name
self.children = []
class Inner(object):
pass
def Child(self, name):
parent = self
class Child(Parent.Inner):
def __init__(self, name):
self.name = name
self.parent = parent
parent.children.append(self)
return Child(name)
parent = Parent('Bar')
child1 = parent.Child('Foo')
child2 = parent.Child('World')
print(
# Getting its first childs name
child1.name, # From itself
parent.children[0].name, # From its parent
# Also works with the second child
child2.name,
parent.children[1].name,
# Go nuts if you want
child2.parent.children[0].name,
child1.parent.children[1].name
)
print(
# Getting the parents name
parent.name, # From itself
child1.parent.name, # From its children
child2.parent.name,
# Go nuts again if you want
parent.children[0].parent.name,
parent.children[1].parent.name,
# Or insane
child2.parent.children[0].parent.children[1].parent.name,
child1.parent.children[1].parent.children[0].parent.name
)
# Second parent? No problem
parent2 = Parent('John')
child3 = parent2.Child('Doe')
child4 = parent2.Child('Appleseed')
print(
child3.name, parent2.children[0].name,
child4.name, parent2.children[1].name,
parent2.name # ....
)
输出:
Foo Foo World World Foo World
Bar Bar Bar Bar Bar Bar Bar
Doe Doe Appleseed Appleseed John
再一次,一个很棒的答案,给你的麦克道具!
答案 10 :(得分:0)
您可以创建一个类来装饰内部类。在这种情况下,@ inner。
因此,它是一个装饰器:Outer.A = inner(Outer.A)。一旦您的代码需要Outer.A,它将执行inner.__get__
方法,该方法将返回设置了新属性的原始类(A):A.owner = Outer。
类A中的类方法,在这种情况下为def add(cls, y=3)
,可以在owner
处使用新属性return cls.owner.x + y + 1
。
setattr(owner, name, self.inner)
行中断了描述符,因为owner.name => Outer.A => A
不再是内部类的实例。
希望这会有所帮助。
class inner:
def __init__(self, inner):
self.inner = inner
def __get__(self, instance, owner):
print('__get__ method executed, only once... ')
name = self.inner.__name__
setattr(self.inner, 'owner', owner)
setattr(owner, name, self.inner) # breaks descriptor
return self.inner #returns Inner
class Outer:
x = 1
@inner
class A:
@classmethod
def add(cls, y=3):
return cls.owner.x + y + 1
print(Outer.A.add(0)) # First time executes inner.__get__ method
print(Outer.A.add(0)) # Second time not necessary.
>> __get__ method executed, only once...
>> 2
>> 2
答案 11 :(得分:0)
我们可以做的是将Outer类的self变量作为Class Argument传入Inner Class内部,在Outer init下初始化Inner Class,Outer self传入Inner
class Outer:
def __init__(self):
self.somevalue=91
self.Inner=self.Inner(self)
def SomeMethod(self):
print('This is Something from Outer Class')
class Inner:
def __init__(self,Outer)
self.SomeMethod=Outer.SomeMethod
self.somevalue=Outer.somevalue
def SomeAnotherMethod(self):
print(self.somevalue)
self.SomeMethod()
>>>f=Outer()
>>>f.Inner.SomeAnotherMethod()
91
This is Something from Outer Class
现在运行此功能后它可以工作
答案 12 :(得分:-3)
这太简单了:
class A:
def __init__(self):
pass
def func1(self):
print('class A func1')
class B:
def __init__(self):
a1 = A()
a1.func1()
def func1(self):
print('class B func1')
b = A.B()
b.func1()
A类func1
B类func1