I'm trying to create a class object inside the class itself, something like this:
class Motor:
#other code here
def function(self):
x = Motor()
This works and runs correctly, but if I use inheritance to create another class as a daughter of this one (e.g. Car(Motor)), the Car.function() doesn't work properly because it's creating an object of type Motor, not Car. Is there any other way I could do this?
Thanks!!
You'll want to receive the class to instantiate as an argument to the method, rather than hard-coding the class name.
class Motor:
#classmethod
def function(cls):
x = cls()
...
If this is really something that needs to be an instance method, you can use type(self) instead.
class Motor:
def function(self):
x = type(self)()
Related
I read on that instance methods can only be called by creating an instance (object) of the class. But it appears that I can call one without doing so. Check the code below:
class Test:
def func(self): #Instance Method
print(6)
Test.func(Test) # Here I am calling an instance method without creating an instance of class. How?
Please let me know what is happening behind the scenes.
Your code works because you feed as self argument the class itself.
Your function will work as long as you use self as class type and not as class instance, which is very bad practice.
I suggest to use staticmethods for such purposes:
class Test:
#staticmethod
def func():
print(6)
Test.func()
or #classmethod:
class Test:
#classmethod
def func(cls):
print(6)
Test.func()
Output:
6
I am given a designated factory of A-type objects. I would like to make a new version of A-type objects that also have the methods in a Mixin class. For reasons that are too long to explain here, I can't use class A(Mixin), I have to use the A_factory. Below I try to give a bare bones example.
I thought naively that it would be sufficient to inherit from Mixin to endow A-type objects with the mixin methods, but the attempts below don't work:
class A: pass
class A_factory:
def __new__(self):
return A()
class Mixin:
def method(self):
print('aha!')
class A_v2(Mixin): # attempt 1
def __new__(cls):
return A_factory()
class A_v3(Mixin): # attempt 2
def __new__(cls):
self = A_factory()
super().__init__(self)
return self
In fact A_v2().method() and A_v3().method() raises AttributeError: 'A' object has no attribute 'method'.
What is the correct way of using A_factory within class A_vn(Mixin) so that A-type objects created by the factory inherit the mixin methods?
There's no obvious reason why you should need __new__ for what you're showing here. There's a nice discussion here on the subject: Why is __init__() always called after __new__()?
If you try the below it should work:
class Mixin:
def method(self):
print('aha!')
class A(Mixin):
def __init__(self):
super().__init__()
test = A()
test.method()
If you need to use a factory method, it should be a function rather than a class. There's a very good discussion of how to use factory methods here: https://realpython.com/factory-method-python/
Let's say I am inside an object (object1) and I want to pass its reference to another object (object2) I created inside it.
Inside object1:
# ...
self.object2Reference = object2(self)
# ...
Code of object2:
class object2:
def __init__(self, object1Reference)
self.object1Reference = object1Reference
# ...
It fails with the following error:
self.object2 = object2()
TypeError: __init__() takes exactly 2 arguments (1 given)
I want to be able to access variables and methods of object1 from inside object2.
Edit: self.object2Reference = object2(self) happens inside a method that is started via new thread, so self was not what I expected at this time. I tried to make this example as small and simple as possible but forgot one imported aspect doing so. My bad. But the answer is good and complete anyways and also shows the use of inheritance.
To pass the current object to another object it declares for use.
The code:
class Object2:
def __init__(self, object1):
self.object1 = object1
self.object1.print_something()
class Object1:
def __init__(self):
self.object2 = Object2(self)
def print_something(self):
print("I am an object1")
x = Object1()
Seems to be what you are trying to do. This works for me, and prints out "I am an object1". If you structure your code like above with your two objects it should work as you hope.
Edit:
If you are hoping to do inheritance instead of just use the object
I also wanted to add, that if you are looking for inheritance instead of just being able to access object1, you can do that like this:
class Object1:
def print_something(self):
print("I am an object1 method inherited by object 2")
class Object2(Object1):
def __init__(self):
super().__init__()
self.print_something()
x = Object2()
With this, Object2 will inherit any Object1 methods it does not implement. super().__init__() and putting (Object1) in the class declaration are the only two changes you make here, to then be able to use any Object1 method from self.
I have a function which return instances of the class Parent:
def generateParent():
do_stuff
return Parent(some_parameters)
Now I want to init a subclass of Parent with the results of a call to generateParent():
class Child(Parent):
def __new__():
return generateParent(some_other_parameters)
The problem is, when I override some methods from Parent in Child and then call them in instances of Child in my program, the original Parent method gets called instead of the new one from Child. Am I doing something wrong here? Am I using the correct design here for my task?
EDIT: I don't have access neither to Parent nor generateParent()
Solution(thanks to #Paul McGuire's answer):
class Child(object):
def __init__(self):
self.obj = generateParent()
def __getattr__(self, attr):
return getattr(self.obj, attr)
Since generateParent is not your code, then instead of inheritance, you might want to use containment and delegation. That is, instead of defining a subclass, define a wrapper class that contains the generated object, forwards method calls to it when needed, but can add new behavior or modified behavior in the wrapper.
In this question, the OP had a similar situation, having a class generated in a libary, but wanting to extend the class and/or modify some behavior of the class. Look at how I added a wrapper class in that question, and you might consider doing something similar here.
Here's one way to do it:
def generateChild(params):
p = generateParent(params)
p.__class__ = Child
return p
class Child(Parent):
# put method overrides etc here
childinstance = generateChild(some_params)
Perhaps you want generateParent to be able to make instances of other classes:
def generateParent(cls=Parent):
do_stuff
return cls(some_parameters)
Now this will make a Child object:
child = generateParent(Child)
Or perhaps you want Parent and all of its derived classes to use common initialization code?
class Parent(object):
def __init__(self):
do_stuff
# init from some_parameters
class Child(Parent):
# blah..
Make your Child object able to copy information from a created Parent object:
class Child(Parent):
def __init__(self):
model_parent = generateParent()
self.a = model_parent.a
self.b = model_parent.b
# etc.
I have the following structure:
class foo(object):
class bar(object):
def __init__(self, parent):
self._parent=parent #this
def worker(self):
return self._parent.name
def __init__(self, name):
self.name=name
def giveNamePointer(self):
return self.bar(self) #and this
Which works fine, however I was wondering if there is an implicit or easier way to get the reference to the creating instance in the special case, that the created instance is a class defined in the creating class.
edit: could this help me :implementing descriptiors and if so how?
No. Explicit is better than implicit.
(There's nothing special about defining a class inside another class.)