I have a situation like so...
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
How can I access the Outer class's method from the Inner class?
You're trying to access Outer's class instance, from inner class instance. So just use factory-method to build Inner instance and pass Outer instance to it.
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()
The methods of a nested class cannot directly access the instance attributes of the outer class.
Note that it is not necessarily the case that an instance of the outer class exists even when you have created an instance of the inner class.
In fact, it is often recommended against using nested classes, since the nesting does not imply any particular relationship between the inner and outer classes.
maybe I'm mad but this seems very easy indeed - the thing is to make your inner class inside a method of the outer class...
def do_sthg(self):
...
def mess_around(self):
outer_class_self = self
class Mooble():
def do_sthg_different(self):
...
outer_class_self.do_sthg()
Plus... "self" is only used by convention, so you could do this:
def do_sthg(self):
...
def mess_around(outer_class_self):
class Mooble():
def do_sthg_different(self):
...
outer_class_self.do_sthg()
It might be objected that you can't then create this inner class from outside the outer class... but this ain't true:
class Bumblebee():
def do_sthg(self):
print "sthg"
def give_me_an_inner_class(outer_class_self):
class Mooble():
def do_sthg_different(self):
print "something diff\n"
outer_class_self.do_sthg()
return Mooble
then, somewhere miles away:
blob = Bumblebee().give_me_an_inner_class()()
blob.do_sthg_different()
even push the boat out a bit and extend this inner class (NB to get super() to work you have to change the class signature of Mooble to class Mooble(object)).
class InnerBumblebeeWithAddedBounce(Bumblebee().give_me_an_inner_class()):
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()
later
mrh1997 raised an interesting point about the non-common inheritance of inner classes delivered using this technique. But it seems that the solution is pretty straightforward:
class Fatty():
def do_sthg(self):
pass
class InnerFatty(object):
pass
def give_me_an_inner_fatty_class(self):
class ExtendedInnerFatty(Fatty.InnerFatty):
pass
return ExtendedInnerFatty
fatty1 = Fatty()
fatty2 = Fatty()
innerFattyClass1 = fatty1.give_me_an_inner_fatty_class()
innerFattyClass2 = fatty2.give_me_an_inner_fatty_class()
print (issubclass(innerFattyClass1, Fatty.InnerFatty))
print (issubclass(innerFattyClass2, Fatty.InnerFatty))
I found this.
Tweaked to suite your question:
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)
I’m sure you can somehow write a decorator for this or something
related: What is the purpose of python's inner classes?
A few years late to the party.... but to expand on #mike rodent's wonderful answer, I've provided my own example below that shows just how flexible his solution is, and why it should be (or should have been) the accepted answer.
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 # ....
)
Output:
Foo Foo World World Foo World
Bar Bar Bar Bar Bar Bar Bar
Doe Doe Appleseed Appleseed John
Again, a wonderful answer, props to you mike!
You can easily access to outer class using metaclass: after creation of outer class check it's attribute dict for any classes (or apply any logic you need - mine is just trivial example) and set corresponding values:
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!
Using this approach, you can easily bind and refer two classes between each other.
I've created some Python code to use an outer class from its inner class, based on a good idea from another answer for this question. I think it's short, simple and easy to understand.
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}
The main code, "production ready" (without comments, etc.). Remember to replace all of each value in angle brackets (e.g. <x>) with the desired value.
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>}
Explanation of how this method works (the basic steps):
Create a function named _subclass_container to act as a wrapper to access the variable self, a reference to the higher level class (from code running inside the function).
Create a variable named _parent_class which is a reference to the variable self of this function, that the sub-classes of _subclass_container can access (avoids name conflicts with other self variables in subclasses).
Return the sub-class/sub-classes as a dictionary/list so code calling the _subclass_container function can access the sub-classes inside.
In the __init__ function inside the higher level class (or wherever else needed), receive the returned sub-classes from the function _subclass_container into the variable subclasses.
Assign sub-classes stored in the subclasses variable to attributes of the higher level class.
A few tips to make scenarios easier:
Making the code to assign the sub classes to the higher level class easier to copy and be used in classes derived from the higher level class that have their __init__ function changed:
Insert before line 12 in the main code:
def _subclass_init(self):
Then insert into this function lines 5-6 (of the main code) and replace lines 4-7 with the following code:
self._subclass_init(self)
Making subclass assigning to the higher level class possible when there are many/unknown quantities of subclasses.
Replace line 6 with the following code:
for subclass_name in list(subclasses.keys()):
setattr(self, subclass_name, subclasses[subclass_name])
Example scenario of where this solution would be useful and where the higher level class name should be impossible to get:
A class, named "a" (class a:) is created. It has subclasses that need to access it (the parent). One subclass is called "x1". In this subclass, the code a.run_func() is run.
Then another class, named "b" is created, derived from class "a" (class b(a):). After that, some code runs b.x1() (calling the sub function "x1" of b, a derived sub-class). This function runs a.run_func(), calling the function "run_func" of class "a", not the function "run_func" of its parent, "b" (as it should), because the function which was defined in class "a" is set to refer to the function of class "a", as that was its parent.
This would cause problems (e.g. if function a.run_func has been deleted) and the only solution without rewriting the code in class a.x1 would be to redefine the sub-class x1 with updated code for all classes derived from class "a" which would obviously be difficult and not worth it.
Do you mean to use inheritance, rather than nesting classes like this? What you're doing doesn't make a heap of sense in Python.
You can access the Outer's some_method by just referencing Outer.some_method within the inner class's methods, but it's not going to work as you expect it will. For example, if you try this:
class Outer(object):
def some_method(self):
# do something
class Inner(object):
def __init__(self):
Outer.some_method()
...you'll get a TypeError when initialising an Inner object, because Outer.some_method expects to receive an Outer instance as its first argument. (In the example above, you're basically trying to call some_method as a class method of Outer.)
Another possibility:
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 ()
What we can do is pass the self variable of Outer Class inside the Inner Class as Class Argument and Under Outer init initialise the Inner Class with Outer self passed into 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
Now After running this function it Works
Expanding on #tsnorri's cogent thinking, that the outer method may be a static method:
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
Now the line in question should work by the time it is actually called.
The last line in the above code gives the Inner class a static method that's a clone of the Outer static method.
This takes advantage of two Python features, that functions are objects, and scope is textual.
Usually, the local scope references the local names of the (textually) current function.
...or current class in our case. So objects "local" to the definition of the Outer class (Inner and some_static_method) may be referred to directly within that definition.
You may create a class, to decorate inner classes. In this case #inner.
Since this a decorator: Outer.A = inner(Outer.A). Once your code requires Outer.A it will be executed inner.__get__ method, which returns the original class (A) with a new attribute set on it: A.owner = Outer.
A classmethod in class A, in this case def add(cls, y=3), may use new attribute owner at return cls.owner.x + y + 1.
The line setattr(owner, name, self.inner), breaks the descriptor because owner.name => Outer.A => A is no longer an instance of the class inner.
Hope this helps.
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
It can be done by parsing the outer class object into inner class.
class Outer():
def __init__(self,userinput):
self.userinput = userinput
def outer_function(self):
self.a = self.userinput + 2
class Inner():
def inner_function(self):
self.b = self.a + 10
after defining this, it need to run the function
m = Outer(3)
m.outer_function()
print (m.a)
#this will output 5
Now it has the variable of outer class.
and then, it need to run inner class functions.
m.Inner.inner_function(m)
The object m of outer class is parsed into the function of inner class (inside the brackets)
Now, the inner class function is accessing self.a from the outer class.
print (m.b)
#this will output 15
It is too simple:
Input:
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()
Output
class A func1
class B func1
I may be trying to do something that is outside of the realm of possibility here, but I figured I would ask first before abandoning hope. So here it goes...
I have 2 classes, A and B. Each class has an arbitrary number of functions. Class B will be instantiated somewhere in Class A and Class A will utilize one of Class B functions via that instantiation. A function in Class B will need to refer to one or more of Class A's functions using it's current instantiation data of Class A.
Class A
#!/usr/bin/python
from classB import classB
class classA(object):
def Apple(self):
print("Inside Apple")
b = classB()
b.Banana()
b.bar()
def foo(self):
print("foo inside apple")
a = classA()
a.Apple()
Class B:
#!/usr/bin/python
import inspect
class classB(object):
def Banana(self):
print("Inside banana")
def bar(self):
print("bar inside banana")
'''
The following lines just show I can get the names of the
calling class and methods.
'''
stack = inspect.stack()
the_class = stack[1][0].f_locals["self"].__class__
the_method = stack[1][0].f_code.co_name
print("Caller Class: {}".format(the_class))
print("Caller Method: {}".format(the_method))
function_name = 'foo'
if hasattr(the_class, function_name):
print("Class {} has method {}".format(the_class,
function_name))
getattr(the_class, function_name)()
I get the following error:
getattr(the_class, function_name)()
TypeError: unbound method foo() must be called with classA instance as first argument (got nothing instead)
Thanks!
As the error suggests, you must build an object of classA (i.e. the_class) before calling getattr on it.
objA = the_class()
But taking a step back, why don't you just pass class A to class B while initializing it?
b = classB(self)
That will allow you to access the exact method of class A that you need.
Else, if method 'foo' in class A is supposed to be a static method, make it so by using #staticmethod decorator.
I read similar questions on SO, but couldn't find answer.
This question is not about accessing instance of outer class or it's method, but about accessing outer class object that should be normal task. As soon as we have __qualname__ that contains information about outer class's name, there is no reason why not to be able dynamically access to outer class object.
This example do job:
class Outer:
class Inner:
#classmethod
def parent_class(cls):
outer_name = cls.__qualname__.split('.')[-2]
outer_cls = globals()[outer_name]
print(outer_cls)
Outer.Inner.parent_class() # <class '__main__.Outer'>
But it wouldn't work in parent_class function placed in another module:
# some.py
class Some:
#classmethod
def parent_class(cls):
outer_name = cls.__qualname__.split('.')[-2]
outer_cls = globals()[outer_name]
print(outer_cls)
# main.py
from some import Some
class Outer:
class Inner(Some):
pass
Outer.Inner.parent_class() # KeyError: 'Outer'
I think it can be solved with Outer's class decorator that appends it's class object to all nested classes, but is there any "clean" way just to get outer class object?
Looks like this solution works in every case:
import sys
class Outer:
class Inner:
#classmethod
def parent_class(cls):
outer_name = cls.__qualname__.split('.')[-2]
outer_module = sys.modules[cls.__module__]
outer_cls = vars(outer_module)[outer_name]
print(outer_cls)
Outer.Inner.parent_class() # <class '__main__.Outer'>
I have the following python snippet:
class myClass:
myVar = 'a'
def __init__(self):
self.myOtherVar = 'b'
myVar = 'c' # Gets assigned but only as a local variable.
print myVar # prints 'a' !
print self.myOtherVar # says 'self' not found
My question is this;
What's the proper way to print the contents of myVar from within myClass and/or re-assign them from init?
The problem you are facing is because you don't understand how the scoping of class declarations work. A class declaration is executed in its own scope. After the execution is completed a new class object is created and the obtained scope is attached to the class as its __dict__.
Note: the class scope is not searched from within the methods scopes! This means that you have to reference class attributes as MyClass.attribute when inside a method definition.
For example:
class MyClass:
var = 1
# we are executing this code as a single block
# so you must reference the variable as is usual
print(var)
# default values are *not* inside the definition.
# they are evaluated in the outer scope, so use plain "var" here
def method(self, a_default=var):
print(a_default)
def other_method(self):
# inside methods you are in a different scope
print(MyClass.var)
# equivalent *if* no "var" instance attributes exists
print(self.var)
Note: since the class doesn't still exist when executing its declaration you cannot refer to MyClass at the "top level" of MyClass declaration:
class MyClass:
var = 1
print(MyClass.var) # error: MyClass still doesn't exist.
A side effect of this, is that the following code:
class MyClass:
x = 1
results = list(i+x for i in range(10))
Produces:
NameError Traceback (most recent call last)
<ipython-input-6-f1d4417b2e52> in <module>()
----> 1 class MyClass:
2 x = 1
3 results = list(i+x for i in range(10))
4
<ipython-input-6-f1d4417b2e52> in MyClass()
1 class MyClass:
2 x = 1
----> 3 results = list(i+x for i in range(10))
4
<ipython-input-6-f1d4417b2e52> in <genexpr>(.0)
1 class MyClass:
2 x = 1
----> 3 results = list(i+x for i in range(10))
4
NameError: name 'x' is not defined
Because generator expressions (and list-comprehensions in python3) are, in fact, considered functions with their own scope. Since the class scope isn't searched from inner function scopes the x cannot be found.
You can word around this using a function definition and default values:
class MyClass:
x = 1
def _make_results(x=x):
return list(i+x for i in range(10))
results = _make_results()
del _make_results # otherwise it would be added as a method.
# or:
results = (lambda x=x: list(i+x for i in range(10)))()
This isn't usually a problem since class definitions rarely contain anything other than method definitions and a few constants.
There are already a few questions on SO about class scopes:
The scope of names defined in class block doesn't extend to the methods' blocks. Why is that?
Short Description of the Scoping Rules?
Nested classes' scope?
Variable scopes in python classes
Why static binding works differently for class and function?
self.var will:
give var in self.__dict__ if present
give var in self.__class__.__dict__ if present
AttributeError
So use this or self.__class__.var if you want to access the static variable minding inheritance. If you extend myClass, the children instances will access the static variable in the child class.
If you want to access the static variable in myClass even when called from descendants, use myClass.var.
As for reassigning them, this must be done explicitly on the class object, or the assignment will just target the instance.
class myClass:
myVar = 'a'
def __init__(self):
self.myOtherVar = 'b'
print myVar # -> 'a'
class EmptyClass: pass
s = EmptyClass()
__init__(s)
myVar = s.myOtherVar
print myVar # -> 'b'
print myClass.myVar # -> 'b'
If I have the following code:
class Foo(object):
bar = 1
def bah(self):
print(bar)
f = Foo()
f.bah()
It complains
NameError: global name 'bar' is not defined
How can I access class/static variable bar within method bah?
Instead of bar use self.bar or Foo.bar. Assigning to Foo.bar will create a static variable, and assigning to self.bar will create an instance variable.
Define class method:
class Foo(object):
bar = 1
#classmethod
def bah(cls):
print cls.bar
Now if bah() has to be instance method (i.e. have access to self), you can still directly access the class variable.
class Foo(object):
bar = 1
def bah(self):
print self.bar
As with all good examples, you've simplified what you're actually trying to do. This is good, but it is worth noting that python has a lot of flexibility when it comes to class versus instance variables. The same can be said of methods. For a good list of possibilities, I recommend reading Michael Fötsch' new-style classes introduction, especially sections 2 through 6.
One thing that takes a lot of work to remember when getting started is that python is not java. More than just a cliche. In java, an entire class is compiled, making the namespace resolution real simple: any variables declared outside a method (anywhere) are instance (or, if static, class) variables and are implicitly accessible within methods.
With python, the grand rule of thumb is that there are three namespaces that are searched, in order, for variables:
The function/method
The current module
Builtins
{begin pedagogy}
There are limited exceptions to this. The main one that occurs to me is that, when a class definition is being loaded, the class definition is its own implicit namespace. But this lasts only as long as the module is being loaded, and is entirely bypassed when within a method. Thus:
>>> class A(object):
foo = 'foo'
bar = foo
>>> A.foo
'foo'
>>> A.bar
'foo'
but:
>>> class B(object):
foo = 'foo'
def get_foo():
return foo
bar = get_foo()
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
class B(object):
File "<pyshell#11>", line 5, in B
bar = get_foo()
File "<pyshell#11>", line 4, in get_foo
return foo
NameError: global name 'foo' is not defined
{end pedagogy}
In the end, the thing to remember is that you do have access to any of the variables you want to access, but probably not implicitly. If your goals are simple and straightforward, then going for Foo.bar or self.bar will probably be sufficient. If your example is getting more complicated, or you want to do fancy things like inheritance (you can inherit static/class methods!), or the idea of referring to the name of your class within the class itself seems wrong to you, check out the intro I linked.
class Foo(object):
bar = 1
def bah(self):
print Foo.bar
f = Foo()
f.bah()
bar is your static variable and you can access it using Foo.bar.
Basically, you need to qualify your static variable with Class name.
You can access class variables by object and directly by class name from the outside or inside of class and basically, you should access class variables directly by class name because if there are the same name class and instance variables, the same name instance variable is prioritized while the same name instance variable is ignored when accessed by object. So, using class name is safer than using object to access class variables.
For example, you can access the class variable by object and directly by class name from the outside of the class as shown below:
class Person:
name = "John" # Class variable
obj = Person()
print(obj.name) # By object
print(Person.name) # By class name
Output:
John
John
But, if you add the same name instance variable as the class variable by object:
class Person:
name = "John" # Class variable
obj = Person()
obj.name = "Tom" # Adds the same name instance variable as class variable
print(obj.name) # By object
print(Person.name) # By class name
Or, if you add the same name instance variable as the class variable by self in __init__():
class Person:
name = "John" # Class variable
def __init__(self, name):
self.name = name # Adds the same name instance variable as class variable
obj = Person("Tom")
print(obj.name) # By object
print(Person.name) # By class name
The same name instance variable is prioritized when accessed by object:
Tom # By object
John # By class name
And, you can also access the class variable by self and directly by class name from the inside of the instance method as shown below:
class Person:
name = "John" # Class variable
def test(self): # Instance method
print(self.name) # By "self"
print(Person.name) # By class name
obj = Person()
obj.test()
Output:
John
John
But, if you add the same name instance variable as the class variable by object:
class Person:
name = "John" # Class variable
def test(self): # Instance method
print(self.name) # By "self"
print(Person.name) # By class name
obj = Person()
obj.name = "Tom" # Adds the same name instance variable as the class variable
obj.test()
Or, if you add the same name instance variable as the class variable by self in __init__():
class Person:
name = "John" # Class variable
def __init__(self, name):
self.name = name # Adds the same name instance variable as the class variable
def test(self): # Instance method
print(self.name) # By "self"
print(Person.name) # Directly by class name
obj = Person("Tom")
obj.test()
The same name instance variable is prioritized when accessed by self:
Tom # By "self"
John # By class name