Apologies if this doesn't make sense, i'm not much of an experienced programmer.
Consider the following code:
import mymodule
class MyClass:
def __init__(self):
self.classInstance = myModule.classInstance()
and then ......
from mymodule import classInstance
class MyClass(classInstance):
def __init__(self):
pass
If I just wanted to use the one classInstance in MyClass, is it ok to import the specific class from the module and have MyClass inherit this class ?
Are there any best practices, or things I should be thinking about when deciding between these two methods ?
Many thanks
Allow me to propose a different example.
Imagine to have the class Vector.
Now you want a class Point. Point can be defined with a vector but maybe it has other extra functionalities that Vector doesn't have.
In this case you derive Point from Vector.
Now you need a Line class.
A Line is not a specialisation of any of the above classes so probably you don't want to derive it from any of them.
However Line uses points. In this case you might want to start you Line class this way:
class Line(object):
def __init__(self):
self.point1 = Point()
self.point2 = Point()
Where point will be something like this:
class Point(Vector):
def __init__(self):
Vector.__init__(self)
So the answer is really: Depends what you need to do, but when you have a clear idea of what you are coding, than choosing between sub-classing or not becomes obvious.
I hope it helped.
You make it sound like you're trying to "choose between" those two approaches, but they do completely different things. The second one defines a class that inherits from a class (confusingly) called classInstance. The first one defines a class called MyClass (not inheriting from anything except the base obect type) that has an instance variable called self.classInstance, which happens to be set to an instance of the classInstance class.
Why are you naming your class classInstance?
Related
Is it possible in python for a nested class to extend its parent?
Like this:
class Parent:
class Child(Parent):
pass
child = Parent.Child()
Is it possible to do this in the opposite direction?
Like this:
class Parent(Child):
class Child:
pass
parent = Parent()
From what I know this is not possible, even with from __future__ import annotations.
The best known way around this is just not to make nested classes.
Important:
The purpose of this question is to make it clear if this is even possible in the python language.
There is no "final goal", objectives to be accomplished with this approach or justification for it.
Don't spam in the comments/answers about "how bad this code is".
No and Yes.
No, because when you inherit from a class, that class must be defined before you can inherit from it. Neither of your code examples will work due to this.
Yes, because Python is a dynamic language and you can change (monkey-patch) the base classes even after defining them:
class Temp:
pass
# example 1
class Parent:
class Child(Temp):
pass
Parent.Child.__bases__ = (Parent,)
# example 2
class Parent(Temp):
class Child:
pass
Parent.__bases__ = (Parent.Child,)
Why use the Temp class?
Classes automatically inherit from object. Due to a bug (https://bugs.python.org/issue672115), we cannot change __bases__ if a class inherits from object. Hence, we inherit from a temporary (Temp) class to avoid that issue.
What are the differences between importing a class from a file and using super() in python?
Import: # I understand that this will import all the functions and init from a class to another class in a file when trigger the below code;
from something import Some
super(): # I understand that this also will inherit all the functions and init from a class to another class in a file. **Ain't this technically the same as importing?
super(xx, self).__init__() or super().__init__() or super()
Can any python experts shows some example? I have recently read some codes online and they used both of this, my question is since both do almost the same thing(to my understanding) then why dont just use either one for all files and why need to use both? If possible, can share some examples?
You'll need to understand a bit of Object-oriented programming principles to understand super.
In general, when you are importing a module, that module becomes available for your current function/class.
By using Super you satisfy inheritance; facilitating your current class's this to have references to all attributes of its parent(s). If you are just developing some functions, you will not need super. This is strictly an object-oriented paradigm.
from xyz import abc
def some_function():
# here you can use abc's attributes by explicit invocation.
x = abc.x
# Or call functions.
abc.some_function()
When you're dealing with classes, super does the magic of facilitating inheritance.
class Parent_Class(object):
def __init__(self):
super(Parent_Class, self).__init__()
def parent_method(self):
print('This is a parent method')
class Child_Class(Parent_Class):
def __init__(self):
super(Child_Class, self).__init__()
def child_method(self):
# Because of super, self of child class is aware of all its parent's methods and properties.
self.parent_method()
import is used for importing module
__init__() is a class method, which is invoked when a new instance of a class is instantiated
This is 2 different thing
EDIT: I've made this edit to clarify the answer for you, since I assume you are not familiar with OOP. TL;DR: These two terms are completely different, they relate to two separate things. super() call a class's parent method, while import import a module
we can still import the module form file B into file A and in file A
we can still use the methods from the file B in file A right?
Right.
what makes it different than super() which calls the methods from file B when used in file A
First, you only encounter super() in subclass (lets say class B) of a class(lets say class A). You access A's method through B's instance via super(). Let see this example: You have 2 file, A.py and B.py, each define A and B:
In A.py, you define class A
class A(object):
def __init__(self):
print("Instantiate class A")
def printA(self):
print("AAAAAAAAAAAAAA")
In B.py, you define class B:
from A import A # you need this import for `B.py` to know what is `A`
class B(A): # Mean B inherit A
def __init__(self):
super(B, self).__init__() # This line all its parent's method (`__init__()`)
def printB(self):
print("BBBBBBBBBBBB")
super(B, self).printA() # This line all its parent's method (`printA`)
# And you instantiate a `B` instance, then call a method of it, which call its super method `printA`
b = B()
b.printB()
Output is (note that `init():
Instantiate class A
BBBBBBBBBBBB
AAAAAAAAAAAAAA
To conclude, I suggest you to read some material about OOP. You will clearly see the differences btw these two things. Good luck. I hope this help!
The import statement is used to import modules into modules. The super callable is used to delegate from subclass implementation to superclass implementation.
Notably, import connects between fixed equals whereas super connects in a dynamic hierarchy.
The point of import is to make a specific module or its content available in another module.
# moda.py
def foo(who):
print(who, "called '%s.foo'" % __name__)
# modb.py
import moda
moda.foo(__name__)
Note that importing uses a qualified name that uniquely identifies the target. At any time, the name used in an import can refer to only one specific entity. That means that import couples strongly - the target is fully identified and cannot change after the import.
The point of super is to access the closest superclass implementation in a subclass implementation.
class A:
def call(self, who):
print(who, "called '%s.call'" % __class__, "on self of class", self.__class__)
class Alpha(A):
def call(self, who):
super(Alpha, self).call(who)
print("... via '%s.call'" % __class__)
Note that super only work with local information - super does only identify the source, not the target. As such, the target is dynamically bound and not uniquely identifiable. That means that super couples weakly - the target is relatively defined and can only be resolved at runtime.
class Alpher(A):
def call(self, who):
print("'%s.call' sneakily intercepts the call..." % __class__)
super(Alpher, self).call(who)
class Better(Alpha, Alpher):
pass
The above injects Alpher into the relation from Alpha to A without modifying either of the two.
>>> Better().call('Saul')
'<class '__main__.Alpher'>.call' sneakily intercepts the call...
Saul called <class '__main__.A'>.call on self of class <class '__main__.Better'>
...via '<class '__main__.Alpha'>.call'
Python 3.6
I'm trying to modify the behavior of a third party library.
I don't want to directly change the source code.
Considering this code below:
class UselessObject(object):
pass
class PretendClassDef(object):
"""
A class to highlight my problem
"""
def do_something(self):
# Allot of code here
result = UselessObject()
return result
I'd like to substitute my own class for UselessObject
I'd like to know if using a metaclass in my module to intercept the creation of UselessObject is a valid idea?
EDIT
This answer posted by Ashwini Chaudhary on the same question, may be of use to others. As well as the below answer.
P.S. I also discovered that 'module' level __metaclass__ does't work in python 3. So my initial question of it 'being a valid idea' is False
FWIW, here's some code that illustrates Rawing's idea.
class UselessObject(object):
def __repr__(self):
return "I'm useless"
class PretendClassDef(object):
def do_something(self):
return UselessObject()
# -------
class CoolObject(object):
def __repr__(self):
return "I'm cool"
UselessObject = CoolObject
p = PretendClassDef()
print(p.do_something())
output
I'm cool
We can even use this technique if CoolObject needs to inherit UselessObject. If we change the definition of CoolObject to:
class CoolObject(UselessObject):
def __repr__(self):
s = super().__repr__()
return "I'm cool, but my parent says " + s
we get this output:
I'm cool, but my parent says I'm useless
This works because the name UselessObject has its old definition when the CoolObject class definition is executed.
This is not a job for metaclasses.
Rather, Python allows you to do this through a technique called "Monkeypatching", in which you, at run time, substitute one object for another in run time.
In this case, you'd be changing the thirdyparty.UselessObject for your.CoolObject before calling thirdyparty.PretendClassDef.do_something
The way to do that is a simple assignment.
So, supposing the example snippet you gave on the question is the trirdyparty module, on the library, your code would look like:
import thirdyparty
class CoolObject:
# Your class definition here
thirdyparty.UselesObject = Coolobject
Things you have to take care of: that you change the object pointed by UselessObject in the way it is used in your target module.
If for example, your PretendedClassDef and UselessObject are defined in different modules, you have to procees in one way if UselessObject is imported with from .useless import UselessObject (in this case the example above is fine), and import .useless and later uses it as useless.UselessObject - in this second case, you have to patch it on the useless module.
Also, Python's unittest.mock has a nice patch callable that can properly perform a monkeypatching and undo it if by some reason you want the modification to be valid in a limited scope, like inside a function of yours, or inside a with block. That might be the case if you don't want to change the behavior of the thirdyparty module in other sections of your program.
As for metaclasses, they only would be of any use if you would need to change the metaclass of a class you'd be replacing in this way - and them they only could have any use if you'd like to insert behavior in classes that inherit from UselessObject. In that case it would be used to create the local CoolObject and you'd still perform as above, but taking care that you'd perform the monkeypatching before Python would run the class body of any of the derived classes of UselessObject, taking extreme care when doing any imports from the thirdparty library (that would be tricky if these subclasses were defined on the same file)
This is just building on PM 2Ring's and jsbueno's answers with more contexts:
If you happen to be creating a library for others to use as a third-party library (rather than you using the third-party library), and if you need CoolObject to inherit UselessObject to avoid repetition, the following may be useful to avoid an infinite recursion error that you might get in some circumstances:
module1.py
class Parent:
def __init__(self):
print("I'm the parent.")
class Actor:
def __init__(self, parent_class=None):
if parent_class!=None: #This is in case you don't want it to actually literally be useless 100% of the time.
global Parent
Parent=parent_class
Parent()
module2.py
from module1 import *
class Child(Parent):
def __init__(self):
print("I'm the child.")
class LeadActor(Actor): #There's not necessarily a need to subclass Actor, but in the situation I'm thinking, it seems it would be a common thing.
def __init__(self):
Actor.__init__(self, parent_class=Child)
a=Actor(parent_class=Child) #prints "I'm the child." instead of "I'm the parent."
l=LeadActor() #prints "I'm the child." instead of "I'm the parent."
Just be careful that the user knows not to set a different value for parent_class with different subclasses of Actor. I mean, if you make multiple kinds of Actors, you'll only want to set parent_class once, unless you want it to change for all of them.
Suppose I have a simple class like this:
class Class1(object):
def __init__(self, property):
self.property = property
def method1(self):
pass
An instances of Class1 returns a value that can be used in other class:
class Class2(object):
def __init__(self, instance_of_class1, other_property):
self.other_property = other_property
self.instance_of_class1 = instance_of_class1
def method1(self):
# A method that uses self.instance_of_class1.property and self.other_property
This is working. However, I have the feeling that this is not a very common approach and maybe there are alternatives. Having said this, I tried to refactor my classes to pass simpler objects to Class2, but I found that passing the whole instance as an argument actually simplifies the code significantly. In order to use this, I have to do this:
instance_of_class1 = Class1(property=value)
instance_of_class2 = Class2(instance_of_class1, other_property=other_value)
instance_of_class2.method1()
This is very similar to the way some R packages look like. Is there a more "Pythonic" alternative?
There's nothing wrong with doing that, though in this particular example it looks like you could just as easily do
instance_of_class2 = Class2(instance_of_class1.property, other_property=other_value).
But if you find you need to use other properties/methods of Class1 inside of Class2, just go ahead and pass the whole Class1 instance into Class2. This kind of approach is used all the time in Python and OOP in general. Many common design patterns call for a class to take an instance (or several instances) of other classes: Proxy, Facade, Adapter, etc.
I have that strange feeling this is an easy question.
I want to be able to "alias" a class type so i can swap out the implementation at a package level. I dont want to have X amount of import X as bah scattered throughout my code...
Aka. How can I do something like the below:
class BaseClass(object):
def __init__(self): pass
def mymthod(self): pass
def mymthod1(self): pass
def mymthod2(self): pass
class Implementation(BaseClass):
def __init__(self):
BaseClass.__init__()
Seperate package...
#I dont want thse scattered through out modules,
#i want them in one place where i can change one and change implementations
#I tried putting it in the package init but no luck
import Implementation as BaseClassProxy
class Client(BaseClassImpl):
def __init__(self):
BaseClassImpl.__init__(self)
In any file (where this fits best is up to you, probably wherever Implementation was defined):
BaseClassProxy = Implementation
Since classes are first class objects in Python, you can pretty much bind them to any variable and use them the same way. In this case, you can make an alias for the class.
just put something like
BaseClassProxy = Implementation
in the module, then do:
from module import BaseClassProxy