3

Say that I have a function like the following:

def eggs(a,b,c):
 if c.foo:
 return a + b.bar
 else:
 return c.spam

I'd like to have a higher order function capable of introspecting the function passed and retrieve what members of an argument are mentioned inside the code via the dot syntax, with the following behavior:

>>> member_inspector(eggs, 'c')
('foo','spam')
>>> member_inspector(eggs, 'b')
('bar')
>>> member_inspector(eggs, 'a')
()

Can this be done? How?

asked May 2, 2018 at 12:20
7
  • 3
    To what degree to you want to take this? What about getattr(c, 'b' + 'a' + 'r')? Or def eggs(c, p): getattr(c, p). These examples are only evaluated at runtime and cannot be introspected. Commented May 2, 2018 at 12:22
  • Good question. I'm not interesed in methods called via getattr or other corner cases. I'm only considering the member resolution via the dot syntax. Commented May 2, 2018 at 12:27
  • 2
    What if the function does something like foo = c and then accesses foo.spam? Commented May 2, 2018 at 12:29
  • Then member_inspector(eggs, 'c') returns (). I'm not interested in backtracking variable assignments (unless someone comes up with a very simple way to include it as a plus) Commented May 2, 2018 at 12:33
  • 1
    @MadPhysicist It sure is. I'm referring to the fact that a textual inspection of the code of the function passed should only care about the dot syntax. Commented May 2, 2018 at 12:40

1 Answer 1

5

Here's a basic version:

import inspect
from textwrap import dedent
import ast
def member_inspector(f, var):
 source = dedent(inspect.getsource(f))
 module = ast.parse(source)
 func = module.body[0]
 result = []
 for stmt in func.body:
 for node in ast.walk(stmt):
 if (isinstance(node, ast.Attribute) and
 isinstance(node.value, ast.Name) and
 node.value.id == var):
 result.append(node.attr)
 return result
answered May 2, 2018 at 12:30
Sign up to request clarification or add additional context in comments.

1 Comment

Could I ask you for a bit of explanation, maybe some links to the ast module docs, and maybe even a "caveats" section? (Doesn't work if the function's source code can't be accessed, doesn't detect attribute access with getattr or vars or __dict__, gets tripped up by assignments like foo = c; c.bar, if the same attribute is accessed twice it's included in the output twice, etc.) Your code is good, but the answer is not.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.