How to access the calling/outer/container python class within current class when added as a property. Consider this example...
class a():
#staticmethod
def meth():
print 'Who called me?'
class b():
my_a = a
class c():
my_a = a
b.my_a.meth()
>> Who called me?
c.my_a.meth()
>> Who called me?
So the question in this example is how to know within a.meth() whether it is being called from class b or class a?
The above are obviously static classes and methods, would the solution to the above also apply to containing objects?
There's no good way to know how the meth() function was accessed. By the time it is called, it is simply a function. If you use #classmethod instead, you will at least get the class passed to you, but in this case, they are both the same a, so I'm not sure you'll get what you want.
You will likely need to do some more bookkeeping to get the information you want.
Related
I have an Object of the following class which inherates from the algorithm class.
class AP(Algorithm):
def evaluate(self, u):
return self.stuff *2 +u
The Algorithm class has a method called StoppingCritiria.
At some point in the project the object objAP = AP() gets created. Later on I can then actually access it.
And at that point in time I want to override the method StoppingCriteria by some function which calls the old StoppingCriteria.
I tried simply
def new_stopping(self):
return super().StoppingCriteria() and custom(self.u)
objAP.StoppingCriteria = newStoppingCriteria
But that did not work. What did work were two rather inconviniend solutions:
New AP class (not desirable since I possibly need to do that for lots of classes)
class AP_custom(AP):
def StoppingCriteria(self):
return super().StoppingCriteria() and custom(self)
Override the Method but not using super but rather copy pasting the code into the new function and adding my code to that. Not desirable since I want to changes in the original method to be applyed to my new function as well.
See Override a method at instance level for many possible solutions. None of them will really work with super though, since you're simply not defining the replacement function in a class. You can define it slightly differently though for it to work:
class Foo:
def bar(self):
print('bar')
f = Foo()
def _bar(self):
type(self).bar(self) # or Foo.bar(self)
print('baz')
from typing import MethodType
f.bar = MethodType(_bar, f)
f.bar() # outputs bar baz
Since you're replacing the method at the instance level, you don't really need to access the method of the super class, you just want to access the method of the class, which still exists in its original form.
so i don't know if what i am asking for is even passable or not, but never the less, i want to do is the following
class A:
def methodA(self):
pass
def methodB(self):
pass
class B:
pass
b = B()
b.methodA()
b.methodB()
but the thing is i might going to have so many number of class B objects this is why i want to assign the "A"s methods to the B class rather than to a single object of class B, i found one solution but the problem with it i have to pass the object as a parameter so for example i am going to have something like this
b.methodA(b)
b.methodB(b)
edited
so the reason why i want to do such thing is, i am making a program that will have two python interpreter whose interpreting the same python file, and i want to share objects between them by only sending/receiving the data inside the object along with the object type, so that the other interpreter will only receive the object data along with its type and make new object from class like the B class, and since both of the interpreters are interpreting the same python file, both of them will have access to the object class, so i don't really have to send the object methods, i can simply make the other interpreter copy it(if it was passable)
edited
so i will need to assign the methods and removing them in run time, and i won't be able to know what classes are the class B are going to copy methods from, until the code execution finishes
You can check Class inheritance or Polymorphism. If you have only one class that should use other's function, Inheritance is better. One will be the child of other. For example, if B will be the child of A, B will have A functions and more. read more at:
Example:
Parent
class Person:
def __init__(self, fname, lname):
self.firstname = fname
self.lastname = lname
def printname(self):
print(self.firstname, self.lastname)
#Use the Person class to create an object, and then execute the printname method:
x = Person("John", "Doe")
x.printname()
Child class:
class Student(Person):
pass
Then you could use Person's functions from Student:
x = Student("Mike", "Olsen")
x.printname()
read more: https://www.w3schools.com/python/python_inheritance.asp
You can pass class A into class B, if what you are doing is to let B have functions in A.
class A():
def method1():
return 'method1'
def method2():
return 'method2'
class B(A):
pass
B.method1()
B.method2()
It's possible to use type in Python to create a new class object, as you probably know:
A = type('A', (object,), {})
a = A() # create an instance of A
What I'm curious about is whether there's any problem with creating different class objects with the same name, eg, following on from the above:
B = type('A', (object,), {})
In other words, is there an issue with this second class object, B, having the same name as our first class object, A?
The motivation for this is that I'd like to get a clean copy of a class to apply different decorators to without using the inheritance approach described in this question.
So I'd like to define a class normally, eg:
class Fruit(object):
pass
and then make a fresh copy of it to play with:
def copy_class(cls):
return type(cls.__name__, cls.__bases__, dict(cls.__dict__))
FreshFruit = copy_class(fruit)
In my testing, things I do with FreshFruit are properly decoupled from things I do to Fruit.
However, I'm unsure whether I should also be mangling the name in copy_class in order to avoid unexpected problems.
In particular, one concern I have is that this could cause the class to be replaced in the module's dictionary, such that future imports (eg, from module import Fruit return the copied class).
There is no reason why you can't have 2 classes with the same __name__ in the same module if you want to and have a good reason to do so.
e.g. In your example from module import Fruit -- python doesn't care at all about the __name__ of the class. It looks in the module's globals for Fruit and imports what it finds there.
Note that, in general, this approach isn't great if you're using super (although the same can be said for class decorators ...):
class A(Base):
def foo(self):
super(A, self).foo()
B = copy_class(A)
In this case, when B.foo is called, it will end up calling super(A, self) which could lead to funky behaviour in a number of circumstances. . .
Why are constructors indeed called "Constructors"? What is their purpose and how are they different from methods in a class?
Also, can there be more that one __init__ in a class? I tried the following, can someone please explain the result?
>>> class test:
def __init__(self):
print "init 1"
def __init__(self):
print "init 2"
>>> s=test()
init 2
Finally, is __init__ an operator overloader?
There is no function overloading in Python, meaning that you can't have multiple functions with the same name but different arguments.
In your code example, you're not overloading __init__(). What happens is that the second definition rebinds the name __init__ to the new method, rendering the first method inaccessible.
As to your general question about constructors, Wikipedia is a good starting point. For Python-specific stuff, I highly recommend the Python docs.
Why are constructors indeed called "Constructors" ?
The constructor (named __new__) creates and returns a new instance of the class. So the C.__new__ class method is the constructor for the class C.
The C.__init__ instance method is called on a specific instance, after it is created, to initialise it before being passed back to the caller. So that method is the initialiser for new instances of C.
How are they different from methods in a class?
As stated in the official documentation __init__ is called after the instance is created. Other methods do not receive this treatment.
What is their purpose?
The purpose of the constructor C.__new__ is to define custom behaviour during construction of a new C instance.
The purpose of the initialiser C.__init__ is to define custom initialisation of each instance of C after it is created.
For example Python allows you to do:
class Test(object):
pass
t = Test()
t.x = 10 # here you're building your object t
print t.x
But if you want every instance of Test to have an attribute x equal to 10, you can put that code inside __init__:
class Test(object):
def __init__(self):
self.x = 10
t = Test()
print t.x
Every instance method (a method called on a specific instance of a class) receives the instance as its first argument. That argument is conventionally named self.
Class methods, such as the constructor __new__, instead receive the class as their first argument.
Now, if you want custom values for the x attribute all you have to do is pass that value as argument to __init__:
class Test(object):
def __init__(self, x):
self.x = x
t = Test(10)
print t.x
z = Test(20)
print t.x
I hope this will help you clear some doubts, and since you've already received good answers to the other questions I will stop here :)
Classes are simply blueprints to create objects from. The constructor is some code that are run every time you create an object. Therefor it does'nt make sense to have two constructors. What happens is that the second over write the first.
What you typically use them for is create variables for that object like this:
>>> class testing:
... def __init__(self, init_value):
... self.some_value = init_value
So what you could do then is to create an object from this class like this:
>>> testobject = testing(5)
The testobject will then have an object called some_value that in this sample will be 5.
>>> testobject.some_value
5
But you don't need to set a value for each object like i did in my sample. You can also do like this:
>>> class testing:
... def __init__(self):
... self.some_value = 5
then the value of some_value will be 5 and you don't have to set it when you create the object.
>>> testobject = testing()
>>> testobject.some_value
5
the >>> and ... in my sample is not what you write. It's how it would look in pyshell...
coonstructors are called automatically when you create a new object, thereby "constructing" the object. The reason you can have more than one init is because names are just references in python, and you are allowed to change what each variable references whenever you want (hence dynamic typing)
def func(): #now func refers to an empty funcion
pass
...
func=5 #now func refers to the number 5
def func():
print "something" #now func refers to a different function
in your class definition, it just keeps the later one
There is no notion of method overloading in Python. But you can achieve a similar effect by specifying optional and keyword arguments
I have a class that's being imported in module_x for instantiation, but first I want to override one of the class's methods to include a specific feature dynamically (inside some middleware that runs before module_x is loaded.
Neither AndiDog's nor Andrew's answer answer your question completely. But they have given the most important tools to be able to solve your problem (+1 to both). I will be using one of their suggestions in my answer:
You will need 3 files:
File 1: myClass.py
class C:
def func(self):
#do something
File 2: importer.py
from myClass import *
def changeFunc():
A = C()
A.func = lambda : "I like pi"
return A
if __name__ == "importer":
A = changeFunc()
File 3: module_x.py
from importer import *
print A.func()
The output of module_x would print "I like pi"
Hope this helps
You should know that each class type (like C in class C: ...) is an object, so you can simply overwrite the class methods. As long as instances don't overwrite their own methods (won't happen too often because that's not really useful for single inntances), each instance uses the methods as inherited from its class type. This way, you can even replace a method after an instance has been created.
For example:
class C:
def m(self):
print "original"
c1 = C()
c1.m() # prints "original"
def replacement(self):
print "replaced!"
C.m = replacement
c1.m() # prints "replaced!"
C().m() # prints "replaced!"
Since every python class is actually a dictionary (not only objects!)
You can easily override class methods by associate them with new function.
class A:
def f(self):
return 5
a = A()
a.f() #5
A.f = lambda self: 10
a.f() #10
You should use it with care. In most cases decorators & proper OO-design will work for you and if you forced to override class method, maybe, you make something wrong.