how to get class name of a class static method through inspection - python

I found same similar question, but my question is diffent
def trace ():
?
class A():
#staticmethod
def Aha():
trace ()
...
I want the trace output
A.Aha() was called
I have known how to get function name through inspection, and get class name of instance.method, such this:
self_argument = frame.f_code.co_varnames[0] # This *should* be 'self'.
instance = frame.f_locals[self_argument]
class_name = instance.__class__.__name__
but class static method have not self argument, what should I do ?

That is the very definition of a static method: it is called without a class argument (as in class methods) and without an instance argument (as in instance methods). The only real difference between a function declared in module scope and a static method is that the method name is defined in the class' namespace and not in the module's namespace.
In other words, you can't get to the class object directly. You can get the function name by examining the stack (although I am not sure how useful it is):
>>> import sys
>>> import traceback
>>> class A(object):
#staticmethod
def a():
trace()
>>> def trace():
print traceback.extract_stack(sys._getframe())[-3][3]
>>> A.a()
A.a()
And given the name, you could get to the class object by extracting from the name and looking it up in the module's namespace...
For reference:
frame # -1 : call to traceback.extract_stack()
frame # -2 : call to trace()
frame # -3 : call to A.a()

You can try to create a wrapper/decorator for Aha. I suggest you to read this and this if you don't know that decorators are.
Something like the following should print out the function name and then call the function.
def wrapper(func):
def inner(*args, **kwargs):
print("function {0} has been called".format(func.__name__))
return func(*args, **kwargs)
return inner
#wrapper
def f():
print "I'm in the function
returns
In [16]: f()
function f has been called
in the function

Related

Python: Call derived class method from another class

I have searched all the related this stackoverflow question but its not satisfied my issue.
BaseHandler.py
class BaseHandler(object):
def __init__(self, rHandler, path, param):
self._rHandler = rHandler
self._server = self._rHandler.server
self._path = path
self._param = param
def _getElement(self, name):
return name + "append"
MyClass.py
class MyClass(BaseHandler.BaseHandler):
def getA(self):
print "Some info"
def getB(self):
el = self._getElement("T") #baseclass method
print ebl
I wanted to call getB from the below class.
RThread.py
import MyClass
class RThread(object):
def someMethod(self):
clr = MyClass.MyClass
clr.getB()
I am getting the following error:
TypeError: unbound method getB() must be called with MyClass instance as first argument (got nothing instead)
When I try the following:
clr = MyClass.MyClass()
I am getting the following error:
init() takes exactly 4 arguments (1 given)
So kindly help me how to call this method from different class.
You need to instantiate the class in order to call a method on it.
def someMethod(self):
clr = MyClass.MyClass(*args)
clr.getB()
In the case you want the method to be callable from the class you need to use either #staticmethod or #classmethod
#staticmethod
def getB():
return self._getElement("T")
However, you are using the self. notation which requires an instance. So you would need to flag the _getElement method with #staticmethod as well. Static methods do not have access to the parent class. You can use the #classmethod decorator to do so.
#classmethod
def getB(cls):
return cls._getElement("T")
You're not calling the method correctly; you need to create an object. This is how you create an object, which is what you were doing, except you weren't passing in enough parameters.
clr = MyClass.MyClass()
Since MyClass inherits from BaseHandler and you did not override its constructor, you're using the constructor from BaseHandler, which has four arguments, one of which is self.
def __init__(self, rHandler, path, param):
...
So, try something like this:
clr = MyClass.MyClass(arg1, arg2, arg3)
clr.getB()

In python, can I access a method in class scope (but not in function scope)

For better encapsulation, I want to decorate instance methods with methods inside the same class.
class SomeClass(object):
#staticmethod
def some_decorator(func):
def wrapped(self):
print 'hello'
return func(self)
return wrapped
#some_decorator
def do(self):
print 'world'
x = SomeClass()
x.do()
However, this piece of code raises TypeError: 'staticmethod' object is not callable
Now I make a workaround by defining a class and overload its new method to simulate a function, but it's eventually a class, not a function.
So can I access my functions inside the class scope?
Just get rid of that #staticmethod line. You want some_decorator to behave like a plain function, not like some kind of method.
The decorator is called when the class definition is being executed, before the class object itself exists. The normal method definitions inside a class are actually just plain old functions, they become methods dynamically each time they are called as attributes of the class instance (which turns them into bound methods). But while the class object itself is being built you can treat them as plain functions.
class SomeClass(object):
def some_decorator(func):
def wrapped(self):
print 'hello'
return func(self)
return wrapped
#some_decorator
def do(self):
print 'world'
x = SomeClass()
x.do()
output
hello
world
BTW, you have an error in your decorator: it's returning wrapped() instead of wrapped.
As chepner mentions in the comments we can delete some_decorator so that it doesn't take up space in the class object after we've finished using it in the class definition. (If we accidentally try to call it we'll get an error). We could do del SomeClass.some_decorator after the class definition, but it's also perfectly valid to put a del statement inside the class definition:
class SomeClass(object):
def some_decorator(func):
def wrapped(self):
print 'hello'
return func(self)
return wrapped
#some_decorator
def do(self):
print 'world'
del some_decorator

Python - create additional statements when calling inherited method

Let's say I have this:
class Foo:
...
def func():
return 1+2
class Bar(Foo):
...
def another_func():
# additional stuff I want to do when my parent's func() is called
I don't want to override func , but I do want to add some additional statements when it's called. Also, I don't want to change the original Foo.func.
Is it even possible? If not, any idea for a workaround?
There is no way of doing that, the canonical solution would be to overide func und wrap the original function like so:
class Bar(Foo):
...
def func():
# additional stuff I want to do when my parent's func() is called
res = super(Bar, self).func() # super().func() on Py3
# additional stuff I want to do after my parent's func() is called
return res
You need to override the func function and make the call to parent's func from within it. Python has super() for that purpose:
super(type[, object-or-type])
Return a proxy object that delegates method calls to a parent or sibling class of type.
This is useful for accessing inherited methods that have been overridden in a class.
The search order is same as that used by getattr() except that the type itself is skipped.
Example:
class Foo(object):
def func(self):
print "In parent"
class Bar(Foo):
def func(self):
super(Bar, self).func()
print 'In child' # Your additonal stuff
When you will run the func of Bar as:
b = Bar()
b.func()
will print:
In parent # <-- from Foo.func()
In child # <-- from Bar.func()

Define a method outside of class definition?

class MyClass:
def myFunc(self):
pass
Can I create MyFunc() outside of the class definition, maybe even in another module?
Yes. You can define a function outside of a class and then use it in the class body as a method:
def func(self):
print("func")
class MyClass:
myMethod = func
You can also add a function to a class after it has been defined:
class MyClass:
pass
def func(self):
print("func")
MyClass.myMethod = func
You can define the function and the class in different modules if you want, but I'd advise against defining the class in one module then importing it in another and adding methods to it dynamically (as in my second example), because then you'd have surprisingly different behaviour from the class depending on whether or not another module has been imported.
I would point out that while this is possible in Python, it's a bit unusual. You mention in a comment that "users are allowed to add more" methods. That sounds odd. If you're writing a library you probably don't want users of the library to add methods dynamically to classes in the library. It's more normal for users of a library to create their own subclass that inherits from your class than to change yours directly.
I'd also add a reminder that functions don't have to be in classes at all. Python isn't like Java or C# and you can just have functions that aren't part of any class. If you want to group together functions you can just put them together in the same module, and you can nest modules inside packages. Only use classes when you need to create a new data type, not just to group functions together.
You can define a function outside of a class and then add it. However, there is a subtle difference in assigning the function to the class or to the instance object. Here is an example:
class MyClass1(object):
def __init__(self, bar):
self.foo = 'up'
MyClass1.foobar = bar
class MyClass2(object):
def __init__(self, bar):
self.foo = 'up'
self.foobar = bar
def bar(self):
return "What's " + self.foo
Let's first look at what is happening in MyClass1. foobar in this class is similar to a normal method as though it was defined inside the class definition (i.e. it is a method bound to the instance of this class). Let's take a look at what this looks like...
In [2]: x = MyClass1(bar)
In [3]: x.foobar
Out[3]: <bound method MyClass1.bar of <__main__.MyClass1 object at 0x104346990>>
In [4]: x.foobar()
Out[4]: "What's up"
How does this differ from MyClass2? In MyClass2, foobar is simply a reference to the bar function and is NOT a bound method. Because of this we must pass the instance in for this function to work properly. e.g.
In [5]: y = MyClass2(bar)
In [6]: y.foobar
Out[6]: <function __main__.bar>
In [7]: y.foobar()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-6feb04878e5f> in <module>()
----> 1 y.foobar()
TypeError: bar() takes exactly 1 argument (0 given)
In [8]: y.foobar(y)
Out[8]: "What's up"
Although I'm not sure if this is ever good practice to be doing it this way...
Yes you can definitely have functions outside of a class. Here is a mini example...
def date_parse(date_string):
return date(date_string)
class MyClass:
def myFunc(self):
pass
def myDateFunc(self, date_string):
self.date = date_parse(date_string)
I give a shoot at what you are looking for, where one class Helper provides functions to a specialized class (MyClass)
class Helper(object):
def add(self, a, b):
return a + b
def mul(self, a, b):
return a * b
class MyClass(Helper):
def __init__(self):
Helper.__init__(self)
print self.add(1, 1)
if __name__ == '__main__':
obj = MyClass()
This will print
>>> 2
You can!
For example:
In django this is the view function and it just stay in the views module in my app
def user_list_view(request):
queryset = User.objects.all()
return render(request, 'list_user_users.html', {'object_list': queryset})
And in the url routing module I just import it from the module and use it there is no class whatsoever
from . import views
from django.urls import path
urlpatterns = [
# homepage of app
path('', views.user_list_view),

How to access the parent class during initialisation in python?

How do I find out which class I am initialising a decorator in? It makes sense that I wouldn't be able to find this out as the decorator is not yet bound to the class, but is there a way of getting round this?
class A(object):
def dec(f):
# I am in class 'A'
def func(cls):
f(cls)
return func
#dec
def test(self):
pass
I need to know which class I am (indicated by the commented line).
I don't think this is possible. At the very moment when you define test, the class doesn't exist yet.
When Python encounters
class A(object):
it creates a new namespace in which it runs all code that it finds in the class definition (including the definition of test() and the call to the decorator), and when it's done, it creates a new class object and puts everything into this class that was left in the namespace after the code was executed.
So when the decorator is called, it doesn't know anything yet. At this moment, test is just a function.
I don't get the question.
>>> class A(object):
def dec(f):
def func(cls):
print cls
return func
#dec
def test(self):
pass
>>> a=A()
>>> a.test()
<__main__.A object at 0x00C56330>
>>>
The argument (cls) is the class, A.
As Nadia pointed out you will need to be more specific. Python does not allow this kind of things, which means that what you are trying to do is probably something wrong.
In the meantime, here is my contribution: a little story about a sailor and a frog. (use a constructor after the class initialization)
class Cruise(object):
def arewelostyet(self):
print 'Young sailor: I think I am lost, help me :s'
instance = Cruise()
instance.arewelostyet()
def whereami(lostfunc):
"""
decorator
"""
def decorated(*args, **kwargs):
lostfunc(*args, **kwargs)
print 'Frog: Crôak! thou art sailing in class', lostfunc.im_class.__name__
# don't forget to write name and doc
decorated.func_name = lostfunc.func_name
decorated.func_doc = lostfunc.func_name
return decorated
print '[i]A frog pops out of nowhere[/i]'
# decorate the method:
Cruise.arewelostyet = whereami(Cruise.arewelostyet)
instance.arewelostyet()

Categories

Resources