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

    Code and XML structure for canonicalization with Python
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    ElementTree canonicalize: Normalize XML in Python

    Learn Python ElementTree canonicalize for stable XML comparisons, hashes, namespaces, comments, and signature preparation.

    Ler mais

    Tempo de leitura: 5 minutos
    22/10/2026
    Python programming code displayed on a screen
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    T-strings and templatelib: Structured Interpolation

    Learn Python t-strings and string.templatelib for structured interpolation, safer renderers, logging, and custom processing.

    Ler mais

    Tempo de leitura: 5 minutos
    22/10/2026
    SQLite database and Python code for selective iterdump export
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    SQLite iterdump: Create Selective Dumps in Python

    Learn sqlite3.Connection.iterdump filters for selective SQLite dumps, dependency checks, validation, and safer restoration.

    Ler mais

    Tempo de leitura: 4 minutos
    21/10/2026
    Code and files representing Python data compression
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    compression.zstd: Fast Zstandard in Python

    Learn Python compression.zstd for fast file and data compression, streaming, integrity checks, and safe decompression.

    Ler mais

    Tempo de leitura: 7 minutos
    21/10/2026
    Configuration file and code structure for Python ConfigParser
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    ConfigParser: Read INI Files Without Sections

    Learn Python ConfigParser unnamed sections with validation, typed values, compatibility, layered settings, and safe INI writing.

    Ler mais

    Tempo de leitura: 5 minutos
    20/10/2026
    Binary data and computer memory representing Python memoryview
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    memoryview count and index: Search Without Copies

    Learn Python memoryview count and index to search values in zero-copy buffers and validate binary data efficiently.

    Ler mais

    Tempo de leitura: 5 minutos
    20/10/2026