[Python] Dynamic read-only attributes in python instances

Discussão em 'Python' iniciado por Stack, Março 17, 2025.

  1. Stack

    Stack Membro Participativo

    EDIT This code contains several bugs, see jsbueno's answer below for a correct version

    I would like to create read-only attributes that dynamically retrieve values from an internal dictionary. I have tried to implement these as descriptors:

    from typing import Any

    class AttDesc:
    def __init__(self, name):
    self.name = name

    def __get__(self, obj, objtype=None):
    return obj._d[self.name]

    def __set__(self, obj, value):
    raise AtrributeError("Read only!")

    class A:
    def __init__(self, klist: list[str], vlist: list[Any]) -> None:
    self._d = dict(zip(klist, vlist))
    for k in self._d:
    setattr(type(self), k, AttDesc(k))

    @property
    def d(self):
    return self._d


    The problem with this approach is that the descriptor instances are class attributes. This means that, in an interactive session:

    a1 = A(['x', 'y'], [1, 2])
    a2 = A(['z', ], [3])


    if I press TAB for autocomplete on a1. I will be given the option to choose the attribute z, which "belongs" to instance a2. I have also tried to implement via the instance's __getattr__ method:

    class B:
    def __init__(self, klist: list[str], vlist: list[Any]):
    object.__setattr__(self, '_d', dict(zip(klist, vlist)))

    @property
    def d(self):
    return self._d

    def __getattr__(self, name):
    if name in self.d:
    return self.d[name]
    else:
    object.__getattr__(name)

    def __setattr__(self, k, v):
    if k in self.d:
    raise AttributeError("Read only!")
    object.__setattr__(self, k, v)


    If I try b = B(['w'], [3]) in an interactive session, pressing TAB on b. won't show w as an option, because it's not an instance attribute.

    Pandas does something similar to what I want: it allows accessing the columns of a DataFrame with the dot operator, and only the appropriate columns for a given instance show up upon pressing TAB in an interactive session. I have tried to look into the Pandas code but it is a bit abstruse to me. I think they use something similar to my second __getattr__ option, but I don't understand how they make it work.

    How could I implement this behaviour?

    Continue reading...

Compartilhe esta Página