Python: using Self and adding methods to an object on the fly - python

Here's my idea: Start with a simple object:
class dynamicObject(object):
pass
And to be able to add pre written methods to it on the fly:
def someMethod(self):
pass
So that I can do this:
someObject = dyncamicObject()
someObject._someMethod = someMethod
someObject._someMethod()
Problem is, it wants me to specify the self part of _someMethod() so that it looks like this:
someObject._someMethod(someObject)
This seems kind of odd since isn't self implied when a method is "attached" to an object?
I'm new to the Python way of thinking and am trying to get away from the same thought process for languages like C# so the idea here it to be able to create an object for validation by picking and choosing what validation methods I want to add to it rather than making some kind of object hierarchy. I figured that Python's "self" idea would work in my favor as I thought the object would implicitly know to send itself into the method attached to it.
One thing to note, the method is NOT attached to the object in any way (Completely different files) so maybe that is the issue? Maybe by defining the method on it's own, self is actually the method in question and therefore can't be implied as the object?

Although below I've tried to answer the literal question, I think
Muhammad Alkarouri's answer better addresses how the problem should actually be solved.
Add the method to the class, dynamicObject, rather than the object, someObject:
class dynamicObject(object):
pass
def someMethod(self):
print('Hi there!')
someObject=dynamicObject()
dynamicObject.someMethod=someMethod
someObject.someMethod()
# Hi there!
When you say someObject.someMethod=someMethod, then someObject.__dict__ gets the key-value pair ('someMethod',someMethod).
When you say dynamicObject.someMethod=someMethod, then someMethod is added to dynamicObject's __dict__. You need someMethod defined in the class for
someObject.someMethod to act like a method call. For more information about this, see Raymond Hettinger's essay on descriptors -- after all, a method is nothing more than a descriptor! -- and Shalabh Chaturvedi's essay on attribute lookup.
There is an alternative way:
import types
someObject.someMethod=types.MethodType(someMethod,someObject,type(someObject))
but this is really an abomination since you are defining 'someMethod' as a key in someObject.__dict__, which is not the right place for methods. In fact, you do not get a class method at all, just a curried function. This is more than a mere technicality. Subclasses of dynamicObject would fail to inherit the someMethod function.

To achieve what you want (create an object for validation by picking and choosing what validation methods I want to add to it), a better way is:
class DynamicObject(object):
def __init__(self, verify_method = None):
self.verifier = verify_method
def verify(self):
self.verifier(self)
def verify1(self):
print "verify1"
def verify2(self):
print "verify2"
obj1 = DynamicObject()
obj1.verifier = verify1
obj2 = DynamicObject(verify2)
#equivalent to
#obj2 = DynamicObject()
#obj2.verify = verify2
obj1.verify()
obj2.verify()

Why don't you use setattr? I found this way much more explicit.
class dynamicObject(object):
pass
def method():
print "Hi"
someObject = dynamicObject()
setattr(someObject,"method", method)
someObject.method()

Sometimes it is annoying to need to write a regular function and add it afterwards when the method is very simple. In that case, lambdas can come to the rescue:
class Square:
pass
Square.getX = lambda self: self.x
Square.getY = lambda self: self.y
Square.calculateArea = lambda self: self.getX() * self.getY()
Hope this helps.

If you just want to wrap another class, and not have to deal with assigning a new method to any instance, you can just make the method in question a staticmethod of the class:
class wrapperClass(object):
#staticmethod
def foo():
print("yay!")
obj = wrapperClass()
obj.foo() // Yay!
And you can then give any other class the .foo method with multiple inheritance.
class fooDict(dict, wrapperClass):
"""Normal dict with foo method"""
foo_dict = fooDict()
foo_dict.setdefault('A', 10)
print(foo_dict) // {'A': 10}
foo_dict.foo() // Yay!

Related

How to decorate a python class and override a method?

I have a class
class A:
def sample_method():
I would like to decorate class A sample_method() and override the contents of sample_method()
class DecoratedA(A):
def sample_method():
The setup above resembles inheritance, but I need to keep the preexisting instance of class A when the decorated function is used.
a # preexisting instance of class A
decorated_a = DecoratedA(a)
decorated_a.functionInClassA() #functions in Class A called as usual with preexisting instance
decorated_a.sample_method() #should call the overwritten sample_method() defined in DecoratedA
What is the proper way to go about this?
There isn't a straightforward way to do what you're asking. Generally, after an instance has been created, it's too late to mess with the methods its class defines.
There are two options you have, as far as I see it. Either you create a wrapper or proxy object for your pre-existing instance, or you modify the instance to change its behavior.
A proxy defers most behavior to the object itself, while only adding (or overriding) some limited behavior of its own:
class Proxy:
def __init__(self, obj):
self.obj = obj
def overridden_method(self): # add your own limited behavior for a few things
do_stuff()
def __getattr__(self, name): # and hand everything else off to the other object
return getattr(self.obj, name)
__getattr__ isn't perfect here, it can only work for regular methods, not special __dunder__ methods that are often looked up directly in the class itself. If you want your proxy to match all possible behavior, you probably need to add things like __add__ and __getitem__, but that might not be necessary in your specific situation (it depends on what A does).
As for changing the behavior of the existing object, one approach is to write your subclass, and then change the existing object's class to be the subclass. This is a little sketchy, since you won't have ever initialized the object as the new class, but it might work if you're only modifying method behavior.
class ModifiedA(A):
def overridden_method(self): # do the override in a normal subclass
do_stuff()
def modify_obj(obj): # then change an existing object's type in place!
obj.__class__ = ModifiedA # this is not terribly safe, but it can work
You could also consider adding an instance variable that would shadow the method you want to override, rather than modifying __class__. Writing the function could be a little tricky, since it won't get bound to the object automatically when called (that only happens for functions that are attributes of a class, not attributes of an instance), but you could probably do the binding yourself (with partial or lambda if you need to access self.
First, why not just define it from the beginning, how you want it, instead of decorating it?
Second, why not decorate the method itself?
To answer the question:
You can reassign it
class A:
def sample_method(): ...
pass
A.sample_method = DecoratedA.sample_method;
but that affects every instance.
Another solution is to reassign the method for just one object.
import functools;
a.sample_method = functools.partial(DecoratedA.sample_method, a);
Another solution is to (temporarily) change the type of an existing object.
a = A();
a.__class__ = DecoratedA;
a.sample_method();
a.__class__ = A;

Proper way to define function in a class that does not use self value

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.

How to pass a class method as an argument to a function external to that class?

This is how it works for me:
class SomeName:
def __init__(self):
self.value = "something"
def some_method(self):
print self.value
def external_func(instance, method):
method(instance)
external_func(SomeName(), SomeName.some_method)
This appears to work correctly. Is this the right way to do this?
Your code is "technically correct" (it does what you ask for) but - at least in your example - pretty useless:
def external_func(instance, method):
method(instance)
external_func(SomeName(), SomeName.some_method)
is the same as:
def external_func(method):
method()
external_func(SomeName().some_method)
which FWIW is the same as:
SomeName().some_method()
but I assume you understood this already .
Now you probably have a reason to try to pass both the method AND instance to external_func(), or there might be a better way to solve your real problem...
I of course don't know what you're doing exactly, but it sounds to me like you're trying to do too much inside of one function. Your problem might be better solved by simply splitting up the contents of external_func.
The goals here, as I understand them, are you don't know ahead of time what the object/method pair will be, and want to reduce code repetition.
Perhaps something like this would be better:
def main():
obj = SomeName()
# do the setting up portion
complex_object = external_func_set_up(obj)
# presumably at some point you have to designate the method to be used:
method = get_method_name(obj)
# run the method:
getattr(obj, method)()
# finish up the external operation:
external_func_complete(***args***)
I understand this is more code, but I think in the end it's a lot clearer what is happening, and also might force you to think through your problem a bit more (and potentially come up with an even better solution).
You could pass SomeName().some_method or make some_metod staticmethod or classmethod if there is no instance data used in your method.
Check documentation to know more about staticmethod and classmethod:
https://docs.python.org/3/library/functions.html#staticmethod
https://docs.python.org/3/library/functions.html#classmethod
Depending on what you're doing. Because functions are also objects in Python it is possible to do so.
But is it a good solution? It seems though that you're trying to handle a problem which maybe could be better solved with more of an object oriented approach:
class A:
def __init__(self):
self.value = "class A"
def some_method(self):
print self.value
class B:
def __init__(self):
self.value = "class B"
def some_method(self):
print self.value
some_class = A()
some_class.some_method()
some_class = B()
some_class.some_method()
Output:
"class A"
"class B"
In my view this would be a better approach (if this is possible/reasonable in your case): You just call some_method() on your class, maybe without even knowing what exact type of object you're dealing with (regarding inheritance). The class itself knows what to do and reacts accordingly when its method has been called.
This of course doesn't work when you work with external libraries which you have no influence on.

How to cast object in Python

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.)

Python, overiding itself

I've a following problem. I have a model class in MVC and it has a special purpose. In certain cases it should be able to override itself. Is this kind of behavior possible?
Class Text(Document):
a = StringField()
b = StringField()
def save(self):
if 1==Text.object(a=self.a).count(): # if similar object exists in db,
self = Text.object(a=self.a).first() # get the instance from db and
# override the origian class.
else: #use super class' save-function
return super(Text, self).save()
There's no trivial way for an object to become another object in python. Assigning to self won't do this; self is a local variable in the method definition, And assigning to it won't change the existing instance in any way; only make it inaccessible for the rest of the method.
There are a few ways to approach this problem. The preferred way is to have a method that returns the correct instance.
class Foo(...):
def get_or_save(self):
existing = load_from_database(self.bar)
if existing is not None:
return existing
else:
save_to_database(self)
return self
new_inst = Text()
new_inst.bar = "baz"
inst = new_inst.get_or_save()
# stop using new_inst
There is also a hackish way to get a similar effect to your original example. Ordinary python classes store most of their attributes in a special __dict__ attribute. You can copy that and it will be as though one instance is replaced by the other. Of course, that only works for perfectly plain python classes, and may or may not work classes defined in an ORM, or which retain state in more clever ways.
class Foo(...):
def save(self):
existing = load_from_database(self.bar)
if existing is not None:
self.__dict__ = existing.__dict__
else:
save_to_database(self)
Yes it is possible :-)
Seriously, using a conditional call to super as in your example will achieve the result.
However, the style of your example is a little confusing, and changing it may allow you to achieve your overall objectives more easily. (But neither of these directly affects your question.)
I would not recommend putting a method in your class called object unless I had no other choice.
The fact that you are passing self.a to Text.object, within method Text.save, doesn't seem right. It would be cleaner to simply call self.object() and have method object use self.a directly in its code.

Categories