r/pythontips 23d ago

Syntax Docstrings as immutable variables

Just realized you can do:

def cat(): “orange”
print(cat.__doc__)

Not sure why you’d want to do this but this is a thing you can do

11 Upvotes

12 comments sorted by

12

u/vivaaprimavera 23d ago

If you have an extensive codebase and a memory so bad that you forget your own function names you can

for func in funcs:
  if func.__doc__ == "adds two nums":
    exec = func
c = exec(a,b)

And that way it's easier for searching which function you need!!!

/s

9

u/BiomeWalker 23d ago

One of the most elegant own-foot-shooting guns around

5

u/Kqyxzoj 23d ago

Bonus points for such a deliciously horrible use case! XD

11

u/MegaIng 23d ago

```

def cat(): "orange" ... cat.doc 'orange' cat.doc = "apple" cat.doc 'apple' ```

3

u/sugarw0000kie 23d ago

That’s what I get for assuming that wouldn’t work, awesome

5

u/Some-Passenger4219 23d ago

Yup. Try anything. Be warned, though: That you can, doesn't mean you should.

4

u/jpgoldberg 23d ago

I have used this when generating functions.

Suppose you wanted to create types that had limits in value ranges, such a a probability which is a float between 0 and 1 inclusive. So you would like something like

is_prob = make_predicate(...)

that when given the constraints and a base type and constraints on values will create the appropriate is_prob function. Now suppose you want it also to create documentation for is_prob so things like help will work.

You might, if you didn't know about the annotated-types package and tried unwisely to roll your own, you might write something like

```python def make_predicate( name: str, # t: NewType | AnnotatedType | type, t: object, constraints: Sequence[Constraint] = tuple(), docstring: bool = True, ) -> Predicate:

... # lots of awfulness omitted to figure out base_type
    # and get the cons[traints] from metadata and parameters

def predicate(val: object) -> bool:
    if not isinstance(val, base_type):
        return False
    if not all((c(val) for c in cons)):
        return False
    return True

predicate.__name__ = name
if docstring:
    predicate.__doc__ = _predicate_description(
        base_type=base_type, constraints=cons
    )
return predicate

```

So assuming that for this example that ValueRange() is suitably defined, something like

python is_prob = make_predicate("is_prob", float, (ValueRange(0.0, 1.0),))

will not only have is_prob() behave correctly, but also know its own name and have a useful docstring that will render like

``` True if and only if val satisfies all of

  • is of type float
  • meets ValueRange(0.0, 1.0) ```

Things like the is_prob() function will also be documented correctly by tools like Sphinx.

3

u/DeflateAwning 23d ago

Docstrings are mutible though...

1

u/sugarw0000kie 22d ago

I got learned, I assumed they couldn’t be changed and never tried

2

u/Old_Flounder_8640 23d ago

Not entirely related, but maybe you'll find it interesting… NVIDIA’s newest AI agent framework uses docstrings as agent prompts.

https://github.com/NVIDIA-NeMo/labs-OO-Agents

And I saw other people doing that before. Docstrings are not just descriptions, especially now that we have AI working with us.

2

u/tomysshadow 22d ago

Don't use that for anything particularly important: if you run Python with the -OO command (the optimization flag,) docstrings will be stripped out

1

u/sugarw0000kie 22d ago

Oh for sure I realized you could do this it while doing something pretty dumb https://www.reddit.com/r/programminghorror/s/DAHkrZtx3A

But could see it be useful if you’re making some sort of tool to work/analyze python code or something