I would like to modify an initializer of a class at run-time. Are there any potential catches with a code like this? I'm new into decorators so not really sure.
class Object:
def __init__(self):
print "do something"
#classmethod
def modify(cls, f):
__init___old = cls.__init__
def __init__(self):
__init___old(self)
f(self)
cls.__init__ = __init__
return f
#Object.modify
def f(self):
print "do something else"
Apart from confusing people who aren't used to python's powerful meta programming facilities, things like you do should work fine. Class is modifiable is a feature of python.
However, I would suggest to find a more conventional way to do what you needed to do, meta programming causes the source code on file to no longer match what a cursory inspection of the code suggest that the code do, so it is not very good for readability. For this particular case, you could append to a list in a class variable to be called in a loop in __init__.
The only catch you may or may not experience is that if you use a python optimizing compiler, e.g. psyco, pypy, using dynamic features like this may cause them to not be able to optimize things as well as they would otherwise be able to.
Rather than redefining __init__ like this, make your class keep a list of functions (which can be augmented) that should be executed at object initialization time.
class Object:
obj_initializers = []
def __init__(self):
print "do something"
for f in self.obj_initializers:
f(self)
#classmethod
def add_initializer(cls, f):
cls.obj_initializers.append(f)
def f(self):
print "do something else"
Object.add_initializer(f)
In your code, f isn't actually modified; you are just abusing the decorator syntax to execute another function with f as an argument.
Related
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.
First off, let me say that yes I have researched this extensively for a few days now with no luck. I have looked at numerous examples and similar situations such as this one, but so far nothing has been able to resolve me issue.
My problem is I have a Python project that has a primary class, with two nested classes (yea yea I know), one of those classes is a subclass of the first. I can not figure out why I keep getting NameError: global name 'InnerSubClass' is not defined.
I understand scoping (both classes in question are in the same scope) but nothing I try seems to resolve the issue (I want to keep the two classes nested at a minimum) despite this problem working for other people.
Here is a simple example of what I am trying to do:
class SomeClass(object):
def __init__(self):
"""lots of other working stuff"""
class MainClass(object):
def __init__(self):
self.stuff = []
self.moreStuffs = []
class InnerClass(object):
def __init__(self, thing, otherThing):
self.thing = thing
self.otherThing = otherThing
self.otherStuff = []
class InnerSubClass(InnerClass):
def __init__(self, thing, otherThing, newThing):
super(InnerSubClass).__init__(thing, otherThing)
self.newThing = newThing
"""other code that worked before the addition of 'InnerSubClass'"""
def doSomething(self):
innerclass = self.InnerSubClass('thisthing', 'thatthing', 'thingthing')
print("just more thing words %s" % innerclass.newThing)
myThing = MainClass()
myThing.doSomething()
I have tried changing super(InnerSubClass).__init__(thing, otherThing)
to
super(InnerClass.InnerSubClass).__init__(thing, otherThing)
and even
super(MainClass.InnerClass.InnerSubClass).__init__(thing, otherThing) with no success. I made "InnerSubClass" inherit straight from object InnerSubClass(object): etc, and it still doesn't work.
Granted I am far from a seasoned python developer and come from mostly other compiled OO languages, and can't seem to wrap my head around why this isn't working. If I get rid of the "InnerSubClass", everything works just fine.
It doesn't seem like python offers "private" classes and functions like other languages, which is fine but I would like to utilize the nesting to at least keep objects "lumped" together. In this case, nothing should be instantiating "InnerClass" or "InnerSubClass" except functions in "MainClass".
Please provide helpful advice and explain why it doesn't work as expected with background information on how this should be done properly. If this was as simple as it seems, it would have been figured out by now.
edit: for clarification, this is only for v2
There is no "class scope" in lookup order
When creating a new class, the code in the body is executed and the resulting names are passed to type for creation. Python lookups go from inner to outer, but you don't have a "class level", only the names you define to become attributes/methods of your new class. In fact, if you want to access class variables inside a method, you use MyClass.attr instead of simple attr.
The inheritance works because InnerSubClass(InnerClass) occurs inside the class creation. To access InnerClass after MainClass has been created, do the same as you would for class attributes: MainClass.InnerClass
Just to include an example:
class Outer:
out = 1
class Inner:
inside = 2
try:
print(out) # this is confusing
except NameError:
print("can't find out")
def f(self):
try:
print(inside) # this is clear
except NameError:
print("can't find inside")
try:
print(Inner.inside) # this is less clear
except NameError:
print("can't find Inner.inside")
Outer.Inner().f()
# can't find anything
Edit:
The above is a general view, to apply it directly to your situation, look at your inner classes the way you look at regular class attributes. You'd access these as MyClass.attr, where MyClass is defined globally. If you replace attr with InnerSubClass, you get the class (attribute lookup doesn't care about inheritance, but about where the attributes are).
A stripped-down example with nested inheriting classes:
class MainClass(object):
class Inner(object):
pass
class InnerSub(Inner):
def __init__(self):
print(super(MainClass.InnerSub)) # note you use MainClass, known globally
def f(self):
return self.InnerSub()
MainClass().f() # prints "<super ...>" and returns a MainCLass.InnerSub object
Here they do it like this
super(MainClass.InnerSubClass, self).__init__(thing, otherThing)
So that you can test it here is the full working example
class SomeClass(object):
def __init__(self):
"""lots of other working stuff"""
class MainClass(object):
def __init__(self):
self.stuff = []
self.moreStuffs = []
class InnerClass(object):
def __init__(self, thing, otherThing):
self.thing = thing
self.otherThing = otherThing
self.otherStuff = []
class InnerSubClass(InnerClass):
def __init__(self, thing, otherThing, newThing):
super(MainClass.InnerSubClass, self).__init__(thing, otherThing)
self.newThing = newThing
"""other code that worked before the addition of 'InnerSubClass'"""
def doSomething(self):
innerclass = self.InnerSubClass('thisthing', 'thatthing', 'thingthing')
print("just more thing words %s" % innerclass.newThing)
print("and I also inherit from InnerClass %s" % innerclass.otherThing)
myThing = MainClass()
myThing.doSomething()
The output is
just more thing words thingthing
and I also inherit from InnerClass thatthing
If you have reasons for not using MainClass.InnerSubClass, you can also use type(self) or self.__class__ (OK, but which one) inside __init__ to get the containing class. This works well lots of layers deep (which shouldn't happen anyway), and requires the argument passed to super to be the type of the instance (which it should be anyway) but breaks if you subclass, as seen here. The concept might be clearer to you than scoping rules:
class MainClass:
class Inner:
pass
class InnerSub(Inner):
def __init__(self):
print(super(self.__class__))
print(super(type(self)))
MainClass().InnerSub()
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.
I frequently have simple classes which I'll only ever want a single instance of. As a simple example:
import datetime
import sys
class PS1(object):
def __repr__(self):
now = datetime.datetime.now()
return str(now.strftime("%H:%M:%S"))
sys.ps1 = PS1()
Is there a way that I could somehow combine the definition and instantiation into a single step and achieve the same results?
As another example, just as something that is simple enough to understand.
class Example(object):
def methodOne(self, a, b):
return a + b
def methodTwo(self, a, b):
return a * b
example = Example()
I googled around and found nothing (lots of people throwing around the words one-off and anonymous but nobody seems to be talking about the same thing I am). I tried this, but it didn't work:
example = class(object):
def methodOne(self, a, b):
return a + b
def methodTwo(self, a, b):
return a * b
I realize I don't gain much, just one line I don't have to type plus one fewer things in my namespace, so I understand if this doesn't exist.
I think you don't see this often because it's really hard to read, but ...
sys.ps1 = type('PS1', (object,), {'__repr__': lambda self: datetime.datetime.now().strftime('%H:%M:%S')})()
would do the trick here...
I use type to dynmically create a class (the arguments are name, base classes, class dictionary). The class dictionary just consists of a single function __repr__ in this case.
Hopefully we can agree that the full format is much easier to grok and use ;-).
You could use a simple class decorator to replace the class with an instance of it:
def instantiator(cls):
return cls()
Then use it like this:
#instantiator
class PS1(object):
def __repr__(self):
now = datetime.datetime.now()
return str(now.strftime("%H:%M:%S"))
Then:
>>> PS1
11:53:37
If you do this, you might want to make the class name lowercase, since it will ultimately be used to name an instance, not a class.
This still requires an extra line, but not an extra name in the namespace.
If you really wanted to, you could write a metaclass that does the same thing, but automatically. However, I don't really think this would save much effort over just instantiating the class manually, and it would definitely make the code more complex and difficult to understand.
You could use a metaclass, so you can still use prettier syntax in comparison to #mgilson's answer.
class OneOff(type):
def __new__(cls, name, bases, attrs):
klass = type.__new__(cls, name, bases, attrs)
return klass()
class PS1(object):
__metaclass__ = OneOff
...
However, I'm with the others saying that I'm not sure this is a great idea. I did something like this once, but it was for a very specific usecase, and I'd really think about exploring other avenues first. Also, this looks an awful lot like a singleton/borg, so maybe that would be the better way for you to go.
(#mgilson's answer achieves what you're looking for in the most direct way. I second him on the opinion your original code is better than any of the answers here)
A simpler, more readable alternative, only if you don't need to use any special functions (e.g. __repr__), just use a dict of functions (playing the role of the methods):
fake_obj = dict(method_one = lambda a,b: a+b, method_two = lambda a,b: a*b)
There are two ways to do this in python. One is to instantiate a singleton object which can be done with a decorator, another is to make the class itself the used object with class methods and class variables.
The first option (singleton) looks like this:
def apply_class(*args, **kwargs):
def myclass(c):
c(*args,**kwargs)
return myclass
#apply_class(5)
class mysingleton(object):
def __init__(self, x):
print x
The second option (class methods/variables) looks like this:
class mysingleton:
myvariable = 5
#classmethod
def mymethod(cls):
print cls.myvariable
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.)