I would like to replace an object instance by another instance inside a method like this:
class A:
def method1(self):
self = func(self)
The object is retrieved from a database.
It is unlikely that replacing the 'self' variable will accomplish whatever you're trying to do, that couldn't just be accomplished by storing the result of func(self) in a different variable. 'self' is effectively a local variable only defined for the duration of the method call, used to pass in the instance of the class which is being operated upon. Replacing self will not actually replace references to the original instance of the class held by other objects, nor will it create a lasting reference to the new instance which was assigned to it.
As far as I understand, If you are trying to replace the current object with another object of same type (assuming func won't change the object type) from an member function. I think this will achieve that:
class A:
def method1(self):
newObj = func(self)
self.__dict__.update(newObj.__dict__)
It is not a direct answer to the question, but in the posts below there's a solution for what amirouche tried to do:
Python object conversion
Can I dynamically convert an instance of one class to another?
And here's working code sample (Python 3.2.5).
class Men:
def __init__(self, name):
self.name = name
def who_are_you(self):
print("I'm a men! My name is " + self.name)
def cast_to(self, sex, name):
self.__class__ = sex
self.name = name
def method_unique_to_men(self):
print('I made The Matrix')
class Women:
def __init__(self, name):
self.name = name
def who_are_you(self):
print("I'm a women! My name is " + self.name)
def cast_to(self, sex, name):
self.__class__ = sex
self.name = name
def method_unique_to_women(self):
print('I made Cloud Atlas')
men = Men('Larry')
men.who_are_you()
#>>> I'm a men! My name is Larry
men.method_unique_to_men()
#>>> I made The Matrix
men.cast_to(Women, 'Lana')
men.who_are_you()
#>>> I'm a women! My name is Lana
men.method_unique_to_women()
#>>> I made Cloud Atlas
Note the self.__class__ and not self.__class__.__name__. I.e. this technique not only replaces class name, but actually converts an instance of a class (at least both of them have same id()). Also, 1) I don't know whether it is "safe to replace a self object by another object of the same type in [an object own] method"; 2) it works with different types of objects, not only with ones that are of the same type; 3) it works not exactly like amirouche wanted: you can't init class like Class(args), only Class() (I'm not a pro and can't answer why it's like this).
Yes, all that will happen is that you won't be able to reference the current instance of your class A (unless you set another variable to self before you change it.) I wouldn't recommend it though, it makes for less readable code.
Note that you're only changing a variable, just like any other. Doing self = 123 is the same as doing abc = 123. self is only a reference to the current instance within the method. You can't change your instance by setting self.
What func(self) should do is to change the variables of your instance:
def func(obj):
obj.var_a = 123
obj.var_b = 'abc'
Then do this:
class A:
def method1(self):
func(self) # No need to assign self here
In many cases, a good way to achieve what you want is to call __init__ again. For example:
class MyList(list):
def trim(self,n):
self.__init__(self[:-n])
x = MyList([1,2,3,4])
x.trim(2)
assert type(x) == MyList
assert x == [1,2]
Note that this comes with a few assumptions such as the all that you want to change about the object being set in __init__. Also beware that this could cause problems with inheriting classes that redefine __init__ in an incompatible manner.
Yes, there is nothing wrong with this. Haters gonna hate. (Looking at you Pycharm with your in most cases imaginable, there's no point in such reassignment and it indicates an error).
A situation where you could do this is:
some_method(self, ...):
...
if(some_condition):
self = self.some_other_method()
...
return ...
Sure, you could start the method body by reassigning self to some other variable, but if you wouldn't normally do that with other parametres, why do it with self?
One can use the self assignment in a method, to change the class of instance to a derived class.
Of course one could assign it to a new object, but then the use of the new object ripples through the rest of code in the method. Reassiging it to self, leaves the rest of the method untouched.
class aclass:
def methodA(self):
...
if condition:
self = replace_by_derived(self)
# self is now referencing to an instance of a derived class
# with probably the same values for its data attributes
# all code here remains untouched
...
self.methodB() # calls the methodB of derivedclass is condition is True
...
def methodB(self):
# methodB of class aclass
...
class derivedclass(aclass):
def methodB(self):
#methodB of class derivedclass
...
But apart from such a special use case, I don't see any advantages to replace self.
You can make the instance a singleton element of the class
and mark the methods with #classmethod.
from enum import IntEnum
from collections import namedtuple
class kind(IntEnum):
circle = 1
square = 2
def attr(y): return [getattr(y, x) for x in 'k l b u r'.split()]
class Shape(namedtuple('Shape', 'k,l,b,u,r')):
self = None
#classmethod
def __repr__(cls):
return "<Shape({},{},{},{},{}) object at {}>".format(
*(attr(cls.self)+[id(cls.self)]))
#classmethod
def transform(cls, func):
cls.self = cls.self._replace(**func(cls.self))
Shape.self = Shape(k=1, l=2, b=3, u=4, r=5)
s = Shape.self
def nextkind(self):
return {'k': self.k+1}
print(repr(s)) # <Shape(1,2,3,4,5) object at 139766656561792>
s.transform(nextkind)
print(repr(s)) # <Shape(2,2,3,4,5) object at 139766656561888>
Related
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
Say I have a
class A:
def __init__(self, *args):
pass
and I want an decorator that copies A's definition and extend it with the new class.
def decorator(cls): # some decorator here
# make a new class which inherits from A
# return it while preserving the original A
Is that possible? (PS: This is to avoid maintainence problems.)
When you invoke a function using decorator syntax:
#my_decorator_function
class A:
pass
The decorator function's return value will replace the existing definition of A. So if you want it to create a new class and "return it while preserving the original A", you've got a tricky challenge. What you return will replace A, so you need to decide if that should be the original A or the new class. You can put the other one somewhere else.
For instance, this decorator would replace A with a subclass, and the subclass will make the original A class available as a class attribute named _orig:
def class_decorator(cls):
class SubClass(cls):
_orig = cls
# add other stuff here?
return SubClass
You can add extra logic to copy the original class's __name__ and __doc__ into the new class if you want to. You could also turn the logic around, and add SubClass as an attribute of cls before returning the otherwise unmodified cls.
Using #decorator is not the only possible syntax. You can put B = decorator(A) after the class definition.
class A:
...
B = decorator(A)
Now you still have a reference on the undecorated A, and you have a decorated version B.
The other answers have done a good job, but to make it crystal clear why you don't want to do this:
def dec(cls):
new_cls = type(cls.__name__, (cls,), {})
return new_cls
#dec
class A():
pass
Now inspect the method resolution order class A:
>>> A.__mro__
(<class '__main__.A'>, <class '__main__.A'>, <class 'object'>)
>>> classes = A.__mro__
>>> classes[0].__name__
'A'
>>> classes[1].__name__
'A'
TWO class As! Are they the same?
>>> classes[0] is classes[1]
False
Nope; different. The current variable A is pointing to the lowest one of course:
>>> A is classes[0]
True
But now you've lost name-access to the parent. That's usually not optimal.
In short: you are creating a metric ton of confusion and ambiguity for yourself a few months from now when you have forgotten all about what you did. Do something else.
If you really want to, here is an idea for spinning out new subclasses:
def add_babymaker(cls):
'''Adds a method for making new child classes.'''
def babymaker(name=None):
'''Creates a new child class based on the parent class.'''
name = name if name is not None else cls.__name__
new_cls = type(name, (cls,), {})
return new_cls
cls.babymaker = babymaker
return cls
#add_babymaker
class A():
pass
B = A.babymaker('B')
C = A.babymaker('C')
ANew = A.babymaker()
I think I have worked it out. That's not really a good idea.
def make_variant(cls):
suffix='VARIANT'
new = type(cls.__name__+suffix, (cls, ), {})
# new.__repr__ = lambda self: 'HELLO' # Just do whatever needed here
assert cls.__name__ + suffix not in globals()
globals()[cls.__name__+suffix] = new # Think twice about this line
return cls
#make_variant
class A:
def __init__(self):
pass
print(AVARIANT(), A())
I have class:
class A(object):
def do_computing(self):
print "do_computing"
Then I have:
new_class = type('B', (object,), {'a': '#A', 'b': '#B'})
What I want to achieve is to make all methods and properties on class A a member of class B. Class A can have from 0 to N such elements. I want to make them all a member of class B.
So far I get to:
methods = {}
for el in dir(A):
if el.startswith('_'):
continue
tmp = getattr(A, el)
if isinstance(tmp, property):
methods[el] = tmp
if isinstance(tmp, types.MethodType):
methods[el] = tmp
instance_class = type('B', (object,), {'a': '#A', 'b': '#B'})
for name, func in methods.items():
new_method = types.MethodType(func, None, instance_class)
setattr(instance_class, name, new_method)
But then when I run:
instance().do_computing()
I get an error:
TypeError: unbound method do_computing() must be called with A instance as first argument (got B instance instead)
Why I had to do that? We have a lot of legacy code and I need fancy objects that will pretend they are old objects but really.
One more important thing. I cannot use inheritance, to much magic happens in the background.
If you do it like this, it will work:
import types
class A(object):
def do_computing(self):
print "do_computing"
methods = {name:value for name, value in A.__dict__.iteritems()
if not name.startswith('_')}
instance_class = type('B', (object,), {'a': '#A', 'b': '#B'})
for name, func in methods.iteritems():
new_method = types.MethodType(func, None, instance_class)
setattr(instance_class, name, new_method)
instance_class().do_computing()
Unless I'm missing something, you can do this with inheritance:
class B(A):
def __init__(self):
super(B, self).__init__()
Then:
>>> b = B()
>>> b.do_computing()
do_computing
Edit: cms_mgr said the same in the comments, also fixed indentation
are you creating a facade? maybe you want something like this:
Making a facade in Python 2.5
http://en.wikipedia.org/wiki/Facade_pattern
you could also use delegators. here's an example from the wxpython AGW:
_methods = ["GetIndent", "SetIndent", "GetSpacing", "SetSpacing", "GetImageList", "GetStateImageList",
"GetButtonsImageList", "AssignImageList", "AssignStateImageList", "AssignButtonsImageList",
"SetImageList", "SetButtonsImageList", "SetStateImageList", 'other_methods']
def create_delegator_for(method):
"""
Creates a method that forwards calls to `self._main_win` (an instance of :class:`TreeListMainWindow`).
:param `method`: one method inside the :class:`TreeListMainWindow` local scope.
"""
def delegate(self, *args, **kwargs):
return getattr(self._main_win, method)(*args, **kwargs)
return delegate
# Create methods that delegate to self._main_win. This approach allows for
# overriding these methods in possible subclasses of HyperTreeList
for method in _methods:
setattr(HyperTreeList, method, create_delegator_for(method))
Note that these wrap class methods... i.e both functions take a signature like def func(self, some, other, args) and are intended to be called like self.func(some, args). If you want to delegate a class function to a non-class function, you'll need to modify the delegator.
You can inherit from a parent class as such:
class Awesome():
def method_a():
return "blee"
class Beauty(Awesome):
def __init__(self):
self.x = self.method_a()
b = Beauty()
print(b.x)
>>> "blee"
This was freely typed, but the logic is the same none the less and should work.
You can also do fun things with setattr like so:
#as you can see this class is worthless and is nothing
class blee():
pass
b = blee()
setattr(b, "variable_1", "123456")
print(b.variable_1)
>>> 123456
essentially you can assign any object, method to a class instance with setattr.
EDIT: Just realized that you did use setattr, woops ;)
Hope this helps!
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
Consider the following class :
class Token:
def __init__(self):
self.d_dict = {}
def __setattr__(self, s_name, value):
self.d_dict[s_name] = value
def __getattr__(self, s_name):
if s_name in self.d_dict.keys():
return self.d_dict[s_name]
else:
raise AttributeError('No attribute {0} found !'.format(s_name))
In my code Token have some other function (like get_all() wich return d_dict, has(s_name) which tell me if my token has a particular attribute).
Anyway, I think their is a flaw in my plan since it don't work : when I create a new instance, python try to call __setattr__('d_dict', '{}').
How can I achieve a similar behaviour (maybe in a more pythonic way ?) without having to write something like Token.set(name, value) and get(name) each I want to set or get an attribute for a token.
Critics about design flaw and/or stupidity welcome :)
Thank !
You need to special-case d_dict.
Although of course, in the above code, all you do is replicate what any object does with __dict__ already, so it's pretty pointless. Do I guess correctly if you intended to special case some attributes and actally use methods for those?
In that case, you can use properties.
class C(object):
def __init__(self):
self._x = None
#property
def x(self):
"""I'm the 'x' property."""
return self._x
#x.setter
def x(self, value):
self._x = value
#x.deleter
def x(self):
del self._x
The special-casing of __dict__ works like this:
def __init__(self):
self.__dict__['d_dict'] = {}
There is no need to use a new-style class for that.
A solution, not very pythonic but works. As Lennart Regebro pointed, you have to use a special case for d_dict.
class Token(object):
def __init__(self):
super(Token,self).__setattr__('d_dict', {})
def __getattr__(self,name):
return self.a[name]
def __setattr__(self,name,value):
self.a[name] = value
You need to use new style classes.
the problem seems to be in time of evaluation of your code in __init__ method.
You could define __new__ method and initialize d_dict variable there instead of __init__.
Thats a bit hackish but it works, remember though to comment it as after few months it'll be total magic.
>>> class Foo(object):
... def __new__(cls, *args):
... my_cls = super(Foo, cls).__new__(cls, *args)
... my_cls.d_dict = {}
... return my_cls
>>> f = Foo()
>>> id(f.d_dict)
3077948796L
>>> d = Foo()
>>> id(d.d_dict)
3078142804L
Word of explanation why I consider that hackish: call to __new__ returns new instance of class so then d_dict initialised in there is kind of static, but it's initialised with new instance of dictionary each time class is "created" so everything works as you need.
It's worth remembering that __getattr__ is only called if the attribute doesn't exist in the object, whereas __setattr__ is always called.
I think we'll be able to say something about the overall design of your class if you explain its purpose. For example,
# This is a class that serves as a dictionary but also has user-defined methods
class mydict(dict): pass
# This is a class that allows setting x.attr = value or getting x.attr:
class mysetget: pass
# This is a class that allows setting x.attr = value or getting x.attr:
class mygetsethas:
def has(self, key):
return key in self.__dict__
x = mygetsethas()
x.a = 5
print(x.has('a'), x.a)
I think the last class is closest to what you meant, and I also like to play with syntax and get lots of joy from it, but unfortunately this is not a good thing. Reasons why it's not advisable to use object attributes to re-implement dictionary: you can't use x.3, you conflict with x.has(), you have to put quotes in has('a') and many more.