Ik heb een wrapper-functie die een functie retourneert. Is er een manier om de docstring van de geretourneerde functie programmatisch in te stellen? Als ik naar __doc__
zou kunnen schrijven, zou ik het volgende doen:
def wrapper(a):
def add_something(b):
return a + b
add_something.__doc__ = 'Adds ' + str(a) + ' to `b`'
return add_something
Dan zou ik kunnen doen
>>> add_three = wrapper(3)
>>> add_three.__doc__
'Adds 3 to `b`
Omdat __doc__
echter alleen-lezen is, kan ik dat niet doen. Wat is de juiste manier?
Bewerken: Ok, ik wilde het simpel houden, maar dit is natuurlijk niet wat ik probeer te doen. Ook al is __doc__
over het algemeen beschrijfbaar, in mijn geval niet.
Ik probeer automatisch testcases te maken voor unittest
. Ik heb een wrapper-functie die een klasseobject maakt dat een subklasse is van unittest.TestCase
:
import unittest
def makeTestCase(filename, my_func):
class ATest(unittest.TestCase):
def testSomething(self):
# Running test in here with data in filename and function my_func
data = loadmat(filename)
result = my_func(data)
self.assertTrue(result > 0)
return ATest
Als ik deze klasse aanmaak en de docstring van testSomething
probeer in te stellen, krijg ik een foutmelding:
>>> def my_func(): pass
>>> MyTest = makeTestCase('some_filename', my_func)
>>> MyTest.testSomething.__doc__ = 'This should be my docstring'
AttributeError: attribute '__doc__' of 'instancemethod' objects is not writable
Antwoord 1, autoriteit 100%
Een instancemethod
haalt zijn docstring uit zijn __func__
. Wijzig in plaats daarvan de docstring van __func__
. (Het __doc__
attribuut van functies is beschrijfbaar.)
>>> class Foo(object):
... def bar(self):
... pass
...
>>> Foo.bar.__func__.__doc__ = "A super docstring"
>>> help(Foo.bar)
Help on method bar in module __main__:
bar(self) unbound __main__.Foo method
A super docstring
>>> foo = Foo()
>>> help(foo.bar)
Help on method bar in module __main__:
bar(self) method of __main__.Foo instance
A super docstring
Van de 2.7 documenten:
Door de gebruiker gedefinieerde methoden
Een door de gebruiker gedefinieerd methodeobject combineert een klasse, een klasse-instantie (of Geen) en elke aanroepbare
object (normaal gesproken een door de gebruiker gedefinieerde functie).Speciale alleen-lezen attributen: im_self is het instantieobject van de klasse, im_func is de functie
voorwerp; im_class is de klasse van im_self voor gebonden methoden of de klasse die om de . vroeg
methode voor ongebonden methoden;__doc__
is de documentatie van de methode (zelfde als
im_func.__doc__
);__name__
is de naam van de methode (hetzelfde alsim_func.__name__
);
__module__
is de naam van de module waarin de methode is gedefinieerd, of Geen indien niet beschikbaar.Gewijzigd in versie 2.2: im_self gebruikt om te verwijzen naar de klasse die de methode definieerde.
Gewijzigd in versie 2.6: voor 3.0 forward-compatibiliteit is im_func ook beschikbaar als
__func__
,en im_self als__self__
.
Antwoord 2, autoriteit 38%
Ik zou de docstring doorgeven aan de fabrieksfunctie en type
gebruiken om de klasse handmatig te construeren.
def make_testcase(filename, myfunc, docstring):
def test_something(self):
data = loadmat(filename)
result = myfunc(data)
self.assertTrue(result > 0)
clsdict = {'test_something': test_something,
'__doc__': docstring}
return type('ATest', (unittest.TestCase,), clsdict)
MyTest = makeTestCase('some_filename', my_func, 'This is a docstring')
Antwoord 3, autoriteit 20%
Dit is een aanvulling op het feit dat het __doc__
attribuut van klassen van het type type
niet kan worden gewijzigd. Het interessante punt is dat dit alleen waar is zolang de klasse is gemaakt met behulp van type. Zodra je een metaclass gebruikt, kun je eigenlijk gewoon __doc__
wijzigen.
Het voorbeeld gebruikt de abc (AbstractBaseClass) module. Het werkt met een speciale ABCMeta
metaclass
import abc
class MyNewClass(object):
__metaclass__ = abc.ABCMeta
MyClass.__doc__ = "Changing the docstring works !"
help(MyNewClass)
zal resulteren in
"""
Help on class MyNewClass in module __main__:
class MyNewClass(__builtin__.object)
| Changing the docstring works !
"""
Antwoord 4, autoriteit 16%
Gebruik gewoon decorateurs. Dit is jouw geval:
def add_doc(value):
def _doc(func):
func.__doc__ = value
return func
return _doc
import unittest
def makeTestCase(filename, my_func):
class ATest(unittest.TestCase):
@add_doc('This should be my docstring')
def testSomething(self):
# Running test in here with data in filename and function my_func
data = loadmat(filename)
result = my_func(data)
self.assertTrue(result > 0)
return ATest
def my_func(): pass
MyTest = makeTestCase('some_filename', my_func)
print MyTest.testSomething.__doc__
> 'This should be my docstring'
Hier is een vergelijkbare use-case: Dynamische hulp van Python en automatisch aanvullen
Antwoord 5, autoriteit 9%
__doc__
is niet alleen beschrijfbaar als uw object van het type ‘type’ is.
In jouw geval is add_three
een functie en kun je __doc__
gewoon instellen op een willekeurige tekenreeks.
Antwoord 6
In het geval dat u automatisch unittest.TestCase-subklassen probeert te genereren, heeft u mogelijk meer kilometers die hun shortDescription-methode.
Dit is de methode die de onderliggende docstring stript tot op de eerste regel, zoals te zien is in normale unittest-uitvoer; het negeren ervan was voldoende om ons controle te geven over wat er werd weergegeven in rapportagetools zoals TeamCity, wat we nodig hadden.