Is there a way to circumvent the constructor __init__ of a class in python?
Example:
class A(object):
def __init__(self):
print "FAILURE"
def Print(self):
print "YEHAA"
Now I would like to create an instance of A. It could look like this, however this syntax is not correct.
a = A
a.Print()
EDIT:
An even more complex example:
Suppose I have an object C, which purpose it is to store one single parameter and do some computations with it. The parameter, however, is not passed as such but it is embedded in a huge parameter file. It could look something like this:
class C(object):
def __init__(self, ParameterFile):
self._Parameter = self._ExtractParamterFile(ParameterFile)
def _ExtractParamterFile(self, ParameterFile):
#does some complex magic to extract the right parameter
return the_extracted_parameter
Now I would like to dump and load an instance of that object C. However, when I load this object, I only have the single variable self._Parameter and I cannot call the constructor, because it is expecting the parameter file.
#staticmethod
def Load(file):
f = open(file, "rb")
oldObject = pickle.load(f)
f.close()
#somehow create newObject without calling __init__
newObject._Parameter = oldObject._Parameter
return newObject
In other words, it is not possible to create an instance without passing the parameter file. In my "real" case, however, it is not a parameter file but some huge junk of data I certainly not want to carry around in memory or even store it to disc.
And since I want to return an instance of C from the method Load I do somehow have to call the constructor.
OLD EDIT:
A more complex example, which explains why I am asking the question:
class B(object):
def __init__(self, name, data):
self._Name = name
#do something with data, but do NOT save data in a variable
#staticmethod
def Load(self, file, newName):
f = open(file, "rb")
s = pickle.load(f)
f.close()
newS = B(???)
newS._Name = newName
return newS
As you can see, since data is not stored in a class variable I cannot pass it to __init__. Of course I could simply store it, but what if the data is a huge object, which I do not want to carry around in memory all the time or even save it to disc?
You can circumvent __init__ by calling __new__ directly. Then you can create a object of the given type and call an alternative method for __init__. This is something that pickle would do.
However, first I'd like to stress very much that it is something that you shouldn't do and whatever you're trying to achieve, there are better ways to do it, some of which have been mentioned in the other answers. In particular, it's a bad idea to skip calling __init__.
When objects are created, more or less this happens:
a = A.__new__(A, *args, **kwargs)
a.__init__(*args, **kwargs)
You could skip the second step.
Here's why you shouldn't do this: The purpose of __init__ is to initialize the object, fill in all the fields and ensure that the __init__ methods of the parent classes are also called. With pickle it is an exception because it tries to store all the data associated with the object (including any fields/instance variables that are set for the object), and so anything that was set by __init__ the previous time would be restored by pickle, there's no need to call it again.
If you skip __init__ and use an alternative initializer, you'd have a sort of a code duplication - there would be two places where the instance variables are filled in, and it's easy to miss one of them in one of the initializers or accidentally make the two fill the fields act differently. This gives the possibility of subtle bugs that aren't that trivial to trace (you'd have to know which initializer was called), and the code will be more difficult to maintain. Not to mention that you'd be in an even bigger mess if you're using inheritance - the problems will go up the inheritance chain, because you'd have to use this alternative initializer everywhere up the chain.
Also by doing so you'd be more or less overriding Python's instance creation and making your own. Python already does that for you pretty well, no need to go reinventing it and it will confuse people using your code.
Here's what to best do instead: Use a single __init__ method that is to be called for all possible instantiations of the class that initializes all instance variables properly. For different modes of initialization use either of the two approaches:
Support different signatures for __init__ that handle your cases by using optional arguments.
Create several class methods that serve as alternative constructors. Make sure they all create instances of the class in the normal way (i.e. calling __init__), as shown by Roman Bodnarchuk, while performing additional work or whatever. It's best if they pass all the data to the class (and __init__ handles it), but if that's impossible or inconvenient, you can set some instance variables after the instance was created and __init__ is done initializing.
If __init__ has an optional step (e.g. like processing that data argument, although you'd have to be more specific), you can either make it an optional argument or make a normal method that does the processing... or both.
Use classmethod decorator for your Load method:
class B(object):
def __init__(self, name, data):
self._Name = name
#store data
#classmethod
def Load(cls, file, newName):
f = open(file, "rb")
s = pickle.load(f)
f.close()
return cls(newName, s)
So you can do:
loaded_obj = B.Load('filename.txt', 'foo')
Edit:
Anyway, if you still want to omit __init__ method, try __new__:
>>> class A(object):
... def __init__(self):
... print '__init__'
...
>>> A()
__init__
<__main__.A object at 0x800f1f710>
>>> a = A.__new__(A)
>>> a
<__main__.A object at 0x800f1fd50>
Taking your question literally I would use meta classes :
class MetaSkipInit(type):
def __call__(cls):
return cls.__new__(cls)
class B(object):
__metaclass__ = MetaSkipInit
def __init__(self):
print "FAILURE"
def Print(self):
print "YEHAA"
b = B()
b.Print()
This can be useful e.g. for copying constructors without polluting the parameter list.
But to do this properly would be more work and care than my proposed hack.
Not really. The purpose of __init__ is to instantiate an object, and by default it really doesn't do anything. If the __init__ method is not doing what you want, and it's not your own code to change, you can choose to switch it out though. For example, taking your class A, we could do the following to avoid calling that __init__ method:
def emptyinit(self):
pass
A.__init__ = emptyinit
a = A()
a.Print()
This will dynamically switch out which __init__ method from the class, replacing it with an empty call. Note that this is probably NOT a good thing to do, as it does not call the super class's __init__ method.
You could also subclass it to create your own class that does everything the same, except overriding the __init__ method to do what you want it to (perhaps nothing).
Perhaps, however, you simply wish to call the method from the class without instantiating an object. If that is the case, you should look into the #classmethod and #staticmethod decorators. They allow for just that type of behavior.
In your code you have put the #staticmethod decorator, which does not take a self argument. Perhaps what may be better for the purpose would a #classmethod, which might look more like this:
#classmethod
def Load(cls, file, newName):
# Get the data
data = getdata()
# Create an instance of B with the data
return cls.B(newName, data)
UPDATE: Rosh's Excellent answer pointed out that you CAN avoid calling __init__ by implementing __new__, which I was actually unaware of (although it makes perfect sense). Thanks Rosh!
I was reading the Python cookbook and there's a section talking about this: the example is given using __new__ to bypass __init__()
>>> class A:
def __init__(self,a):
self.a = a
>>> test = A('a')
>>> test.a
'a'
>>> test_noinit = A.__new__(A)
>>> test_noinit.a
Traceback (most recent call last):
File "", line 1, in
test_noinit.a
AttributeError: 'A' object has no attribute 'a'
>>>
However I think this only works in Python3. Below is running under 2.7
>>> class A:
def __init__(self,a):
self.a = a
>>> test = A.__new__(A)
Traceback (most recent call last):
File "", line 1, in
test = A.__new__(A)
AttributeError: class A has no attribute '__new__'
>>>
As I said in my comment you could change your __init__ method so that it allows creation without giving any values to its parameters:
def __init__(self, p0, p1, p2):
# some logic
would become:
def __init__(self, p0=None, p1=None, p2=None):
if p0 and p1 and p2:
# some logic
or:
def __init__(self, p0=None, p1=None, p2=None, init=True):
if init:
# some logic
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.
I have a Python class (it's not actually mine, it's from a package, so I don't want to edit this one). Minimal example (unrealistic):
import os
class SuperClass:
def __init__(self):
# Do something, for example
self.a = 0
pass
def from_file(filename):
# Do something with the file,
# use it to create superclass
# instance obj. For example...
obj = SuperClass()
obj.a = os.stat(filename).st_size
return obj
Now I want to create a subclass of this superclass, whose initialization always comes from a file -- that is, I want to do something like
class SubClass(SuperClass):
def __init__(self, filename):
self = SuperClass.from_file(filename)
This doesn't work (I didn't expect it to): I don't get an exception but the subclass is not initialized correctly. For instance, if the SuperClass has some instance value a, which is always set, doing
new_subclass_instance = SubClass('/filepath/file')
print(new_subclass_instance.a)
will give an AttributeError: type object 'SubClass' has no attribute 'a'.
How can I initialize using the from_file function from the parent class?
Python's __init__ method is in reality not a constructor, it's just an initializer. That's why you cannot implement this behavior in the __init__ method - once __init__ is called, you already have a superfluous object instance floating around.
The method responsible for actually creating a new instance of the class is __new__, so we can achieve our goal by overriding that. The basic idea is to write something like this:
class SubClass(SuperClass):
def __new__(cls, filename):
return cls.from_file(filename)
def __init__(self, *args, **kwargs):
pass
The empty __init__ is necessary because python will automatically call it on the object that's returned from __new__. If we omit the empty __init__ method, python will end up calling SuperClass.__init__ on the object instead, and that will reset all of its attributes.
There is, however, a problem: Since we've rewritten the __new__ method so that it requires a filename argument, the from_file method probably no longer works. You haven't shown its code, but it probably does something along these lines:
#classmethod
def from_file(cls, filename):
obj = cls()
obj.filename = filename
return obj
The problem here is that the call to cls() will fail: This calls our __new__ method, which expects a filename argument, without any arguments. We end up with an exception like TypeError: __new__() missing 1 required positional argument: 'filename'. To work around this, we can make the filename parameter optional:
class SubClass(SuperClass):
def __new__(cls, filename=None):
if filename is None:
return super().__new__(cls)
return cls.from_file(filename)
def __init__(self, *args, **kwargs):
pass
Now we can call obj = SubClass('/filepath/file') as desired. However, it's also possible to call SubClass without any arguments (like obj = SubClass()), which will return a completely unitialized object instance (remember, our __init__ is empty, so the object will have no attributes whatsoever). There is, unfortunately, nothing we can do about this.
Generally speaking, it's probably a bad idea to do this. As I'm sure you can tell by now, there are numerous pitfalls one has to watch out for when trying to change an existing class's interface like this. It's very possible that it's not worth the trouble and you should just stick to creating your instances with SubClass.from_file.
While integrating a Django app I have not used before, I found two different ways to define functions inside the class. The author seems to use them both distinctively and intentionally. The first one is the one that I myself use a lot:
class Dummy(object):
def some_function(self, *args, **kwargs):
# do something here
# self is the class instance
The other one is the one I never use, mostly because I do not understand when and what to use it for:
class Dummy(object):
#classmethod
def some_function(cls, *args, **kwargs):
# do something here
# cls refers to what?
The classmethod decorator in the python documentation says:
A class method receives the class as the implicit first argument, just
like an instance method receives the instance.
So I guess cls refers to Dummy itself (the class, not the instance). I do not exactly understand why this exists, because I could always do this:
type(self).do_something_with_the_class
Is this just for the sake of clarity, or did I miss the most important part: spooky and fascinating things that couldn't be done without it?
Your guess is correct - you understand how classmethods work.
The why is that these methods can be called both on an instance OR on the class (in both cases, the class object will be passed as the first argument):
class Dummy(object):
#classmethod
def some_function(cls,*args,**kwargs):
print cls
#both of these will have exactly the same effect
Dummy.some_function()
Dummy().some_function()
On the use of these on instances: There are at least two main uses for calling a classmethod on an instance:
self.some_function() will call the version of some_function on the actual type of self, rather than the class in which that call happens to appear (and won't need attention if the class is renamed); and
In cases where some_function is necessary to implement some protocol, but is useful to call on the class object alone.
The difference with staticmethod: There is another way of defining methods that don't access instance data, called staticmethod. That creates a method which does not receive an implicit first argument at all; accordingly it won't be passed any information about the instance or class on which it was called.
In [6]: class Foo(object): some_static = staticmethod(lambda x: x+1)
In [7]: Foo.some_static(1)
Out[7]: 2
In [8]: Foo().some_static(1)
Out[8]: 2
In [9]: class Bar(Foo): some_static = staticmethod(lambda x: x*2)
In [10]: Bar.some_static(1)
Out[10]: 2
In [11]: Bar().some_static(1)
Out[11]: 2
The main use I've found for it is to adapt an existing function (which doesn't expect to receive a self) to be a method on a class (or object).
One of the most common uses of classmethod in Python is factories, which are one of the most efficient methods to build an object. Because classmethods, like staticmethods, do not need the construction of a class instance. (But then if we use staticmethod, we would have to hardcode the instance class name in the function)
This blog does a great job of explaining it:
https://iscinumpy.gitlab.io/post/factory-classmethods-in-python/
If you add decorator #classmethod, That means you are going to make that method as static method of java or C++. ( static method is a general term I guess ;) )
Python also has #staticmethod. and difference between classmethod and staticmethod is whether you can
access to class or static variable using argument or classname itself.
class TestMethod(object):
cls_var = 1
#classmethod
def class_method(cls):
cls.cls_var += 1
print cls.cls_var
#staticmethod
def static_method():
TestMethod.cls_var += 1
print TestMethod.cls_var
#call each method from class itself.
TestMethod.class_method()
TestMethod.static_method()
#construct instances
testMethodInst1 = TestMethod()
testMethodInst2 = TestMethod()
#call each method from instances
testMethodInst1.class_method()
testMethodInst2.static_method()
all those classes increase cls.cls_var by 1 and print it.
And every classes using same name on same scope or instances constructed with these class is going to share those methods.
There's only one TestMethod.cls_var
and also there's only one TestMethod.class_method() , TestMethod.static_method()
And important question. why these method would be needed.
classmethod or staticmethod is useful when you make that class as a factory
or when you have to initialize your class only once. like open file once, and using feed method to read the file line by line.
I have something like that in my python code
class A:
__mess = "Yeap!"
def doSome(self):
self.FN()
def FN(self):
pass
def myFN(self):
print self.__mess
b = A()
b.FN = myFN
b.doSome()
But this doesn't work. Where am I wrong?
python 2.6.5
upd: I want to redefine method (FN) only for one exemplar (b).
upd2:
import new
class A:
__mess = "Yeap!"
def doSome(self):
self.FN()
def FN(self):
pass
def myFN(self):
print self.__mess
b = A()
b.FN = new.instancemethod(myFN, b, A)
b.doSome()
Doesn't work too.
Traceback (most recent call last):
File "", line 1, in
File "", line 4, in doSome
File "", line 2, in myFN
AttributeError: A instance has no
attribute '__mess'
myLoopFN is a function, not an instance method. Do
import new
b.loopFN = new.instancemethod( myLoopFN, b, A )
The problem is that Python treats instance methods very slightly differently to regular functions: they get the instance upon which they are run as the default first argument. If you define a method inside a class definition it automagically becomes an instance method, so that when you instantiate the class it gets passed the instance. However, when you define myLoopFN you do it outside the class definition, so that it is an ordinary function instead of an instance method. You fix this by explicitly declaring it as an instance method.
...
BUT
This is icky because it's not something you should do; changing instance methods at runtime will lead to problems. You'll never be sure whether your A is an original A or a modified one, and you won't be able to debug it because you can't tell whether you've changed loopFN or not. This will give you the kind of bugs that Nyarlathotep himself would be proud of.
The right way to do this is to subclass A and override the method, so that you can distinguish between the different classes.
class myA( A ):
def loopFN(self):
#put modified function here
This way, you can instantiate the modified class and be certain of its methods.
Edit
You are using a double-underscore variable name, __mess. You (almost certainly) don't want to do this. For some reason known only to our Benevolent Dictator for Life and a select few others, Python automatically mangles these __ names to _<class-name>__, to serve as a sort-of faux private variable. This is horrible, and besides there's no reason to call it __mess instead of (the much nicer) mess.
If you absolutely must call it __mess, you can refer to it as follows:
def myFN(self):
print( self._A__mess )
(mutatis mutandis when you change the name of A). This is nasty and unPythonic.
Regarding the second error (with __mess):
Change
print self.__mess
to
print self._mess
And change
class A:
__mess = "Yeap!"
to
class A:
_mess = "Yeap!"
Double underscores tell Python to use name-mangling.
An alternative is to change
def myFN(self):
print self.__mess
to
def myFN(self):
print self._A__mess
Alright, so I was taking a look at some source when I came across this:
>>> def __parse(self, filename):
... "parse ID3v1.0 tags from MP3 file"
... self.clear()
... try:
... fsock = open(filename, "rb", 0)
... try:
... fsock.seek(-128, 2)
... tagdata = fsock.read(128)
... finally:
... fsock.close()
... if tagdata[:3] == 'TAG':
... for tag, (start, end, parseFunc) in self.tagDataMap.items():
... self[tag] = parseFunc(tagdata[start:end])
... except IOError:
... pass
...
So, I decided to test it out.
>>> __parse("blah.mp3")
And, I received this error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __parse() takes exactly 2 arguments (1 given)
This wouldn't be the first time I've encountered this, I keep thinking I'm meant to include self in the argument parameter list, but I know that that's not right. Could someone explain to me why this happens a lot with code I try to play around with, I suppose its due to my level of understanding about the terms, I barely even understand what init or self does, or why it's relevant. def x(b): print b is the same as def x(self, b): self.b = b print self.b isn't it? Why does it matter so much!
I just want a basic explanation, so I can get this out of my mind,thanks.
The def __parse was inside some class definition.
You can't pull the method defs out of the class definitions. The method function definition is part of the class.
Look at these two examples:
def add( a, b ):
return a + b
And
class Adder( object ):
def __init__( self ):
self.grand_total = 0
def add( self, a, b ):
self.grand_total += a+b
return a+b
Notes.
The function does not use self.
The class method does use self. Generally, all instance methods will use self, unless they have specific decorators like #classmethod that say otherwise.
The function doesn't depend on anything else else.
The class method depends on being called by an instance of the class Adder; further, it depends on that instance of the class Adder having been initialized correctly. In this case, the initialization function (__init__) has assured that each instance of Adder always has an instance variable named grand_total and that instance variable has an initial value of 0.
You can't pull the add method function out of the Adder class and use it separately. It is not a stand-alone function. It was defined inside the class and has certain expectations because of that location inside the class.
Functions/methods can be written outside of a class and then used for a technique in Python called monkeypatching:
class C(object):
def __init__(self):
self.foo = 'bar'
def __output(self):
print self.foo
C.output = __output
c = C()
c.output()
Looks like you're a bit confused about classes and object-oriented programming. The 'self' thing is one of the gotchas in python for people coming from other programming languages. IMO the official tutorial doesn't handle it too well. This tutorial seems quite good.
If you've ever learnt java, self in python is very similar to this in java. The difference is that python requires you to list self as the first argument to every function in a class definition.
If python is your first programming language (or your first object-oriented language), you could remember this as a simple rule-of-thumb: if you're defining a function that's part of a class, you need to include self as the first argument. If you're defining a function that's not part of a class, you shouldn't include self in the arguments. You can't take a class function and make it stand-alone without doing some (or possibly a lot of) extra coding. Finally, never include self as an argument when calling a function.
There are exceptions to those rules, but they're not worth worrying about now.
self is passed in automatically by the instancemethod wrapper on classes. This function isn't wrapped; it's not a method, it's just a function. It doesn't even make sense without being attached to a class, since it needs the self parameter.
As an aside, it is possible to create static methods of a class in Python. The simplest way to do this is via decorators (e.g. #staticmethod). I suspect this kind of thing is usually not the Pythonic solution though.