• Is there a way to implement the ** operator on a custom object

    From Tony Flury@3:633/280.2 to All on Thu Feb 8 23:21:20 2024
    I know that mappings by default support the ** operator, to unpack the
    mapping into key word arguments.

    Has it been considered implementing a dunder method for the ** operator
    so you could unpack an object into a key word argument, and the
    developer could choose which keywords would be generated (or could even generate 'virtual' attributes).

    --
    Anthony Flury
    email : anthony.flury@btinternet.com


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: ---:- FTN<->UseNet Gate -:--- (3:633/280.2@fidonet)
  • From Cameron Simpson@3:633/280.2 to All on Fri Feb 9 16:50:21 2024
    On 08Feb2024 12:21, tony.flury@btinternet.com <tony.flury@btinternet.com> wrote:
    I know that mappings by default support the ** operator, to unpack the >mapping into key word arguments.

    Has it been considered implementing a dunder method for the **
    operator so you could unpack an object into a key word argument, and
    the developer could choose which keywords would be generated (or could
    even generate 'virtual' attributes).

    Can you show us why you think that would look like in code?

    Note that Python already has `a ** b` to raise `a` to the power of `b`,
    and it has a bunder method `__pow__` which you can define.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: ---:- FTN<->UseNet Gate -:--- (3:633/280.2@fidonet)
  • From Chris Angelico@3:633/280.2 to All on Fri Feb 9 17:06:42 2024
    On Fri, 9 Feb 2024 at 17:03, Cameron Simpson via Python-list <python-list@python.org> wrote:

    On 08Feb2024 12:21, tony.flury@btinternet.com <tony.flury@btinternet.com> wrote:
    I know that mappings by default support the ** operator, to unpack the >mapping into key word arguments.

    Has it been considered implementing a dunder method for the **
    operator so you could unpack an object into a key word argument, and
    the developer could choose which keywords would be generated (or could
    even generate 'virtual' attributes).

    Can you show us why you think that would look like in code?

    Note that Python already has `a ** b` to raise `a` to the power of `b`,
    and it has a bunder method `__pow__` which you can define.

    I presume this is more like:

    obj = SomeObject()
    func(**obj)

    ie making the object behave in a dict-like way. I can't remember how
    this is implemented, but you can create the necessary methods to have
    your object produce whatever it likes.

    ChrisA

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: ---:- FTN<->UseNet Gate -:--- (3:633/280.2@fidonet)
  • From Alan Bawden@3:633/280.2 to All on Fri Feb 9 17:26:16 2024
    Chris Angelico <rosuav@gmail.com> writes:

    > On 08Feb2024 12:21, tony.flury@btinternet.com <tony.flury@btinternet.com> wrote:
    > >I know that mappings by default support the ** operator, to unpack the
    > >mapping into key word arguments.
    > >
    > >Has it been considered implementing a dunder method for the **
    > >operator so you could unpack an object into a key word argument, and
    > >the developer could choose which keywords would be generated (or could
    > >even generate 'virtual' attributes).

    I presume this is more like:

    obj = SomeObject()
    func(**obj)

    ie making the object behave in a dict-like way. I can't remember how
    this is implemented, but you can create the necessary methods to have
    your object produce whatever it likes.

    All you need to do is subclass collections.abc.Mapping, and
    implement __len__, __iter__, and __getitem__. Pretty easy.

    - Alan

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: ITS Preservation Society (3:633/280.2@fidonet)
  • From Left Right@3:633/280.2 to All on Sat Feb 10 03:09:54 2024
    In order for the "splat" operator to work, the type of the object must
    populate slot `tp_as_mapping` with a struct of this type: https://docs.python.org/3/c-api/typeobj.html#c.PyMappingMethods and
    have some non-null implementations of the methods this struct is
    supposed to contain.

    I can do this in C, but I cannot think of a way to do this in Python
    proper. Defining all the methods mentioned in PyMappingMethods doesn't
    seem to do it. You could try to research this further, and if, indeed
    defining all the methods of PyMappingMethods on the Python side
    doesn't produce an object that behaves like a proper mapping, you
    could probably file a bug report for that.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: ---:- FTN<->UseNet Gate -:--- (3:633/280.2@fidonet)
  • From Roel Schroeven@3:633/280.2 to All on Sat Feb 10 04:03:04 2024
    Left Right via Python-list schreef op 9/02/2024 om 17:09:
    In order for the "splat" operator to work, the type of the object must populate slot `tp_as_mapping` with a struct of this type: https://docs.python.org/3/c-api/typeobj.html#c.PyMappingMethods and
    have some non-null implementations of the methods this struct is
    supposed to contain.

    I can do this in C, but I cannot think of a way to do this in Python
    proper.

    Looks like it can simply be done in Python, no tp_as_mapping needed. I
    tried it like Alan Bawden suggested (sibling post of yours):

    import random # just as an example
    import timeÿÿ # just as an example
    from collections.abc import Mapping

    class VirtualKwargs(Mapping):

    ÿÿÿ def __init__(self):
    ÿÿÿÿÿÿÿ self.fncs = {
    ÿÿÿÿÿÿÿÿÿÿÿ # Simple examples of functions with varying return values to be
    ÿÿÿÿÿÿÿÿÿÿÿ # called for each lookup, instead of fixed values.
    ÿÿÿÿÿÿÿÿÿÿÿ 'time': time.time,
    ÿÿÿÿÿÿÿÿÿÿÿ 'random': random.random,
    ÿÿÿÿÿÿÿ }

    ÿÿÿ def __len__(self):
    ÿÿÿÿÿÿÿ return len(self.fncs)

    ÿÿÿ def __iter__(self):
    ÿÿÿÿÿÿÿ return iter(self.fncs)

    ÿÿÿ def __getitem__(self, key):
    ÿÿÿÿÿÿÿ return self.fncs[key]()


    def func(**kwargs):
    ÿÿÿ for k, v in kwargs.items():
    ÿÿÿÿÿÿÿ print(f'{k}: {v}')


    obj = VirtualKwargs()
    func(**obj)


    Output (obviously changes every run):

    time: 1707497521.175763
    random: 0.6765831287385126

    --

    "Man had always assumed that he was more intelligent than dolphins because
    he had achieved so much — the wheel, New York, wars and so on — whilst all the dolphins had ever done was muck about in the water having a good time.
    But conversely, the dolphins had always believed that they were far more intelligent than man — for precisely the same reasons."
    -- Douglas Adams


    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: ---:- FTN<->UseNet Gate -:--- (3:633/280.2@fidonet)
  • From Left Right@3:633/280.2 to All on Sat Feb 10 04:56:17 2024
    Looks like it can simply be done in Python, no tp_as_mapping needed.

    It's not that it isn't needed. You've just shown a way to add it using
    Python code.

    But, more to the point: extending collections.abc.Mapping may or may
    not be possible in OP's case.

    Also, if you are doing this through inheritance, this seems really
    convoluted: why not just inherit from dict? -- less methods to
    implement, less stuff to import etc.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: ---:- FTN<->UseNet Gate -:--- (3:633/280.2@fidonet)
  • From Cameron Simpson@3:633/280.2 to All on Sat Feb 10 08:13:23 2024
    On 09Feb2024 18:56, Left Right <olegsivokon@gmail.com> wrote:
    But, more to the point: extending collections.abc.Mapping may or may
    not be possible in OP's case.

    We don't yet know if that's what the OP had in mind yet, anyway.

    Also, if you are doing this through inheritance, this seems really >convoluted: why not just inherit from dict? -- less methods to
    implement, less stuff to import etc.

    There's a rule of thumb that we _tend_ not to subclass the builtins; it certainly has its pitfalls to do with object creation/initialisation.
    That said, I have some classes which subclass dict, int, str and
    namedtuple.

    Cheers,
    Cameron Simpson <cs@cskk.id.au>

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: ---:- FTN<->UseNet Gate -:--- (3:633/280.2@fidonet)
  • From Stefan Ram@3:633/280.2 to All on Sun Feb 11 00:24:39 2024
    Cameron Simpson <cs@cskk.id.au> writes:
    That said, I have some classes which subclass dict, int, str and
    namedtuple.

    Consider subclassing
    collections.UserDict instead of dict and
    collections.UserString instead of str.

    --- MBSE BBS v1.0.8.4 (Linux-x86_64)
    * Origin: Stefan Ram (3:633/280.2@fidonet)