__add__ as a property/descriptor seems to work fine, eg:>>> class C:
... @property
... def __add__(self):
... return lambda other: [self, other]
...
>>> C() + C()
[<__main__.C object at 0x0000000003652AC8>, <__main__.C object at 0x0000000003652CC0>]Am I missing something?
Thanks,
-- Ionel Cristian Mărieș, http://blog.ionelmc.roOn Sat, Apr 18, 2015 at 12:15 AM, Guido van Rossum <guido@python.org> wrote:You won't have any more luck defining __add__ as a property -- just don't do that.On how to implement a proxy, I'll let other explain. But this is not it.On Fri, Apr 17, 2015 at 2:04 PM, Ionel Cristian Mărieș <contact@ionelmc.ro> wrote:Well yes, from that example it look right, because the call operator uses the __call__ attribute from the type of the object. However, when the call operator gets the __call__ method it will actually use it as a descriptor. From that perspective it's inconsistent.Also there's the issue about not being able to implement a true proxy (as outlined before).What actually prevents this being fixed?
Thanks,
-- Ionel Cristian Mărieș, http://blog.ionelmc.roOn Fri, Apr 17, 2015 at 11:55 PM, Guido van Rossum <guido@python.org> wrote:I think you're fighting windmills. Like most special operations (e.g. __add__), a __call__ attribute on the object does not work, i.e. it does not make the object callable. E.g.
$ python3
Python 3.5.0a2 (v3.5.0a2:0337bd7ebcb6, Mar 8 2015, 01:12:06)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> class C: pass
...
>>> c = C()
>>> c.__call__ = lambda *a: a
>>> c()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'C' object is not callable
>>> callable(c)
False
>>> hasattr(c, '__call__')
True
>>>On Fri, Apr 17, 2015 at 1:45 PM, Ionel Cristian Mărieș <contact@ionelmc.ro> wrote:_______________________________________________Hello,I had an issue today with the `callable` builtin because it doesn't correctly check that the object has the __call__ attribute.Effectively what `callable(a)` does is `hasattr(type(a), '__call__')` but that's not very straightforward. A more straightforward implementation would do something like `hasattr(a, '__call__')`.For example:Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:44:40) [MSC v.1600 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> callable
<built-in function callable>
>>> class A:
... @property
... def __call__(self):
... raise AttributeError('go away')
...
>>> a = A()
>>> a
<__main__.A object at 0x000000000365B5C0>
>>> a.__call__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __call__
AttributeError: go away
>>> callable(a)
True
>>> # it should be False :(So it boils down to this:>>> hasattr(a, "__call__")
False
>>> hasattr(type(a), "__call__")
TrueMy issue is that I didn't call `callable(type(a))` but just `callable(a)`. Clearly mismatching what happens when you do hasattr(a, "__call__").To put in contrast, this is legal and clearly indicates the descriptors are being used as expected:>>> class B:
... @property
... def __call__(self):
... return lambda: 1
...
>>> b = B()
>>> b()
1There's some more discussing in issue 23990 where I get slightly angry, sorry.So were is this change actually useful? Proxies! Since new-style objects in Python you cannot really proxy the callable aspect of objects, because `callable` just checks that a field is set in a C struct. This is fairly inconvenient because you have to know upfront if your target is going to be callable or not.
Thanks,
-- Ionel Cristian Mărieș, http://blog.ionelmc.ro
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/
----Guido van Rossum (python.org/~guido)
----Guido van Rossum (python.org/~guido)