RE: Popping key causes dict derived from object to revert to object

2024-03-25 Thread AVI GROSS via Python-list
Lori,

The list comprehension you are thinking of does work if you change things a
bit. But it is not a great idea as a main purpose of a dict is that using a
hash means things are found in linear time.  A comprehension iterates on all
values. If you wanted to select just some items to keep in a list, your code
could be modified from:

dict_list = [d.pop('a') for d in dict_list]

to have an IF clause that would specify something like comparing it to the
item you do not want to keep.

But your idiom might be better done to make another dictionaly, not list
with something like:

New_dict = {key:value for key in dict if key != "whatever"}

Or variants on that. It builds a new dictionary, at nontrivial expense, as
compared to using del on an existing dictionary.

-Original Message-
From: Python-list  On
Behalf Of Loris Bennett via Python-list
Sent: Monday, March 25, 2024 2:56 AM
To: python-list@python.org
Subject: Re: Popping key causes dict derived from object to revert to object

Grant Edwards  writes:

> On 2024-03-22, Loris Bennett via Python-list 
wrote:
>
>> Yes, I was mistakenly thinking that the popping the element would
>> leave me with the dict minus the popped key-value pair.
>
> It does.

Indeed, but I was thinking in the context of 

  dict_list = [d.pop('a') for d in dict_list]

and incorrectly expecting to get a list of 'd' without key 'a', instead
of a list of the 'd['a]'.

>> Seem like there is no such function.
>
> Yes, there is. You can do that with either pop or del:
>
> >>> d = {'a':1, 'b':2, 'c':3}
> >>> d
> {'a': 1, 'b': 2, 'c': 3}
> >>> d.pop('b')
> 2
> >>> d
> {'a': 1, 'c': 3}
>
>
> >>> d = {'a':1, 'b':2, 'c':3}
> >>> del d['b']
> >>> d
> {'a': 1, 'c': 3}
>
> In both cases, you're left with the dict minus the key/value pair.
>
> In the first case, the deleted value printed by the REPL because it
> was returned by the expression "d.pop('b')" (a method call).
>
> In the second case is no value shown by the REPL because "del d['b']"
> is a statement not an expression.

Thanks for pointing out 'del'.  My main problem, however, was failing to
realise that the list comprehension is populated by the return value of
the 'pop', not the popped dict.

Cheers,

Loris

-- 
This signature is currently under constuction.
-- 
https://mail.python.org/mailman/listinfo/python-list

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


RE: Popping key causes dict derived from object to revert to object

2024-03-25 Thread AVI GROSS via Python-list
I am glad, Lori, you found a solution another way.

Actually, Lori, I think you were right in looking for a built-in method that 
complements pop() by returning everything else other than the item mentioned. 
There are philosophical and practical considerations that were no doubt 
considered and a reality that the functionality did exist albeit not in a 
pipelined format.

Consider a language like LISP which sort of processed lists of things in which 
a major concept was getting the first item or getting all the rest. Lots of 
LISP programs had complex structures using CAR() and CDR() nested various ways 
to say extract the third item as CAR(CDR(CDR(X))) to the point where some 
commonly used combos became functions with names like CADDR().

There are again many languages where functions or methods are available that 
include an exclusion variant from a collection perhaps by doing something as 
simple as using a minus sign to indicate what to remove, as is commonly done in 
R to remove a column in a data.frame while keeping the order of the remaining 
columns the same.

Lots of languages had similar concepts about ordered data structures but 
dictionaries may be a bit of something else and initially in Python were not 
guaranteed to have any kind of order. Python dicts are more like unordered 
sets. 

So although there remains a concept of not first/rest but this/rest,  I suspect 
there was some thought about the process that ended in deciding not to supply 
some functionality. When you use pop() on something like a large dictionary, 
the original is left intact and is ignored and a copy of a single element is 
made and returned. To do  the opposite and return the rest has two choices. One 
is to make a big copy of the rest of the dictionary and the other is to use del 
internally and return the modified dict. The functions you could write do the 
latter.

So why not add one or more methods to do that? Who knows? But I think some may 
have considered it not needed including some who felt no need for a pipeline 
method when del would do. Another consideration was the common idiom for 
iterating on a collection. Besides pop() you can get lists of dictionary 
entries, keys or values that you can work with and you can even iterate with 
"for key in dict: ..."

Given how many ways common things can be done, and given that adding too many 
methods has costs including new users not understanding all the nuanced 
differences, this fairly useful functionality was left out.

Unfortunately, I think they were wrong here as instead we hear often from 
people like you who assume things would work other ways. I still think it would 
be simple enough to have had a .removekeys(keys) that would work in a pipeline 
to modify the dict by removing one or more items and perhaps another 
.removevalues(values) but at some point you may keep adding methods nobody ever 
uses. The reality is that many trivial one-liner comprehensions can easily do 
many such things using iteration. 

But many simply do not work well in pipelined fashion and thus may need to be 
embedded in a method of your own by subclassing dict or rolling your own.



-Original Message-
From: Loris Bennett  
Sent: Monday, March 25, 2024 2:45 AM
To: avi.e.gr...@gmail.com
Cc: python-list@python.org
Subject: Re: Popping key causes dict derived from object to revert to object

 writes:

> Loris wrote:
>
> "Yes, I was mistakenly thinking that the popping the element would leave
> me with the dict minus the popped key-value pair.  Seem like there is no
> such function."
>
> Others have tried to explain and pointed out you can del and then use the
> changed dict.
>
> But consider the odd concept of writing your own trivial function.
>
> def remaining(adict, anitem):
>   _ = adict.pop(anitem)
>   # alternatively duse del on dict and item
>   return adict
>
>
 remaining({"first": 1, "second": 2, "third": 3}, "second")
> {'first': 1, 'third': 3}
>
>
> Or do you want to be able to call it as in dict.remaining(key) by
> subclassing your own variant of dict and adding a similar method?

No, 'del' does indeed do what I wanted, although I have now decided I
want something else :-)  Nevertheless it is good to know that 'del'
exists, so that I don't have to reinvent it.

Cheers,

Loris

-- 
This signature is currently under constuction.

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


Re: Popping key causes dict derived from object to revert to object

2024-03-25 Thread Grant Edwards via Python-list
On 2024-03-25, Loris Bennett via Python-list  wrote:
> Grant Edwards  writes:
>
>> On 2024-03-22, Loris Bennett via Python-list  wrote:
>>
>>> Yes, I was mistakenly thinking that the popping the element would
>>> leave me with the dict minus the popped key-value pair.
>>
>> It does.
>
> Indeed, but I was thinking in the context of 
>
>   dict_list = [d.pop('a') for d in dict_list]
>
> and incorrectly expecting to get a list of 'd' without key 'a', instead
> of a list of the 'd['a]'.

So when you say "leave me with", you mean "return the same dictionary
with"?  There's an important difference between what a function
returns and what global/local state it "leaves you with".

> Thanks for pointing out 'del'.  My main problem, however, was
> failing to realise that the list comprehension is populated by the
> return value of the 'pop', not the popped dict.

OK, so perhaps you weren't execting the original dict objects to be
mutated, but rather that the pop method would return a new dict object
without the "popped" element. The whole point of the 'pop method is to
return the popped value, otherwise it wouldn't be needed. The 'del'
statement would suffice.

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


Re: Popping key causes dict derived from object to revert to object

2024-03-25 Thread Loris Bennett via Python-list
"Michael F. Stemper"  writes:

> On 25/03/2024 01.56, Loris Bennett wrote:
>> Grant Edwards  writes:
>> 
>>> On 2024-03-22, Loris Bennett via Python-list  wrote:
>>>
 Yes, I was mistakenly thinking that the popping the element would
 leave me with the dict minus the popped key-value pair.
>>>
>>> It does.
>> Indeed, but I was thinking in the context of
>>dict_list = [d.pop('a') for d in dict_list]
>> and incorrectly expecting to get a list of 'd' without key 'a',
>> instead
>> of a list of the 'd['a]'.
> I apologize if this has already been mentioned in this thread, but are
> you aware of "d.keys()" and "d.values"?
>
>  >>> d = {}
>  >>> d['do'] = 'a deer, a female deer'
>  >>> d['re'] = 'a drop of golden sunshine'
>  >>> d['mi'] = 'a name I call myself'
>  >>> d['fa'] = 'a long, long way to run'
>  >>> d.keys()
>  ['fa', 'mi', 'do', 're']
>  >>> d.values()
>  ['a long, long way to run', 'a name I call myself', 'a deer, a female deer', 
> 'a drop of golden sunshine']
>  >>>

Yes, I am, thank you.  However, I didn't want either the keys or the
values.  Instead I wanted to remove a key within a list comprehension.

Cheers,

Loris

PS: "a drop of golden *sun*" - rhymes with "a long, long way to run"


-- 
This signature is currently under constuction.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Popping key causes dict derived from object to revert to object

2024-03-25 Thread Jon Ribbens via Python-list
On 2024-03-25, Loris Bennett  wrote:
> "Michael F. Stemper"  writes:
>
>> On 25/03/2024 01.56, Loris Bennett wrote:
>>> Grant Edwards  writes:
>>> 
 On 2024-03-22, Loris Bennett via Python-list  
 wrote:

> Yes, I was mistakenly thinking that the popping the element would
> leave me with the dict minus the popped key-value pair.

 It does.
>>> Indeed, but I was thinking in the context of
>>>dict_list = [d.pop('a') for d in dict_list]
>>> and incorrectly expecting to get a list of 'd' without key 'a',
>>> instead
>>> of a list of the 'd['a]'.
>> I apologize if this has already been mentioned in this thread, but are
>> you aware of "d.keys()" and "d.values"?
>>
>>  >>> d = {}
>>  >>> d['do'] = 'a deer, a female deer'
>>  >>> d['re'] = 'a drop of golden sunshine'
>>  >>> d['mi'] = 'a name I call myself'
>>  >>> d['fa'] = 'a long, long way to run'
>>  >>> d.keys()
>>  ['fa', 'mi', 'do', 're']
>>  >>> d.values()
>>  ['a long, long way to run', 'a name I call myself', 'a deer, a female 
>> deer', 'a drop of golden sunshine']
>>  >>>
>
> Yes, I am, thank you.  However, I didn't want either the keys or the
> values.  Instead I wanted to remove a key within a list comprehension.

Do you mean something like:

  [my_dict[key] for key in my_dict if key != 'a']

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


Re: Popping key causes dict derived from object to revert to object

2024-03-25 Thread Michael F. Stemper via Python-list

On 25/03/2024 01.56, Loris Bennett wrote:

Grant Edwards  writes:


On 2024-03-22, Loris Bennett via Python-list  wrote:


Yes, I was mistakenly thinking that the popping the element would
leave me with the dict minus the popped key-value pair.


It does.


Indeed, but I was thinking in the context of

   dict_list = [d.pop('a') for d in dict_list]

and incorrectly expecting to get a list of 'd' without key 'a', instead
of a list of the 'd['a]'.

I apologize if this has already been mentioned in this thread, but are
you aware of "d.keys()" and "d.values"?

 >>> d = {}
 >>> d['do'] = 'a deer, a female deer'
 >>> d['re'] = 'a drop of golden sunshine'
 >>> d['mi'] = 'a name I call myself'
 >>> d['fa'] = 'a long, long way to run'
 >>> d.keys()
 ['fa', 'mi', 'do', 're']
 >>> d.values()
 ['a long, long way to run', 'a name I call myself', 'a deer, a female deer', 
'a drop of golden sunshine']
 >>>


--
Michael F. Stemper
Exodus 22:21

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


Re: Popping key causes dict derived from object to revert to object

2024-03-25 Thread Loris Bennett via Python-list
Grant Edwards  writes:

> On 2024-03-22, Loris Bennett via Python-list  wrote:
>
>> Yes, I was mistakenly thinking that the popping the element would
>> leave me with the dict minus the popped key-value pair.
>
> It does.

Indeed, but I was thinking in the context of 

  dict_list = [d.pop('a') for d in dict_list]

and incorrectly expecting to get a list of 'd' without key 'a', instead
of a list of the 'd['a]'.

>> Seem like there is no such function.
>
> Yes, there is. You can do that with either pop or del:
>
> >>> d = {'a':1, 'b':2, 'c':3}
> >>> d
> {'a': 1, 'b': 2, 'c': 3}
> >>> d.pop('b')
> 2
> >>> d
> {'a': 1, 'c': 3}
>
>
> >>> d = {'a':1, 'b':2, 'c':3}
> >>> del d['b']
> >>> d
> {'a': 1, 'c': 3}
>
> In both cases, you're left with the dict minus the key/value pair.
>
> In the first case, the deleted value printed by the REPL because it
> was returned by the expression "d.pop('b')" (a method call).
>
> In the second case is no value shown by the REPL because "del d['b']"
> is a statement not an expression.

Thanks for pointing out 'del'.  My main problem, however, was failing to
realise that the list comprehension is populated by the return value of
the 'pop', not the popped dict.

Cheers,

Loris

-- 
This signature is currently under constuction.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: ANN: EmPy 4.1 -- a powerful, robust and mature templating system for Python

2024-03-25 Thread Barry via Python-list
You should considered also announcing on https://discuss.python.org/ which is a 
lot more active then this list.

Barry


> On 25 Mar 2024, at 04:13, Erik Max Francis via Python-list 
>  wrote:
> 
> I'm pleased to announce the release of EmPy 4.1.
> 
> The 4._x_ series is a modernization of the software and a revamp of
> the EmPy system to update its feature set and make it more consistent
> with the latest Python versions and practices.  EmPy 4._x_ was also
> relicensed to BSD.
> 
> The 4._x_ series adds new markups, including inline comments,
> backquote literals, chained if-then-else extended expression,
> functional expressions, support for modern Pythonic controls,
> stringized and multiline significators, named escapes, diacritics,
> icons, and emojis.
> 
> It adds support for configuration objects (replacing options
> dictionaries); native support for Unicode, file buffering, reference
> counted `sys.stdout` proxies and error dispatchers and handlers; fixes
> several serious bugs; has a set of full unit and system tests, an
> extensive builtin help system; and the online documention has been
> rewritten and expanded.
> 
> Attempts have been made to make EmPy 4._x_ as backward compatible as
> is practical.  Most common markup has not changed; the only changes
> being removal of `repr` (in favor of backquote literals) as well as
> literal close parenthesis, bracket and brace markup; in-place markup
> has changed syntax (to make way for emojis); and custom markup is now
> parsed more sensibly.
> 
> Most backward-incompatible changes are in the embedding interface.
> The `Interpreter` constructor and global `expand` function now require
> keyword arguments to prevent further backward compatibility problems,
> though effort has been made to make the behavior as backward
> compatible as possible.  The supported environment variables have
> changed, as well as the filter, diversion and hook APIs, and options
> dictionaries no longer exist (in deference to configurations).
> 
> For a comprehensive list of changes from 3._x_ to 4._x_, see:
> 
> 
> 
> ## Introduction:  Welcome to EmPy!
> 
> [EmPy](http://www.alcyone.com/software/empy/) is a powerful, robust and mature
> templating system for inserting Python code in template text.  EmPy
> takes a source document, processes it, and produces output.  This is
> accomplished via expansions, which are signals to the EmPy system
> where to act and are indicated with markup.  Markup is set off by a
> customizable prefix (by default the at sign, `@`).  EmPy can expand
> arbitrary Python expressions, statements and control structures in
> this way, as well as a variety of additional special forms.  The
> remaining textual data is sent to the output, allowing Python to be
> used in effect as a markup language.
> 
> EmPy also supports hooks, which can intercept and modify the behavior
> of a running interpreter; diversions, which allow recording and
> playback; filters, which are dynamic and can be chained together; and
> a dedicated user-customizable callback markup.  The system is highly
> configurable via command line options, configuration files, and
> environment variables.  An extensive API is also available for
> embedding EmPy functionality in your own Python programs.
> 
> EmPy also has a supplemental library for additional non-essential
> features (`emlib`), a documentation building library used to create
> this documentation (`emdoc`), and an extensive help system (`emhelp`)
> which can be queried from the command line with the main executable
> `em.py` (`-h/--help`, `-H/--topics=TOPICS`).  The base EmPy
> interpreter can function with only the `em.py`/`em` file/module
> available.
> 
> EmPy can be used in a variety of roles, including as a templating
> system, a text processing system (preprocessing and/or
> postprocessing), a simple macro processor, a frontend for a content
> management system, annotating documents, for literate programming, as
> a souped-up text encoding converter, a text beautifier (with macros
> and filters), and many other purposes.
> 
> 
> ### Markup overview
> 
> Expressions are embedded in text with the `@(...)` notation;
> variations include conditional expressions with `@(...?...!...)`  and
> the ability to handle thrown exceptions with `@(...$...)`.  As a
> shortcut, simple variables and expressions can be abbreviated as
> `@variable`, `@object.attribute`, `@sequence[index]`,
> `@function(arguments...)`, `@function{markup}{...}` and
> combinations.  Full-fledged statements are embedded with `@{...}`.
> Control flow in terms of conditional or repeated expansion is
> available with `@[...]`.  A `@` followed by any whitespace character
> (including a newline) expands to nothing, allowing string
> concatenations and line continuations.  Line comments are indicated
> with `@#...` including the trailing newline.  `@*...*` allows inline
> comments.  Escapes are indicated with `