calling function of one class from other class in python - python

Suppose I have following code
class ter:
def func1()
def func2()
class fg:
def gl1()
def gl2()
ifTrue)
ter.func1() # func1 from class ter
How can I call func1 of class ter from class fg? ter.func1() is not working.

Since ter is the name of the class, ter.func1() is the syntax for calling a #staticmethod or (#classmethod). Generally, you shouldn't use classes in Python just for organizing functions; instead you'd use a "free function" or module-level function.
If you actually have an instance of the class ter, then you call the function on that name:
# Call an "instance method" on Person object
class Person:
def __init__(self, name): # Constructor
self.name = name
def sayHello(self): # Class method (requires `self` parameter)
print 'Hello, {0}'.format(self.name)
def main():
p = Person('Joe') # Instantiate `Person` class (calls constructor)
p.sayHello() # Call an "instance method" on Person object
If you're sure you want to use static methods:
class Person:
def __init__(self, name): # Constructor
self.name = name
def sayHello(self): # Class method (requires `self` parameter)
print 'Hello, {0}'.format(self.name)
#staticmethod
def makePerson(name): # Static Method (note, no `self` parameter)
p = Person(name)
return p
#classmethod
def makePerson2(cls, name): # Class method. First parameter is class
p = cls(name) # Call constructor for that class
return p
def main():
p2 = Person.makePerson('Joe') # Call static "factory" method
p2.sayHello()
Finally, even though Python doesn't have braces/brackets, it is very picky about syntax. If you're not going to declare a body of a method, you must use the pass keyword:
def foo():
pass # This function does nothing

class ter:
def func1(self):
print 'I am func1'
def func2(self):
pass
class fg:
def gl1(self):
pass
def gl2(self):
ter_object=ter()
ter_object.func1()
This should print I am func1.
The point to remember here is that you must create instances of classes unless you call static methods

Related

Tracking decorated methods of children classes in python

In python, how can I setup a parent class to track methods with a specific decorator for each child seperatly? A quick code snippet of what I am trying to do:
class Parent:
decorated_func_dict = {} #dictionary that stores name->func for decorated functions
def get_func_by_decorator_name(self, name):
#stuff
pass
class Child1(Parent):
#func_name("Bob")
def bob_func(self, *args):
pass
#func_name("Tom")
def func2(self, *args):
pass
class Child2(Parent):
#func_name("Bob")
def func_bob2(self, *args):
pass
foo = Child1()
bar = Child2()
foo.get_func_by_decorator_name("Bob")
#Returns foo.bob_func
bar.get_func_by_decorator_name("Bob")
#Returns bar.func_bob2
Using Python 3.9.
A decorator is not something that makes a function look pretty. It is a callable that ingests an object (not only functions), does some arbitrary operations, and returns a replacement object.
In this case, your decorator should be storing references to function objects in a dictionary somewhere. The problem is that you won't be able to reference the class in which the functions are defined until it is created, which happens well after the decorator is run. You can avoid this by storing the name of the class as well as the name of the function.
The final step here is to properly bind the function objects to methods on the right object. That is something that get_func_by_decorated_name can do for you.
In sum, you can write something like this:
decorated_func_dict = {}
def func_name(cls_name, func_name):
def decorator(func):
decorated_func_dict.setdefault(cls_name, {})[func_name] = func
return func
return decorator
class Parent:
def get_func_by_decorator_name(self, name):
return decorated_func_dict[type(self).__name__][name].__get__(self)
class Child1(Parent):
#func_name("Child1", "Bob")
def bob_func(self, *args):
pass
#func_name("Child1", "Tom")
def func2(self, *args):
pass
class Child2(Parent):
#func_name("Child2", "Bob")
def func_bob2(self, *args):
pass
And indeed you get:
>>> foo.get_func_by_decorator_name("Bob")
<bound method Child1.bob_func of <__main__.Child1 object at 0x000001D58181E070>>
>>> bar.get_func_by_decorator_name("Bob")
<bound method Child2.func_bob2 of <__main__.Child2 object at 0x000001D582041F10>>
Another way to do this is to give your functions a name attribute, which you can then aggregate into a mapping in __init_subclass__ in Parent. This allows you to make an interface a bit closer to what you originally intended:
def func_name(func_name):
def decorator(func):
func.special_name = func_name
return func
return decorator
class Parent:
def __init_subclass__(cls):
cls.decorated_func_dict = {}
for item in cls.__dict__.values():
if hasattr(item, 'special_name'):
cls.decorated_func_dict[item.special_name] = item
del item.special_name # optional
def get_func_by_decorator_name(self, name):
return self.decorated_func_dict[name].__get__(self)
class Child1(Parent):
#func_name("Bob")
def bob_func(self, *args):
pass
#func_name("Tom")
def func2(self, *args):
pass
class Child2(Parent):
#func_name("Bob")
def func_bob2(self, *args):
pass
The results are identical to the first example.
The easiest way would of course be to get access to the child's namespace before the class is created, e.g. with a metaclass.

Can't get method name when using decorator

I suppose I'm missing something obvious, but I can't get the name of methods when I'm using decorators. When I run this code, I get the error:
AttributeError: 'str' object has no attribute "__name__"
Could somebody tell me how I can get the name of these decorated method?
Thanks
def Print(*arg, **kwarg):
func, *arguments = arg
print(func.__name__ + "(): {}".format(func=arguments[0]))
class Bob(object):
def __init__(self):
pass
#property
def stuff(self):
return "value from stuff property"
#stuff.setter
def stuff(self, noise):
return noise
class Tester:
def __init__(self):
self.dylan = Bob()
def randomTest(self):
Print(self.dylan.stuff, 1)
if __name__ == "__main__":
whatever = Tester()
whatever.randomTest()
stuff isn't a function or a method; it's a property. The syntax
#property
def stuff(...):
...
creates an instance of the property class using stuff as the argument to property, equivalent to
def stuff(...):
....
stuff = property(stuff)
and instances of property don't have a __name__ attribute, as you've seen.
(It's a little trickier with the setter, since the function and the property have to have the same name. But defining stuff a "second" time doesn't override the existing property named stuff.)
The individual methods are accessed via attributes of the property.
>>> Bob.stuff.fget.__name__
'stuff'
>>> Bob.stuff.fset.__name__
'stuff'
Note another, longer, way to create the same property:
class Bob:
def stuff_getter(self):
...
def stuff_setter(self, noise):
...
stuff = property(stuff_getter, stuff_setter)
del stuff_getter, stuff_setter # Clean up the namespace
def Print(*arg, **kwarg):
func, *arguments = arg
print(func.__name__ + "(): {}".format(func=arguments[0]))
class Bob():
def __init__(self, s):
self.stuff = s
#property
def myStuff(self):
return self.stuff
#myStuff.setter
def setStuff(self, noise):
self.stuff = noise
class Tester:
def __init__(self):
self.dylan = Bob(1)
def randomTest(self):
print(self.dylan.stuff)
if __name__ == "__main__":
whatever = Tester()
whatever.randomTest()
This should work :)

Access derived class attribute in base class function decorator

I want to do something like:
class A(Resource):
#dec(from_file=A.docpath)
def get(self):
pass
class B(A):
docpath = './docs/doc_for_get_b.json'
class C(A):
docpath = './docs/doc_for_get_c.json'
def dec(*args, **kwargs):
def inner(f):
docpath = kwargs.get('from_file')
f.__kwargs__ = open(path, 'r').read()
return f
return inner
The functions that will be called are B.get and C.get, never A.get.
How can I access the custom attribute docpath defined in class B or class C and pass it to the decorator of the get function in class A ?
Current solution: Put the decorator on each derived class ...
class A(Resource):
def _get(self):
pass
class B(A):
#dec(from_file='./docs/doc_for_get_b.json')
def get(self):
return self._get()
class C(A)
#dec(from_file='./docs/doc_for_get_c.json')
def get(self):
return self._get()
This works but it's pretty ugly compared to the one-line declaration of the classes in the previous code.
To access a class's attributes inside the decorator is easy:
def decorator(function):
def inner(self):
self_type = type(self)
# self_type is now the class of the instance of the method that this
# decorator is wrapping
print('The class attribute docpath is %r' % self_type.docpath)
# need to pass self through because at the point function is
# decorated it has not been bound to an instance, and so it is just a
# normal function which takes self as the first argument.
function(self)
return inner
class A:
docpath = "A's docpath"
#decorator
def a_method(self):
print('a_method')
class B(A):
docpath = "B's docpath"
a = A()
a.a_method()
b = B()
b.a_method()
In general I've found using multiple levels of decorators, i.e. decorator factory functions that create decorators such as you've used and such as:
def decorator_factory(**kwargs):
def decorator_function(function):
def wrapper(self):
print('Wrapping function %s with kwargs %s' % (function.__name__, kwargs))
function(self)
return wrapper
return decorator_function
class A:
#decorator_factory(a=2, b=3)
def do_something(self):
print('do_something')
a = A()
a.do_something()
a difficult thing to get right and not easy to comprehend when reading code, so I would err towards using class attributes and generic superclass methods in favour of lots of decorators.
So in your case, don't pass the file path in as an argument to your decorator factory, but set it as a class attribute on your derived classes, and then write a generic method in your superclass that reads the class attribute from the instance's class.

How to assign an overridden parent class function as a callback function in python subclass

class Process(object):
def __init__(self, obj, callback):
if obj and hasattr(callback, 'im_self') and callback.im_self is obj:
self.obj = obj
self.callback=callback.im_func.__name__
else:
raise Exception('invalid callback')
class A(object):
def parse(self):
print 'in parse()'
return Process(self, callback=self.test)
def test(self):
print 'in class A'
class B(A):
def test(self):
print 'in class B'
# do something...
return Process(self, callback=super(B, self).test)
b=B()
p=b.parse()
callback = getattr(p.obj, str(p.callback))
p=callback()
callback = getattr(p.obj, str(p.callback))
callback()
output of the program:
in parse()
in class B
in class B
doesn't call A.test()
I am using Scrapy, it use this way in Process() to save callback function. How to call A.test() through B.test()?
Update due to comments
You are right. Both A and B are spider, A is a base spider, B has a special procedure, so want to call A.test() after B.test(). Have to change class B, it difficult to modify Scrapy’s source code.
class B(A):
def test_again(self):
return super(B,self).test()
def test(self):
print 'in class B'
return Process(self, callback=self.test_again)
You can't, not by only storing the name of the function. There isn't enough context there to distinguish between the original method and the override.
You'd either need to store the original method (e.g. not reach in and grab the original function) or pass in a different method that uses super() to call the original:
def original_test(self):
return super(B, self).test()
super() isn't limited to just the current method, after all.
Note that the method object .__name__ attribute will always return the wrapped function object .__name__ attribute, no need to unwrap the method just to get to that value.

Python decorator as a staticmethod

I'm trying to write a python class which uses a decorator function that needs information of the instance state. This is working as intended, but if I explicitly make the decorator a staticmetod, I get the following error:
Traceback (most recent call last):
File "tford.py", line 1, in <module>
class TFord(object):
File "tford.py", line 14, in TFord
#ensure_black
TypeError: 'staticmethod' object is not callable
Why?
Here is the code:
class TFord(object):
def __init__(self, color):
self.color = color
#staticmethod
def ensure_black(func):
def _aux(self, *args, **kwargs):
if self.color == 'black':
return func(*args, **kwargs)
else:
return None
return _aux
#ensure_black
def get():
return 'Here is your shiny new T-Ford'
if __name__ == '__main__':
ford_red = TFord('red')
ford_black = TFord('black')
print ford_red.get()
print ford_black.get()
And if I just remove the line #staticmethod, everything works, but I do not understand why. Shouldn't it need self as a first argument?
This is not how staticmethod is supposed to be used. staticmethod objects are descriptors that return the wrapped object, so they only work when accessed as classname.staticmethodname. Example
class A(object):
#staticmethod
def f():
pass
print A.f
print A.__dict__["f"]
prints
<function f at 0x8af45dc>
<staticmethod object at 0x8aa6a94>
Inside the scope of A, you would always get the latter object, which is not callable.
I'd strongly recommend to move the decorator to the module scope -- it does not seem to belong inside the class. If you want to keep it inside the class, don't make it a staticmethod, but rather simply del it at the end of the class body -- it's not meant to be used from outside the class in this case.
Python classes are created at runtime, after evaluating the contents of the class declaration. The class is evaluated by assigned all declared variables and functions to a special dictionary and using that dictionary to call type.__new__ (see customizing class creation).
So,
class A(B):
c = 1
is equivalent to:
A = type.__new__("A", (B,), {"c": 1})
When you annotate a method with #staticmethod, there is some special magic that happens AFTER the class is created with type.__new__. Inside class declaration scope, the #staticmethod function is just an instance of a staticmethod object, which you can't call. The decorator probably should just be declared above the class definition in the same module OR in a separate "decorate" module (depends on how many decorators you have). In general decorators should be declared outside of a class. One notable exception is the property class (see properties). In your case having the decorator inside a class declaration might make sense if you had something like a color class:
class Color(object):
def ___init__(self, color):
self.color = color
def ensure_same_color(f):
...
black = Color("black")
class TFord(object):
def __init__(self, color):
self.color = color
#black.ensure_same_color
def get():
return 'Here is your shiny new T-Ford'
Solution does exist!
Problem is that Static method that is trying to be used as decorator is in fact staticmethod object and is not callable.
Solution: staticmethod object has method __get__ which takes any argument and returns real method: python documentation Python 3.5 and up:
class StaticMethod(object):
"Emulate PyStaticMethod_Type() in Objects/funcobject.c"
def __init__(self, f):
self.f = f
def __get__(self, obj, objtype=None):
return self.f
Min solution I came with is:
class A():
def __init__(self):
self.n = 2
#staticmethod
def _returnBaseAndResult(func):
from functools import wraps
#wraps(func)
def wrapper(*args, **kwargs):
self = args[0]
response = func(*args, **kwargs)
return self.n, response
return wrapper
#_returnBaseAndResult.__get__('this can be anything')
def square(self):
return self.n**2
if __name__ == '__main__':
a = A()
print(a.square())
Will print (2, 4)
ensure_black is returning a _aux method that isn't decorated by #staticmethod
You can return a non-static method to a static_method
http://docs.python.org/library/functions.html#staticmethod

Categories