inspect.getmembers_static: Inspect Attributes Safely

Published on: August 30, 2026
Reading time: 2 minutes
Close-up view of a computer screen displaying code in a software development environment.

inspect.getmembers_static() lists attributes without using normal dynamic resolution. Unlike inspect.getmembers(), it avoids invoking many descriptors, properties, and custom __getattr__ or __getattribute__ paths. This makes it useful for documentation tools, debuggers, class analyzers, and API auditing.

The trade-off is that results may contain raw descriptor objects instead of computed values, and attributes created only at runtime may be absent.

Basic example

import inspect

class Example:
    @property
    def value(self):
        print("property executed")
        return 42

obj = Example()
print(inspect.getmembers_static(obj))

The property appears as a descriptor without executing its getter.

Difference from getmembers

inspect.getmembers(obj) performs normal attribute access and may execute arbitrary code. A property can open files, access a network, raise exceptions, or change state.

Filtering with predicate

members = inspect.getmembers_static(
    Example,
    predicate=inspect.isfunction,
)

The predicate receives each static value. Because descriptors are not bound, values can differ from normal attribute access.

Raw descriptors

Static inspection can return property, staticmethod, classmethod, and custom descriptor objects. This is useful when a tool needs the definition rather than the computed result.

for name, value in inspect.getmembers_static(Example):
    if isinstance(value, property):
        print(name, value.fget)

Inheritance and origin

To identify where an attribute was defined, walk the class MRO and inspect each class dictionary.

for cls in Example.__mro__:
    if "value" in vars(cls):
        print("defined on", cls)

Dynamic attributes may be missing

class Dynamic:
    def __getattr__(self, name):
        if name.startswith("field_"):
            return name.upper()
        raise AttributeError(name)

Those names are synthesized rather than stored, so static inspection does not discover them. That is expected.

Not a security sandbox

The function reduces accidental descriptor execution, but introspection is not isolation. Do not import untrusted modules or deserialize unsafe objects merely to analyze them.

Documentation generation

Documentation tools can collect descriptors, docstrings, and definitions statically, then explicitly resolve only trusted members.

Auditing properties

def list_properties(cls):
    return {
        name: value
        for name, value in inspect.getmembers_static(cls)
        if isinstance(value, property)
    }

staticmethod and classmethod

Normal access binds methods. Static inspection may return the wrapper object. Use __func__ when the original function must be analyzed.

Metaclasses

Metaclasses can synthesize attributes. Static inspection separates stored definitions from runtime behavior. This complements the internal guide to DynamicClassAttribute.

Comparing results

normal = {name for name, _ in inspect.getmembers(obj)}
static = {name for name, _ in inspect.getmembers_static(obj)}
print(normal - static)

The difference may reveal dynamic members. Run normal lookup only when its side effects are acceptable.

Common mistakes

  • Expecting computed property values.
  • Treating a raw staticmethod as a bound function.
  • Concluding that a dynamic attribute does not exist.
  • Calling normal inspection on unknown objects first.
  • Treating introspection as a security boundary.

Start with static inspection, recognize descriptor types explicitly, walk the MRO when origin matters, and resolve dynamic values only for trusted members. See the internal guides to inspect and inspect.signature.

Conclusion

inspect.getmembers_static exposes object structure while avoiding much dynamic execution. It is especially valuable for documentation, auditing, and descriptor analysis.

External sources

Share:

Facebook
WhatsApp
Twitter
LinkedIn

Article content

    Related articles

    Python code representing functools.Placeholder and positional arguments
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    functools.Placeholder: Flexible Arguments in partial

    Learn functools.Placeholder in Python 3.14 to build flexible partial and partialmethod calls with open positional arguments.

    Ler mais

    Tempo de leitura: 5 minutos
    17/10/2026
    Code on a screen representing Python t-strings
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    Python 3.14 T-strings: Structured Templates

    Learn Python t-strings in Python 3.14, inspect Template and Interpolation objects, and build structured, extensible renderers.

    Ler mais

    Tempo de leitura: 5 minutos
    16/10/2026
    CPU and memory modules representing Python shared_memory track
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    shared_memory track: Control the Resource Tracker

    Learn Python shared_memory track for safe resource tracking, ownership, cleanup, and independent process coordination.

    Ler mais

    Tempo de leitura: 5 minutos
    16/10/2026
    Data storage unit representing compression with Python compression.zstd
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    compression.zstd: Streaming and Safe Compression

    Learn Python compression.zstd for fast file and data compression with streaming, dictionaries, testing, and safe limits.

    Ler mais

    Tempo de leitura: 6 minutos
    15/10/2026
    Code on screen for diagnosing processes with Python sys.remote_exec
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    sys.remote_exec: Diagnose Running Python Processes

    Learn Python sys.remote_exec for diagnosing running processes with controlled scripts, strong permissions, and safe operational practices.

    Ler mais

    Tempo de leitura: 6 minutos
    15/10/2026
    Python code and environment configuration with os.reload_environ
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    os.reload_environ: Thread Safety and Environment

    Learn Python os.reload_environ to refresh externally changed environment variables with validation, compatibility, and thread-safety precautions.

    Ler mais

    Tempo de leitura: 4 minutos
    14/10/2026