Extending or overwriting a docstring when composing classes - python

I have a class MyClass:
class MyClass(object):
def __init__(self):
pass
def my_function(self, x):
# MyClass.my_function.__doc__ is not writable!
# Otherwise, I could just set it here.
Origin.func(self, x)
The class borrows from Origin:
class Origin(object):
def func(obj, x):
"""This is a function
"""
# do stuff
pass
How can I copy the docstring from Origin.func to MyClass.my_function automatically so that Sphinx Autodoc recognises it? And how can I extend the original docstring by a couple of words?
Edit:
Afaik, I cannot just change __doc__ after the definition of the function since Sphinx would not find it then. Or if it did, where would the "docfix" go?

I'm not clear on exactly how Sphinx works, but assuming it reads from __doc__ rather than parsing the source, there are a number of options.
Consider the simpler example...
def add(x, y):
return x + y
...which is virtually identical to...
add = lambda x, y: x + y
In either case, you cannot refer to the symbol add inside its definition, since the symbol is not defined at that point. Nor can you refer to the function object which the symbol add will ultimately refer to, since it hasn't been created yet.
Therefore, you can only modify add.__doc__ after the symbol has been defined...
def add(x, y):
return x + y
add.__doc__ = 'This is my docstring'
...but this may be a little more verbose than we'd like.
Another option is to exploit the fact that the Python decorator syntax...
#my_decorator
def add(x, y):
return x + y
...is equivalent to...
def add(x, y):
return x + y
add = my_decorator(add)
...that is, although it's placed before the function definition, it's executed after the function is defined, so you can reference the function object inside the body of the decorator function.
A decorator function is required to return a callable object, but given that we have no need to change the behavior of the add function, we can just return the argument which is passed in to the decorator, so given the decorator function...
def set_fixed_docstring(func):
func.__doc___ = 'This is my docstring'
return func
...used like...
#set_fixed_docstring
def add(x, y):
return x + y
...is equivalent to...
def add(x, y):
return x + y
add = set_fixed_docstring(add)
...or...
def add(x, y):
return x + y
add.__doc__ = 'This is my docstring'
add = add
Obviously, a fixed docstring isn't much use here, so we need to parameterize the decorator, which is a little more complex.
In this instance, we need our decorator function to be callable with a string parameter, and to return a callable object which takes the target function as a parameter.
The most common way to do this is to define another function within the decorator function, such that the inner function can refer to symbols defined in the outer function. So the function...
def set_docstring_to(docstring):
def wrapper(func):
func.__doc___ = docstring
return func
return wrapper
...used like...
#set_docstring_to('This is my docstring')
def add(x, y):
return x + y
...is equivalent to...
def add(x, y):
return x + y
add = set_docstring_to('This is my docstring')(add)
...which boils down to the same code as before...
def add(x, y):
return x + y
add.__doc__ = 'This is my docstring'
add = add
Putting all this together, if you were to use a decorator like...
def copy_docstring_from(source):
def wrapper(func):
func.__doc__ = source.__doc__
return func
return wrapper
...then you can just do...
class Origin(object):
def func(obj, x):
"""This is a function
"""
# do stuff
pass
class MyClass(object):
def __init__(self):
pass
#copy_docstring_from(Origin.func)
def my_function(self, x):
# MyClass.my_function.__doc__ is not writable!
# Otherwise, I could just set it here.
Origin.func(self, x)
...which should achieve the desired result with the minimum amount of code.

Related

The pythonic way to construct a multimethod setter

We can use a #property to construct a getter and setter. This is a short example how we can do this:
class A:
def __init__(self,x):
self.x = x
#property
def x(self):
return self.__x
#x.setter
def x(self, x):
if x < 0:
self.__x = 0
elif x > 100:
self.__x = 100
else:
self.__x = x
My case seems to be more complicated.
class A:
def __init__(self, x):
self.__x = x
self.x1()
self.x2()
self.x3()
def x1(self):
self.__x1 = self.__x + 1
return self.__x1
def x2(self):
self.__x2 = self.__x1 + 2
return self.__x2
def x3(self):
self.__x3 = self.__x2 + 3
return self.__x3
if __name__ == "__main__":
a = A(3)
print(a.x3)
Methods x1, x2 and x3 are oversimplified. The self.__x3 variable is set only once, when the __init__ method is called. Now, I need a getter method to get self.__x3 by calling a.x3. How to achieve that in the pythonic way?
Attempting an answer based on the assumption that you want the __x# variables modified only during __init__, and never again, but also want the accessors to follow the same code path (possibly because the read is also programmatically complex):
In this case, you can have the implementing function take an additional, defaulted argument. When accessed in attribute form, it will receive the defaulted argument, but if the fget member of the property is explicitly accessed, it can be called with the non-default argument. A simple example addressing x1 only:
class A:
def __init__(self, x):
self.__x = x
# Access the property itself off the class, bypassing execution,
# then call it directly with the non-default argument
type(self).x1.fget(self, True)
#property
def x1(self, doset=False):
if doset:
self.__x1 = self.__x + 1
return self.__x1
Alternatively, to simplify the usage in __init__, you can use a separate name for the underlying function vs. the property to achieve the same effect:
class A:
def __init__(self, x):
self.__x = x
# Call the implementing function directly with the non-default argument
self._x1(True)
# Implementing function named with single underscore prefix to indicate it's
# for internal/protected use only
def _x1(self, doset=False):
if doset:
self.__x1 = self.__x + 1
return self.__x1
# Define property x1 based on x1 for outside use
x1 = property(_x1)
Of course, if you don't have a complicated getter path, then the real solution is to separate _x1 from x1 completely, where _x1 is pure setter helper function for __init__, and x1 is pure getter:
class A:
def __init__(self, x):
self.__x = x
# Call the init helper
self._init_x1()
# Implementing function named with single underscore prefix to indicate it's
# for internal/protected use only
def _init_x1(self):
self.__x1 = self.__x + 1
#property:
def x1(self):
return self.__x1
To be clear, only the last of these is "Pythonic" in any meaningful sense. The second option has some limited use cases (where you have a function that demands existence, and is highly configurable, but has a reasonable set of defaults that a property could use), but in that case, it's usually a function that has public utility just like the property. Option #1 is the least Pythonic, as it's inconvenient to use (needing to elevate to the class type, extract the fget member, and explicitly pass self), and makes it quite clear that there is no expected use case outside of __init__ (because it's such a pain to use that no one would bother).

Anonymous function / Closure issue

I want to create a class Objective with an implemented call-function. The clue is, when initializing the Objective class a variable called function is handed over which can be either a mathematical function string or a python function itself. The __init__ has now the task to find out what the input is (string or callable function) and declare the variable/function func, which is return of the __call__.
The code right now looks a little like this:
class Objective():
def __init__(self, function):
if isinstance(function, str):
def func(self,x):
return eval(function,x)
elif callable(function):
self.func = function
def __call__(self, x):
return self.func(x)
And the declaration could look a little something like this:
def calc1(x):
return x+1
f = Objective(calc1)
f(1) --> f = 2
OR
f2 = Objective("x+1")
f2(1) --> f2 = 2
Now, as some of you might already noticed, the code won't work if the input is a string, because the definition of the function func only works within the __init__ (and yes, I know, the implementation of eval is not 100% correct either, but for simplicity I wrote it like this). My question is, how do I declare the function func within the if statement of the __init__ function? I hope I could explain my issue understandably.
The way you add any instance variable, self.func = func:
class Objective():
def __init__(self, function):
if isinstance(function, str):
def func(x): # no need for self
return eval(function, locals())
self.func = func # here
elif callable(function):
self.func = function
def __call__(self, x):
return self.func(x)
Note, you don't need self in your definition of func. Also note, you haven't used an anonymous function anywhere. You've used a normal function definition.
Finally, (even though you probably shouldn't be doing this), you need to get x into the namespaces available to eval, so, something to the effect of:
return eval(function, locals())

python: how does a decorator to `__init__` work?

Given a function
#mydecorator
def f(x):
...
f(5)
I could remove the decorator and call the function as
mydecorator(f)(5)
How does that translate to object methods? Especially __init__??
For example, I have created a decorator
class TestClass:
#mydecorator
def __init__(self, x, y):
...
that modifies arguments passed to __init__. I would like to remove it, and apply it manually only on instances I want to
what is the appropriate syntax to do that? (eg, something like myinstance = mydecorator(TestClass)(...))
would the fact that __new__ is called before __init__ affect the behavior?
The decorator doesn't really modify the arguments. It's just a higher order function that returns a function given a function. You could for instance do this
def make_cooler_init(init):
def new_function(*args):
init(*args)
print(args)
return new_function
Using
class TestClass:
#make_cooler_init
def __init__(self, x, y):
self.x = x
self.y = y
This will only change the function to print the argument after init has been called, it won't change much. To modify behavior for only some instance, you could handle that in your decorator as you can gain access to the arguments and the default function.
def make_cooler_init(init):
def new_function(*args):
if args[1] == 'True':
init(*args)
else:
print(args)
return new_function

How to assign class method to class attribute? [duplicate]

This question already has answers here:
Calling a function of a module by using its name (a string)
(18 answers)
Closed 7 years ago.
I'm trying to assign class methods to class attribute, so I can call the methods from string. When using the class I want to call it from string like:
A.MAP['add'](x, y)
A.MAP['subtract'](x, y)
This is my current code:
class A:
MAP = {
'add' : A.add(x, y),
'subtract' : A.subtract(x, y),
}
#classmethod
def add(cls, x, y)
return x + y
#classmethod
def subtract(cls, x, y)
return x - y
However the result shown error that A is not defined at the line of assigning A.add to MAP['add']. For short functions I can use lambda. However, in case of a longer function, how can I achieve this design?
Note that when you try:
class A:
MAP = {
'add' : A.add(x, y),
'subtract' : A.subtract(x, y),
}
you are trying to access e.g. A.add before the name A exists (the class isn't bound to the name until definition completes) and before the name add exists (you haven't defined that method yet). Everything at the top level of the class definition is done in order.
You need to put the class methods into the dictionary after the class has been defined (they don't become callable until definition is complete):
class A:
MAP = {}
#classmethod
def add(cls, x, y): # note colon
return x + y
#classmethod
def subtract(cls, x, y): # also here
return x - y
A.MAP['add'] = A.add
A.MAP['subtract'] = A.subtract
Note that, as neither class method uses cls, you could make them #staticmethods instead. Or just use functions - Python isn't Java, you don't need to put everything into a class.
Alternatively, you can use getattr to access attributes (including class methods) by name:
>>> class A:
#classmethod
def add(cls, x, y):
return x + y
#classmethod
def subtract(cls, x, y):
return x - y
>>> getattr(A, 'add')(1, 2)
3
Please do not program in python like that, instead use a more standard oop approach like this:
#!/usr/bin/env python
class A:
def __init__(self):
pass
#classmethod
def add(self, x, y):
return x + y
#classmethod
def subtract(self, x, y):
return x - y
if __name__ == "__main__":
a = A()
print a.add(1,2) # ans: 3
print a.subtract(2,1) # ans: 1

Wrap calls to methods of a Python class

I would like to wrap a number of class methods in Python with the same wrapper.
Conceptually it would look something like this in the simplest scenario:
x = 0 # some arbitrary context
class Base(object):
def a(self):
print "a x: %s" % x
def b(self):
print "b x: %s" % x
class MixinWithX(Base):
"""Wrap"""
def a(self):
global x
x = 1
super(MixinWithX, self).a()
x = 0
def b(self):
global x
x = 1
super(MixinWithX, self).a()
x = 0
Of course, when there are more methods than a and b, this becomes a mess. It seems like there ought to be something simpler. Obviously x could be modified in a decorator but one still ends up having a long list of garbage, which instead of the above looks like:
from functools import wraps
def withx(f):
#wraps(f) # good practice
def wrapped(*args, **kwargs):
global x
x = 1
f(*args, **kwargs)
x = 0
return wrapped
class MixinWithX(Base):
"""Wrap"""
#withx
def a(self):
super(MixinWithX, self).a()
#withx
def b(self):
super(MixinWithX, self).b()
I thought about using __getattr__ in the mixin, but of course since methods such as a and b are already defined this is never called.
I also thought about using __getattribute__ but it returns the attribute, not wrapping the call. I suppose __getattribute__ could return a closure (example below) but I am not sure how sound a design that is. Here is an example:
class MixinWithX(Base):
# a list of the methods of our parent class (Base) that are wrapped
wrapped = ['a', 'b']
# application of the wrapper around the methods specified
def __getattribute__(self, name):
original = object.__getattribute__(self, name)
if name in wrapped:
def wrapped(self, *args, **kwargs):
global x
x = 1 # in this example, a context manager would be handy.
ret = original(*args, **kwargs)
x = 0
return ret
return wrapped
return original
It has occurred to me that there may be something built into Python that may alleviate the need to manually reproduce every method of the parent class that is to be wrapped. Or maybe a closure in __getattribute__ is the proper way to do this. I would be grateful for thoughts.
Here's my attempt, which allows for a more terse syntax...
x = 0 # some arbitrary context
# Define a simple function to return a wrapped class
def wrap_class(base, towrap):
class ClassWrapper(base):
def __getattribute__(self, name):
original = base.__getattribute__(self, name)
if name in towrap:
def func_wrapper(*args, **kwargs):
global x
x = 1
try:
return original(*args, **kwargs)
finally:
x = 0
return func_wrapper
return original
return ClassWrapper
# Our existing base class
class Base(object):
def a(self):
print "a x: %s" % x
def b(self):
print "b x: %s" % x
# Create a wrapped class in one line, without needing to define a new class
# for each class you want to wrap.
Wrapped = wrap_class(Base, ('a',))
# Now use it
m = Wrapped()
m.a()
m.b()
# ...or do it in one line...
m = wrap_class(Base, ('a',))()
...which outputs...
a x: 1
b x: 0
You can do this using decorators and inspect:
from functools import wraps
import inspect
def withx(f):
#wraps(f)
def wrapped(*args, **kwargs):
print "decorator"
x = 1
f(*args, **kwargs)
x = 0
return wrapped
class MyDecoratingBaseClass(object):
def __init__(self, *args, **kwargs):
for member in inspect.getmembers(self, predicate=inspect.ismethod):
if member[0] in self.wrapped_methods:
setattr(self, member[0], withx(member[1]))
class MyDecoratedSubClass(MyDecoratingBaseClass):
wrapped_methods = ['a', 'b']
def a(self):
print 'a'
def b(self):
print 'b'
def c(self):
print 'c'
if __name__ == '__main__':
my_instance = MyDecoratedSubClass()
my_instance.a()
my_instance.b()
my_instance.c()
Output:
decorator
a
decorator
b
c
There are two general directions I can think of which are useful in your case.
One is using a class decorator. Write a function which takes a class, and returns a class with the same set of methods, decorated (either by creating a new class by calling type(...), or by changing the input class in place).
EDIT: (the actual wrapping/inspecting code I had in mind is similar to
what #girasquid has in his answer, but connecting is done using decoration instead of mixin/inheritance, which I think is more flexible an robust.)
Which brings me to the second option, which is to use a metaclass, which may be cleaner (yet trickier if you're not used to working with metaclasses). If you don't have access to the definition of the original class, or don't want to change the original definition, you can subclass the original class, setting the metaclass on the derived.
There is a solution, and it's called a decorator. Google "python decorators" for lots of information.
The basic concept is that a decorator is a function which takes a function as a parameter, and returns a function:
def decorate_with_x(f)
def inner(self):
self.x = 1 #you must always use self to refer to member variables, even if you're not decorating
f(self)
self.x = 0
return inner
class Foo(object):
#decorate_with_x # #-syntax passes the function defined on next line
# to the function named s.t. it is equivalent to
# foo_func = decorate_with_x(foo_func)
def foo_func(self):
pass

Categories

Resources