• Fallback for operator and other dunder methods

    From Dom Grigonis@21:1/5 to All on Wed Jul 26 05:22:18 2023
    To illustrate what I was trying to achieve:

    class A:
    def __init__(self, arr):
    self.arr = arr

    def __getattr__(self, name):
    arr_method = getattr(self.arr, name)
    def wrapper(*args, **kwargs):
    new_arr = arr_method(*args, **kwargs)
    return type(self)(new_arr)
    return wrapper

    a = A(np.ones((1, 1)))
    print(a.sum().arr) # 1
    print(a + 1) # TypeError: unsupported operand type(s) for +: 'A' and 'int'

    Is there a way to achieve it without actually implementing operators?
    I have looked at Proxy objects, but they do not seem suited to achieve this. (e.g. wrapt)

    If there is no way to do this, wouldn’t it be sensible to have a new method, say ‘__getattrspecial__’? Either with ability to customise for which operators it is being called or not.


    —Nothing ever dies, just enters the state of deferred evaluation—
    Dg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dom Grigonis@21:1/5 to All on Wed Jul 26 09:52:48 2023
    Could you give an example? Something isn’t working for me.

    On 26 Jul 2023, at 09:40, Chris Angelico via Python-list <[email protected]> wrote:

    On Wed, 26 Jul 2023 at 12:23, Dom Grigonis via Python-list <[email protected]> wrote:
    print(a + 1) # TypeError: unsupported operand type(s) for +: 'A' and 'int'

    Is there a way to achieve it without actually implementing operators?
    I have looked at Proxy objects, but they do not seem suited to achieve this. (e.g. wrapt)

    These kinds of special methods are not looked up on the object, but on
    the type. It's more like type(a).__add__(a, 1). So you would need a
    metaclass for this.

    ChrisA
    --
    https://mail.python.org/mailman/listinfo/python-list

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Angelico@21:1/5 to [email protected] on Wed Jul 26 16:40:20 2023
    On Wed, 26 Jul 2023 at 12:23, Dom Grigonis via Python-list <[email protected]> wrote:
    print(a + 1) # TypeError: unsupported operand type(s) for +: 'A' and 'int'

    Is there a way to achieve it without actually implementing operators?
    I have looked at Proxy objects, but they do not seem suited to achieve this. (e.g. wrapt)

    These kinds of special methods are not looked up on the object, but on
    the type. It's more like type(a).__add__(a, 1). So you would need a
    metaclass for this.

    ChrisA

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Angelico@21:1/5 to Dom Grigonis on Wed Jul 26 17:01:38 2023
    On Wed, 26 Jul 2023 at 16:52, Dom Grigonis <[email protected]> wrote:

    Could you give an example? Something isn’t working for me.


    This is a metaclass:

    class Meta(type):
    ...
    class Demo(metaclass=Meta):
    ...

    In order to catch those kinds of attribute lookups, you'll need the
    metaclass to hook them. And you might need to use __getattribute__
    rather than __getattr__. However, there may also be some checks that
    simply look for the presence of the attribute (see: slots), so you may
    find that it's even more complicated. It's usually easiest to just
    create the slots you want.

    ChrisA

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dieter Maurer@21:1/5 to Dom Grigonis on Wed Jul 26 20:01:09 2023
    Dom Grigonis wrote at 2023-7-26 05:22 +0300:
    ...
    Is there a way to achieve it without actually implementing operators?
    I have looked at Proxy objects, but they do not seem suited to achieve this.

    Proxying is a good approach:
    you might have a look at `dm.reuse.proxy.OverridingProxy` (--> `dm.reuse`
    on PyPI).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dom Grigonis@21:1/5 to All on Wed Jul 26 21:35:25 2023
    Tried exactly that and didn’t work. Neither __getattr__, nor __getattribute__ of meta is being invoked.

    On 26 Jul 2023, at 10:01, Chris Angelico via Python-list <[email protected]> wrote:

    On Wed, 26 Jul 2023 at 16:52, Dom Grigonis <[email protected]> wrote:

    Could you give an example? Something isn’t working for me.


    This is a metaclass:

    class Meta(type):
    ...
    class Demo(metaclass=Meta):
    ...

    In order to catch those kinds of attribute lookups, you'll need the
    metaclass to hook them. And you might need to use __getattribute__
    rather than __getattr__. However, there may also be some checks that
    simply look for the presence of the attribute (see: slots), so you may
    find that it's even more complicated. It's usually easiest to just
    create the slots you want.

    ChrisA
    --
    https://mail.python.org/mailman/listinfo/python-list

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Stefan Ram on Thu Jul 27 09:44:52 2023
    [email protected] (Stefan Ram) writes:
    base_class = type( name, (object,), dic )

    The above will work, but

    base_class = type( 'base_class', (), dic )

    might be better.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Dom Grigonis on Thu Jul 27 09:31:36 2023
    Dom Grigonis <[email protected]> writes:
    Is there a way to achieve it without actually implementing operators?

    main.py

    import pydoc_data.topics
    import re

    numeric_types = pydoc_data.topics.topics[ 'numeric-types' ]
    dic = {}
    for numeric_operation in re.finditer\
    ( '^object.(__.*?__)', numeric_types, re.MULTILINE ):
    name = numeric_operation.group( 1 )
    exec( rf'''def %s( self, /, *args, **kwargs ):
    return \
    self.implementation( %r, args, kwargs )''' %( name, name ), dic ) base_class = type( name, (object,), dic )

    class example_class( base_class ):
    def implementation( self, name, *args, **kwargs ):
    print( f'implementation called. {name = }' )
    return 2

    example_object = example_class()

    print( example_object + 1 )
    print( 1 + example_object )

    output

    implementation called. name = '__add__'
    2
    implementation called. name = '__radd__'
    2

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Edmondo Giovannozzi@21:1/5 to All on Wed Aug 2 09:54:59 2023
    Il giorno mercoledì 26 luglio 2023 alle 20:35:53 UTC+2 Dom Grigonis ha scritto:
    Tried exactly that and didn’t work. Neither __getattr__, nor __getattribute__ of meta is being invoked.
    On 26 Jul 2023, at 10:01, Chris Angelico via Python-list <[email protected]> wrote:

    On Wed, 26 Jul 2023 at 16:52, Dom Grigonis <[email protected]> wrote:

    Could you give an example? Something isn’t working for me.


    This is a metaclass:

    class Meta(type):
    ...
    class Demo(metaclass=Meta):
    ...

    In order to catch those kinds of attribute lookups, you'll need the metaclass to hook them. And you might need to use __getattribute__
    rather than __getattr__. However, there may also be some checks that simply look for the presence of the attribute (see: slots), so you may find that it's even more complicated. It's usually easiest to just
    create the slots you want.

    ChrisA
    --
    https://mail.python.org/mailman/listinfo/python-list


    For numpy arrays you can find some suggestion at: https://numpy.org/doc/stable/user/basics.dispatch.html

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dom Grigonis@21:1/5 to All on Fri Aug 4 19:07:50 2023
    The issue was more of a wrapping around numpy array. Found the solution already. Unfortunately, there is no equivalent to __getattr__, the only way is to dynamically define them from meta. It seems it’s pretty standard to just have a collection of
    special method names and using them for similar cases. Well, at least it’s what I got to. __getattr__ feels very hacky for such case, so maybe it’s for the best.

    On 2 Aug 2023, at 19:54, Edmondo Giovannozzi via Python-list <[email protected]> wrote:

    Il giorno mercoledì 26 luglio 2023 alle 20:35:53 UTC+2 Dom Grigonis ha scritto:
    Tried exactly that and didn’t work. Neither __getattr__, nor __getattribute__ of meta is being invoked.
    On 26 Jul 2023, at 10:01, Chris Angelico via Python-list <[email protected] <http://python.org/>> wrote:

    On Wed, 26 Jul 2023 at 16:52, Dom Grigonis <dom.gr <http://dom.gr/>[email protected] <http://gmail.com/>> wrote:

    Could you give an example? Something isn’t working for me.


    This is a metaclass:

    class Meta(type):
    ...
    class Demo(metaclass=Meta):
    ...

    In order to catch those kinds of attribute lookups, you'll need the
    metaclass to hook them. And you might need to use __getattribute__
    rather than __getattr__. However, there may also be some checks that
    simply look for the presence of the attribute (see: slots), so you may
    find that it's even more complicated. It's usually easiest to just
    create the slots you want.

    ChrisA
    --
    https://mail.python.org/mailman/listinfo/python-list


    For numpy arrays you can find some suggestion at: https://numpy.org/doc/stable/user/basics.dispatch.html <https://numpy.org/doc/stable/user/basics.dispatch.html>
    --
    https://mail.python.org/mailman/listinfo/python-list <https://mail.python.org/mailman/listinfo/python-list>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)