Re: isinstance()

2023-08-04 Thread Grant Edwards via Python-list
On 2023-08-04, Chris Angelico via Python-list  wrote:
> On Sat, 5 Aug 2023 at 09:36, dn via Python-list  
> wrote:
>
>> Faced with a situation where an argument may be a scalar-value or an
>> iterable, I'll presume the latter, eg throw it straight into a for-loop.
>> If that fails (because the argument is a scalar), use try-except to
>> re-route the logic.
>
> That's great as long as you aren't expecting to handle strings.

If you do that, you're obviously not expecting to handle strings. The
problem happens when you're not expecting to handle strings, and you
get passed one anyway.

It's like the Spanish Inquisition...

> The string "spam" is sometimes equivalent to the list ["s", "p",
> "a", "m"] and sometimes not.

And b"ABCD" is sometimes equivalent to the list [65,66,67,68] and
sometimes not.

Been there, fell in that hole.

More than a few times. :/

Famous Last Words: "I wasn't expecting to handle strings -- but I
should have been..."

--
Grant



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


Re: isinstance()

2023-08-04 Thread Chris Angelico via Python-list
On Sat, 5 Aug 2023 at 09:36, dn via Python-list  wrote:
> Faced with a situation where an argument may be a scalar-value or an
> iterable, I'll presume the latter, eg throw it straight into a for-loop.
> If that fails (because the argument is a scalar), use try-except to
> re-route the logic.

That's great as long as you aren't expecting to handle strings. The
string "spam" is sometimes equivalent to the list ["s", "p", "a", "m"]
and sometimes not.

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


Re: isinstance()

2023-08-04 Thread dn via Python-list

On 05/08/2023 11.18, Chris Angelico via Python-list wrote:

On Sat, 5 Aug 2023 at 09:08, dn via Python-list  wrote:


On 03/08/2023 11.38, Jon Ribbens via Python-list wrote:

On 2023-08-02, dn  wrote:

Can you please explain why a multi-part second-argument must be a tuple
and not any other form of collection-type?


The following comment may hold a clue:

  if (PyTuple_Check(cls)) {
  /* Not a general sequence -- that opens up the road to
 recursion and stack overflow. */

https://github.com/python/cpython/blob/main/Objects/abstract.c#L2684

Plus an almost total lack of demand for change I should think.


Thanks for the reference!


Am not proposing a change (have learned 'the rule' and accepted
life-as-it-is), but was curious about the restriction: why not any
(reasonable sequence)?


There are quite a few places where the only option is a tuple.


"spam".startswith(["sp", "h"])

Traceback (most recent call last):
   File "", line 1, in 
TypeError: startswith first arg must be str or a tuple of str, not list

try: 1/0

... except [ValueError, IndexError]: pass
...
Traceback (most recent call last):
   File "", line 1, in 
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
   File "", line 2, in 
TypeError: catching classes that do not inherit from BaseException is
not allowed

It simplifies a lot of checks. Either it's a tuple or it's a single
thing. A *lot* of values are iterable, but only tuples are tuples.

As the C comment notes, this also means you don't have to worry about
recursion; otherwise, even core language features like exception
handling would have to iterate over a thing while ensuring that they
don't get stuck in self-referential objects. (Incidentally, it seems
that exception handling doesn't bother with recursion *at all*, and
won't catch "(a, (b, c))" - but even if recursion is handled, it can't
go infinite, short of some serious messing around in ctypes or the C
API.)

Yes. Thanks Chris!

The idea that such 'lists' be immutable (even, hashable), and therefore 
a tuple, makes a certain amount of sense, and @Cameron mentioned 
'frugality'.



My limitation is thinking only at the Python level (which as @Jon 
pointed-out, is only part of the story).


Faced with a situation where an argument may be a scalar-value or an 
iterable, I'll presume the latter, eg throw it straight into a for-loop. 
If that fails (because the argument is a scalar), use try-except to 
re-route the logic. Alternately, in an OOP situation, utilise 
polymorphism so that the 'scalar' and 'iterable' instances both include 
the appropriate method[name]. Accordingly, as long as the argument is an 
iterable (includes an __iter__() method), the actual type/class is 
more-or-less irrelevant.



However, as observed earlier - and with these additions, having learned 
the 'rule', ie use a tuple; the brain is still pondering, but have 
shrugged-shoulders and carried-on regardless...


--
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: isinstance()

2023-08-04 Thread Chris Angelico via Python-list
On Sat, 5 Aug 2023 at 09:08, dn via Python-list  wrote:
>
> On 03/08/2023 11.38, Jon Ribbens via Python-list wrote:
> > On 2023-08-02, dn  wrote:
> >> Can you please explain why a multi-part second-argument must be a tuple
> >> and not any other form of collection-type?
> >
> > The following comment may hold a clue:
> >
> >  if (PyTuple_Check(cls)) {
> >  /* Not a general sequence -- that opens up the road to
> > recursion and stack overflow. */
> >
> > https://github.com/python/cpython/blob/main/Objects/abstract.c#L2684
> >
> > Plus an almost total lack of demand for change I should think.
>
> Thanks for the reference!
>
>
> Am not proposing a change (have learned 'the rule' and accepted
> life-as-it-is), but was curious about the restriction: why not any
> (reasonable sequence)?

There are quite a few places where the only option is a tuple.

>>> "spam".startswith(["sp", "h"])
Traceback (most recent call last):
  File "", line 1, in 
TypeError: startswith first arg must be str or a tuple of str, not list
>>> try: 1/0
... except [ValueError, IndexError]: pass
...
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "", line 2, in 
TypeError: catching classes that do not inherit from BaseException is
not allowed

It simplifies a lot of checks. Either it's a tuple or it's a single
thing. A *lot* of values are iterable, but only tuples are tuples.

As the C comment notes, this also means you don't have to worry about
recursion; otherwise, even core language features like exception
handling would have to iterate over a thing while ensuring that they
don't get stuck in self-referential objects. (Incidentally, it seems
that exception handling doesn't bother with recursion *at all*, and
won't catch "(a, (b, c))" - but even if recursion is handled, it can't
go infinite, short of some serious messing around in ctypes or the C
API.)

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


Re: isinstance()

2023-08-04 Thread dn via Python-list

On 03/08/2023 11.38, Jon Ribbens via Python-list wrote:

On 2023-08-02, dn  wrote:

Can you please explain why a multi-part second-argument must be a tuple
and not any other form of collection-type?


The following comment may hold a clue:

 if (PyTuple_Check(cls)) {
 /* Not a general sequence -- that opens up the road to
recursion and stack overflow. */

https://github.com/python/cpython/blob/main/Objects/abstract.c#L2684

Plus an almost total lack of demand for change I should think.


Thanks for the reference!


Am not proposing a change (have learned 'the rule' and accepted 
life-as-it-is), but was curious about the restriction: why not any 
(reasonable sequence)?



Such pondering continues in my subversive mind, given such thoughts as:

- "we're all adults here"
(eg frequent justification when arguing about Python not having "private 
attributes" per-se).

So, if we introduce a complexity, on our own heads be it!
(hardly likely given that all we are likely to attempt is the 
application of a simple and short 'list' of [un]acceptable types).
NB understood that the quoted-code is applied in many and other 'scalar 
or tuple' situations.


- Python happily enables recursion, which "opens up the road to 
recursion and stack overflow.".

So, why install a 'nanny' to save us from ourselves here?
Again: seems on-the-surface that such 'lists' (at the code-line level) 
will be mono-dimensional 99.9% of the time.



NB having said that, the underlying mechanism *is* multi-dimensional: 
"direct, indirect, or virtual) subclass thereof" 
(https://docs.python.org/3/library/functions.html#isinstance)


Further: the 'rules' say: "classinfo is a tuple of type objects (or 
recursively, other such tuples)". Thus, can write:


>>> target_object = ...
>>> inner_tuple = float, complex
>>> inner_tuple
(, )
>>> isinstance( target_object, ( str, inner_tuple, int, ), )
False

I can't say I've ever used such construction in-the-wild - either 
defining and then using an "inner_tuple", or even nesting. YMMV!



Any thoughts?

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: How to find the full class name for a frame

2023-08-04 Thread Jason Friedman via Python-list
>
> Jason Friedman wrote at 2023-8-3 21:34 -0600:
> > ...
> >my_frame = inspect.currentframe()
> > ...
> >My question is: let's say I wanted to add a type hint for my_frame.
>
> `my_frame` will be an instance of `Types.FrameType`.
>

Confirmed. Thank you!
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to find the full class name for a frame

2023-08-04 Thread Dieter Maurer via Python-list
Jason Friedman wrote at 2023-8-3 21:34 -0600:
> ...
>my_frame = inspect.currentframe()
> ...
>My question is: let's say I wanted to add a type hint for my_frame.

`my_frame` will be an instance of `Types.FrameType`.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Fallback for operator and other dunder methods

2023-08-04 Thread Dom Grigonis via Python-list
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 
>  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 
>>> http://python.org/>> wrote: 
>>> 
>>> On Wed, 26 Jul 2023 at 16:52, Dom Grigonis >> ...@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://mail.python.org/mailman/listinfo/python-list 
> 
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Fallback for operator and other dunder methods

2023-08-04 Thread Edmondo Giovannozzi via Python-list
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 
> >  wrote: 
> > 
> > On Wed, 26 Jul 2023 at 16:52, Dom Grigonis  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://mail.python.org/mailman/listinfo/python-list


Re: isinstance()

2023-08-04 Thread Jon Ribbens via Python-list
On 2023-08-02, dn  wrote:
> Can you please explain why a multi-part second-argument must be a tuple 
> and not any other form of collection-type?

The following comment may hold a clue:

if (PyTuple_Check(cls)) {
/* Not a general sequence -- that opens up the road to
   recursion and stack overflow. */

https://github.com/python/cpython/blob/main/Objects/abstract.c#L2684

Plus an almost total lack of demand for change I should think.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to find the full class name for a frame

2023-08-04 Thread Jason Friedman via Python-list
> My question is: let's say I wanted to add a type hint for my_frame.
> >
> > my_frame: some_class_name = inspect.currentframe()
> >
> > What would I put for some_class_name?
> > "frame" (without quotations) is not recognized,
> > Nor is inspect.frame.
>
> We know Python code is executed in an execution frame.
> (https://docs.python.org/3/reference/executionmodel.html?highlight=frame)
>
> We are told "Frame objects Frame objects represent execution frames."
> (https://docs.python.org/3/reference/datamodel.html?highlight=frame).
> The word "represent" conflicts with the idea of "are".
>
> 'Under the hood' inspect calls sys._current_frames()
> (https://docs.python.org/3/library/sys.html?highlight=frame). That code
> is:
>
> def _getframe(*args, **kwargs): # real signature unknown
>  """
>  Return a frame object from the call stack.
>
>  If optional integer depth is given, return the frame object that many
>  calls below the top of the stack.  If that is deeper than the call
>  stack, ValueError is raised.  The default for depth is zero, returning
>  the frame at the top of the call stack.
>
>  This function should be used for internal and specialized purposes
>  only.
>  """
>  pass
>
> Which rather suggests that if the sys library doesn't know the
> signature, then neither typing nor we mere-mortals are going to do so,
> either.
>
>
> Theory: the concept of a frame does not really exist at the Python-level
> (remember "represents"). Frames (must) exist at the C-level
> (
> https://docs.python.org/3/c-api/frame.html?highlight=frame#c.PyFrameObject)
>
> of the virtual-machine - where typing is not a 'thing'.
>
>
> It's an interesting question. Perhaps a better mind than mine can give a
> better answer?
>
>
Thank you DN.

My ultimate goal is a function I'd put in my main library which other
functions could leverage, something like:

function_in_another_file(arg):
logger.info(my_main_module.render_calling_info(inspect.stack(),
inspect.currentframe())
# Now do the work
-- 
https://mail.python.org/mailman/listinfo/python-list