Say I have a class
class Base(object):
def my_method(self, input):
print input #suppose this is many lines
print "mymethod" #so is this
and a subclass that has a method which does almost the same thing, except for an extra operation in the middle of the method, e.g.
class Sub(Base):
def mymethod(self, input): #how do I properly define this?
print input
print "some other stuff" #additional operation in the middle
print "mymethod"
What is the proper way to overriding mymethod?
Do I copy-and-paste the majority of Base.mymethod()? (Probably not - that definitely violates DRY).
Do I define Base.mymethod() to have a conditional statement for the additional operation that only returns true in a subclass case? (Probably not - that doesn't make sense since the base class should be standalone and this seems like a recipe for disaster)
Can I somehow use super()? (Seems not - Sub's additional operation is in the middle of the method, not the beginning or end)
For such a simple example, I will most likely copy these three small lines, even if creates a repetitions. Try to avoid over-engineering.
In the case where my_method() is actually more complex, you can divide your function into three steps, and let the child classes overload the part they want.
class Base(object):
def my_method(self, input):
self._preprocess(input)
self._process()
self._postprocess()
def _preprocess(self, input):
print(input)
def _process(self):
pass
def _postprocess(self):
print("mymethod")
class Sub(Base):
def _process(self):
print("some other stuff")
Of course you should use more meaningful method names.
That depends on where stuff belongs. Usually if you end up wanting to insert stuff in between operations of the base's method, it means that method should actually be split into several methods.
For instance:
class Base(object):
def my_method(self, input):
print input #suppose this is many lines
print "mymethod" #so is this
could become:
class Base(object):
def my_method(self, input):
self.do_first_thing(input)
self.do_second_thing("mymethod")
def do_first_thing(self, input):
print(input)
def do_second_thing(self, data):
print(data)
This lets subclasses redefine the whole process without having to re-implement each step. The concept is akin to a template method, but backwards.
(Normally the point of a template method pattern is to let subclasses redefine steps, here we use the same structure to let subclasses redefine the template itself).
Related
Let's suppose we have this class:
class Demo:
def __init__(self, str):
self.str = str
def fromBytes1(bytes):
return Demo(bytes2str(bytes))
#classmethod
def fromBytes2(cls, bytes):
return cls(bytes2str(bytes))
What is the difference between fromBytes1 and fromBytes2, except for the fact that you can't call the 1st method in the following way?
Demo().fromBytes1(bytes)
Is there something more subtle that I cannot see here?
Assuming that you only intend to call the methods from a class object, all the important differences are in inheritance. Say you have
class Test(Demo):
pass
If you do Test.fromBytes1(b'ar'), you get an instance of Demo.
If you do Test.fromBytes2(b'ar'), you get an instance of Test.
The second method is more flexible because you can hard code Demo or __class__ into it directly, but you must hard code it in the first case.
I am new to opp programming.I wanted to know what to do with a function that is inside the class but does not use self value
For example
class example:
def __init__(self,n):
self.number=n
def get_t(self,t):
return t*t
def main(self):
b=1
k=self.get_t(b)
From the example the function get_t has nothing to do with self value.
So I wanted to know where to place the function get_t or may be how to restructure the class.
Thank you for your consideration
What you're looking for are static methods. To declare a method static do it like this
#staticmethod
def foo():
pass
Nothing. Just let it be, Python won't complain about it and there's nothing fundamentally wrong about methods that doesn't use its instance. If your linter complains about it, you can shut up that warning. These kind of helper functions are often intended to be private methods that aren't intended to be used externally, you may want to prefix the name with underscore to indicate that.
Convert it into a free function. Python is an OOP language, but it's also a mixed paradigm language, unlike Java, for example, you can actually create a function outside of a class declaration. Pythonic code does not necessarily means putting everything into classes, and often a free function is perfectly suitable place for functions that doesn't involve a particular object instance.
def get_t(t):
return t*t
class example:
def main(self):
b=1
k=self.get_t(b)
If you want to be able to call it from the class by doing Example.get_t(blah) without having to have an instance, then you can either use the staticmethod or classmethod decorator. I suggest using classmethod which can do everything that staticmethod can do while the reverse isn't true and it's easier to make classmethod work correctly when you need to override it in a multi inheritance situation. staticmethod has a very tiny performance advantage, but you're microoptimizing if that's your concern.
class example:
#classmethod
def get_t(cls, t):
return t*t
def main(self):
b=1
k=self.get_t(b)
If get_t() is only being called from one method, you can put it as an inner function of that method:
class example:
def main(self):
def get_t(t):
return t * t
b=1
k=self.get_t(b)
With regards to naming, get_xxx is usually a code smell in python. The get_ prefix indicates that the method is likely a getter, and pythonic code usually don't use getters/setters, because the language supports property. What you have on here though, isn't actually a getter but rather a computation method, so it shouldn't be prefixed with get_. A better name might be calculate_t(t) or square(t).
Case 1: If self is there:-
class example:
def get_t(self,t):
return t*t
Then You can not access get_t function directly from class example like example.get_t(t=2) ,it will give you error. But you can access now by creating an object of class like q = example() and then q.get_t(t=2) , it will give you your desired result.
Case 2 : If self is not there:-
class example:
def get_t(t):
return t*t
Now You can directly access get_t function by class example like example.get_t(t=2) ,it will give you your desired result. But now you cannot use get_t function by creating object like q = example() then q.get_t(t=2) it will give you error.
Conclusion :- It all depends on your use case. But when you struck in this type of ambiguity use #staticmethod like given below:-
class example:
#staticmethod
def get_t(t):
return t*t
I hope it may help you.
Is it good style to create a separate method, in which I preprocess data, before I pass it to the constructor (in case the preprocessing is cumbersome), like so:
class C():
def __init__(self, input, more_input):
self.value = self.prepare_value(input, more_input)
def prepare_value(self, input, more_input):
#here I actually do some nontrivial stuff, over many lines
#for brevity I'm illustrating just a short, one-line operation
value = (input + more_input)/2
return value
print(C(10, 33).value) # has value 21.5
If you wanted to do it like this, then I'd suggest two things.
Make the prepare_value() method a static method by decorating with the #staticmethod decorator. Since it's not making any changes to the instance of the class itself, just returning a value then you shouldn't be making it a method of the instance. Hence, #staticmethod.
Signify that the method should only be used internally by using the name _prepare_value(). This doesn't actually make it private, but it's a well recognized convention to say to other developers (i.e. future you) "this method isn't designed to be used externally".
Overall my suggestion would be:
class C():
def __init__(self, input, more_input):
self.value = self._prepare_value(input, more_input)
#staticmethod
def _prepare_value(input, more_input):
value = (input + more_input)/2
return value
I have following example code:
class AuxiliaryClass:
#staticmethod
def high_cost_method():
"Do something"
class MyTestedClass:
def do_something(self):
something = AuxiliaryClass.high_cost_method()
"do something else"
I want to test MyTestedClass. For this purpose I've created AuxiliaryClassStub class to override high_cost_method(). I want my test to execute do_something() from MyTestedClass, but do_something() should use stub instead of real class.
How can I do that?
My real auxiliary class is quite big, it has a lot of methods and I will use it in many tests, so I don't want to patch single methods. I need to replace whole class during tests.
Note, that high_cost_method() is static, so mocking __init__() or __new__() will not help in this case.
Does it work if you use self.__class__.high_cost_method inside do_something? This way you avoid the direct reference to the class name, which should enable subclassing and overriding the staticmethod with the one from AuxiliaryClass.
class MyTestedClass:
def do_something(self):
something = self.__class__.high_cost_method()
something()
#staticmethod
def high_cost_method():
print("high cost MyTestedClass")
class AuxiliaryClass(MyTestedClass):
#staticmethod
def high_cost_method():
print("high cost AuxiliaryClass")
Then you get
test = AuxiliaryClass()
test.high_cost_method()
high cost AuxiliaryClass
and otherwise
test = MyTestedClass()
test.high_cost_method()
high cost MyTestedClass
I have two classes (let's call them Working and ReturnStatement) which I can't modify, but I want to extend both of them with logging. The trick is that the Working's method returns a ReturnStatement object, so the new MutantWorking object also returns ReturnStatement unless I can cast it to MutantReturnStatement. Saying with code:
# these classes can't be changed
class ReturnStatement(object):
def act(self):
print "I'm a ReturnStatement."
class Working(object):
def do(self):
print "I am Working."
return ReturnStatement()
# these classes should wrap the original ones
class MutantReturnStatement(ReturnStatement):
def act(self):
print "I'm wrapping ReturnStatement."
return ReturnStatement().act()
class MutantWorking(Working):
def do(self):
print "I am wrapping Working."
# !!! this is not working, I'd need that casting working !!!
return (MutantReturnStatement) Working().do()
rs = MutantWorking().do() #I can use MutantWorking just like Working
print "--" # just to separate output
rs.act() #this must be MutantReturnState.act(), I need the overloaded method
The expected result:
I am wrapping Working.
I am Working.
--
I'm wrapping ReturnStatement.
I'm a ReturnStatement.
Is it possible to solve the problem? I'm also curious if the problem can be solved in PHP, too. Unless I get a working solution I can't accept the answer, so please write working code to get accepted.
There is no casting as the other answers already explained. You can make subclasses or make modified new types with the extra functionality using decorators.
Here's a complete example (credit to How to make a chain of function decorators?). You do not need to modify your original classes. In my example the original class is called Working.
# decorator for logging
def logging(func):
def wrapper(*args, **kwargs):
print func.__name__, args, kwargs
res = func(*args, **kwargs)
return res
return wrapper
# this is some example class you do not want to/can not modify
class Working:
def Do(c):
print("I am working")
def pr(c,printit): # other example method
print(printit)
def bla(c): # other example method
c.pr("saybla")
# this is how to make a new class with some methods logged:
class MutantWorking(Working):
pr=logging(Working.pr)
bla=logging(Working.bla)
Do=logging(Working.Do)
h=MutantWorking()
h.bla()
h.pr("Working")
h.Do()
this will print
h.bla()
bla (<__main__.MutantWorking instance at 0xb776b78c>,) {}
pr (<__main__.MutantWorking instance at 0xb776b78c>, 'saybla') {}
saybla
pr (<__main__.MutantWorking instance at 0xb776b78c>, 'Working') {}
Working
Do (<__main__.MutantWorking instance at 0xb776b78c>,) {}
I am working
In addition, I would like to understand why you can not modify a class. Did you try? Because, as an alternative to making a subclass, if you feel dynamic you can almost always modify an old class in place:
Working.Do=logging(Working.Do)
ReturnStatement.Act=logging(ReturnStatement.Act)
Update: Apply logging to all methods of a class
As you now specifically asked for this. You can loop over all members and apply logging to them all. But you need to define a rule for what kind of members to modify. The example below excludes any method with __ in its name .
import types
def hasmethod(obj, name):
return hasattr(obj, name) and type(getattr(obj, name)) == types.MethodType
def loggify(theclass):
for x in filter(lambda x:"__" not in x, dir(theclass)):
if hasmethod(theclass,x):
print(x)
setattr(theclass,x,logging(getattr(theclass,x)))
return theclass
With this all you have to do to make a new logged version of a class is:
#loggify
class loggedWorker(Working): pass
Or modify an existing class in place:
loggify(Working)
There is no "casting" in Python.
Any subclass of a class is considered an instance of its parents. Desired behavior can be achieved by proper calling the superclass methods, and by overriding class attributes.
update: with the advent of static type checking, there is "type casting" - check bellow.
What you can do on your example, is to have to have a subclass initializer that receives the superclass and copies its relevant attributes - so, your MutantReturnstatement could be written thus:
class MutantReturnStatement(ReturnStatement):
def __init__(self, previous_object=None):
if previous_object:
self.attribute = previous_object.attribute
# repeat for relevant attributes
def act(self):
print "I'm wrapping ReturnStatement."
return ReturnStatement().act()
And then change your MutantWorking class to:
class MutantWorking(Working):
def do(self):
print "I am wrapping Working."
return MutantReturnStatement(Working().do())
There are Pythonic ways for not having a lot of self.attr = other.attr lines on the __init__method if there are lots (like, more than 3 :-) ) attributes you want to copy -
the laziest of which wiuld be simply to copy the other instance's __dict__ attribute.
Alternatively, if you know what you are doing, you could also simply change the __class__ attribute of your target object to the desired class - but that can be misleading and carry you to subtle errors (the __init__ method of the subclass would not be called, would not work on non-python defined classes, and other possible problems), I don't recomment this approach - this is not "casting", it is use of introspection to bruteforce an object change and is only included for keeping the answer complete:
class MutantWorking(Working):
def do(self):
print "I am wrapping Working."
result = Working.do(self)
result.__class__ = MutantReturnStatement
return result
Again - this should work, but don't do it - use the former method.
By the way, I am not too experienced with other OO languages, that allow casting - but is casting to a subclass even allowed in any language? Does it make sense? I think casting s only allowed to parentclasses.
update: When one works with type hinting and static analysis in the ways describd in PEP 484, sometimes the static analysis tool can't figure out what is going on. So, there is the typing.cast call: it does absolutely nothing in runtime, just return the same object that was passed to it, but the tools then "learn" that the returned object is of the passed type, and won't complain about it. It will remove typing errors in the helper tool, but I can't emphasise enough it does not have any effect in runtime:
In [18]: from typing import cast
In [19]: cast(int, 3.4)
Out[19]: 3.4
No direct way.
You may define MutantReturnStatement's init like this:
def __init__(self, retStatement):
self.retStatement = retStatement
and then use it like this:
class MutantWorking(Working):
def do(self):
print "I am wrapping Working."
# !!! this is not working, I'd need that casting working !!!
return MutantReturnStatement(Working().do())
And you should get rid from inheriting ReturnStatement in your wrapper, like this
class MutantReturnStatement(object):
def act(self):
print "I'm wrapping ReturnStatement."
return self.retStatement.act()
You don't need casting here. You just need
class MutantWorking(Working):
def do(self):
print "I am wrapping Working."
Working().do()
return MutantReturnStatement()
This will obviously give the correct return and desired printout.
What you do is not a casting, it is a type conversion. Still, you could write something like
def cast_to(mytype: Type[any], obj: any):
if isinstance(obj, mytype):
return obj
else:
return mytype(obj)
class MutantReturnStatement(ReturnStatement):
def __init__(self, *args, **kwargs):
if isinstance(args[0], Working):
pass
# your custom logic here
# for the type conversion.
Usage:
cast_to(MutantReturnStatement, Working()).act()
# or simply
MutantReturnStatement(Working()).act()
(Note that in your example MutantReturnStatement does not have .do() member function.)