Re: Python-list Digest, Vol 232, Issue 1

2023-01-01 Thread Christman, Roger Graydon
Re: Nonetype List

In my introductory programming course, I have drawn some attention to this 
behavior regarding mutating lists.   Indeed, Python is very consistent with its 
behavior:

Any function that mutates a list parameter does not return that list as a 
return value.
For one thing, there is no need to return that value, because the caller still 
owns the list parameter that has been modified.

But secondly, (and what I find especially important), is that returning the 
modified list would lead too many program bugs or misunderstandings.

For example, if append did return the list, you might see this:

x = [1,2,3]
y = x.append(4)
z = y.append(5)

The principal of 'least surprise' would cause a casual reader to believe that x 
retains the value of [1,2,3], y would have the value of [1,2,3,4], and z would 
contain [1,2,3,4,5].

So it would be very surprising indeed to discover that x contains [1,2,3,4,5], 
especially after that statement that makes no reference to x.  Since append 
modifies the list in place, returning that list would make x, y, and z all 
aliases of each other, and aliasing is a source of many bugs that are very hard 
to find.

So a recommendation that I make to my class (and which coincides with Python 
behavior), is to NEVER return a modified list as a return value, but only to 
return lists that were newly created within the function.   So to support this 
principal of 'least surprise', the append method above would necessarily create 
new lists for y and z that are not aliases to x.   Why Python does not do that 
is a very obvious cases of run-time efficiency (constant time to append vs. 
linear to recreate a new list).

And as another observation, I have my students review all of the methods 
defined for the list object, and they are all very consistent.   Most of them 
either define a return value, or modify the list parameter, but almost none do 
both.   The sole exception is the pop() function that modified a list and 
returns a value, but that returned value still is not the modified list, so the 
aliasing problem will never arise.

So, I am very happy with this Python language decision -- it allows for the 
most efficient means to modify a list in place and also very much reduce the 
danger of aliasing bugs.

Roger Christman
Pennsylvania State University

From: Python-list  on behalf of 
python-list-requ...@python.org 
Sent: Sunday, January 1, 2023 12:00 PM
To: python-list@python.org 
Subject: Python-list Digest, Vol 232, Issue 1

Send Python-list mailing list submissions to
python-list@python.org

To subscribe or unsubscribe via the World Wide Web, visit

https://nam10.safelinks.protection.outlook.com/?url=https%3A%2F%2Fmail.python.org%2Fmailman%2Flistinfo%2Fpython-list=05%7C01%7Cdvl%40psu.edu%7C744c83fc485a4b1c79db08daec19a436%7C7cf48d453ddb4389a9c1c115526eb52e%7C0%7C0%7C638081892123929669%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C=etYqO01OszhEpqgjLeKQTMC9b3wT0sc%2FcN8oJo9eEhk%3D=0
or, via email, send a message with subject or body 'help' to
python-list-requ...@python.org

You can reach the person managing the list at
python-list-ow...@python.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Python-list digest..."


Today's Topics:

   1. Re: NoneType List (Thomas Passin)
   2. Re: NoneType List (MRAB)
   3. Re: NoneType List (dn)
   4. RE: NoneType List (avi.e.gr...@gmail.com)
   5. Re: NoneType List (Thomas Passin)
   6. Re: NoneType List (Greg Ewing)
   7. RE: NoneType List (avi.e.gr...@gmail.com)
   8. Re: NoneType List (Chris Angelico)
   9. RE: NoneType List (avi.e.gr...@gmail.com)
  10. Re: NoneType List (Chris Angelico)
  11. Re: NoneType List (Thomas Passin)


--

Message: 1
Date: Sat, 31 Dec 2022 12:07:25 -0500
From: Thomas Passin 
To: python-list@python.org
Subject: Re: NoneType List
Message-ID: <3eb7480c-88f7-72cf-af66-c0072928b...@tompassin.net>
Content-Type: text/plain; charset=UTF-8; format=flowed

Oops, my reply got lost somehow.  Here it is:

Everyone's answer to date has been too complicated.  What is going on is
that list.append() changes the list in place.  It returns nothing.  If
you want to append an item and then assign the result to a new list, you
have to do just that:

l1.append(item)
# If we want a *copy* of the appended list:
l2 = l1[:]  # Changes to l2 will not change l1

# If we want another name for the appended list:
l2 = l1  # Changes to l2 will change l1 since they are the same object

list.sort() also operates in place.  There is a function sorted() that
returns the sorted list (without changing the original list).

The same thing is true of set.add(). The set is changed in place, and
nothing is returned.

On 12/31/2022 10:50 AM, Thomas Passin wrote:
> Happy New Year, everybody!
> I'm new in the 

Re: memoization (original Subject lost because mailer lost the whole thread)

2022-09-19 Thread Christman, Roger Graydon
"Hen Hanna"  asked:
> so... for a few days  i've been revising this Code (in Gauche / Lisp / 
> Scheme) to make it run faster..   and last night  i could improve it enough 
> to give me the result i wantedin  72 minutes or so  (on my slow PC at 
> home).

>  ( Maybe... within a few months, i'll write the same program in Python   
> to see if it runs  10 or 20 times faster. )

> this was the first time  i've used  Caching (memoization).  - instead of  
> calculating (at run-time)Factorial(x)   and   Combination(x,y)   millions 
> of times,   i made 2 tables in advance...A simple Table-lookup  
> (Vector-ref in Scheme)  seems  100 -- 1000 times faster.

> One thought i had was...  Maybe Python's  Factorial(x) and Combination(x,y)   
>  (in  Numpy ?)  are already so fast that...   i don't have to do the  Caching 
> (memoization) ???

Memoization will generally be very fast -- since it is essentially a 
table-lookup.   If it uses a hash-table (which is common for dictionaries), it 
would be close to a constant-time access for any entry; otherwise, if it uses 
some tree structure, it might be logarithmic in the number of entries in the 
tree.

But that fast access comes at a price of storage -- linear with respect to the 
number of items stored (versus no memory cost incurred when not memoizing).

What effect this has when you call these functions "millions of times" depends 
very much one how many of those calls are on the same values.If all of the 
calls have different arguments, memoization would not find it in the table yet, 
and would have to recompute as normal -- and you would end up with no time 
savings, but a considerable memory allocation for all of those newly-cached 
values that you never retrieve.   The big wins come from asking the same 
questions repeatedly.

Now, as far as Python's functionality, I would not expect it to do any 
memoization for you.   It certainly could not predict what arguments would 
provide, but it still could still have a reasonable implementation without 
memoization.  Your Factorial(x) and Combination(x,y) would both require a time 
linear with respect to the value of x, with no memory cost incurred.

But if you were to spend most of your application asking the same questions, I 
would not expect these functions to do any caching or memoization, since I 
would expect very few applications would have enough calls to these functions 
to make it worthwhile.So calling these functions, you can expect a linear 
time for each function call, and if you expect to frequently repeat arguments, 
then you should add your own memoization for an amortized linear time.

And fortunately, Python makes memoization very easy, by using a dictionary as a 
default value.   I've done that often for classroom purposes for cases where it 
makes a big difference (recursive Fibonacci accelerates from exponential time 
to linear time).   And the process is straightforward enough that you could 
even define a decorator that could be applied to any function you choose.   I 
don't have an example handy just because I never took the time to write one.

Roger Christman
Pennsylvania State University



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


Re: New assignmens ...

2021-10-27 Thread Christman, Roger Graydon



On 27/10/2021 8:28, Anton Pardon wrote:
>>> Suppose I would like to write a loop as follows:
>>.   >while ((a, b) := next_couple(a, b))[1]:
>>   >do needed calculations
>>
>>
>>> What I can do is write it as follows:
>>>  while [tmp := next_couple(a,b), a := tmp[0], b := tmp[1]][-1]:
>>   >do needed calculations
>>
>>> I really don't see what is gained by "forcing" me to right the second code 
>>> over the first.
>> No, nobody is forcing you to write it the second way over the first.
>> Nobody is forcing you to use the walrus operator at all!
>>
>> Instead, I would recommend something more like:
>>
>> while b:
>>   do needed calculations
>>   (a,b) = next_couple(a,b)

> But AIU the walrus operator was introduced so we no longer needed, to write 
> such code,
> with the calculation of the next candidate at the bottom and the test at the 
> top.
> You just confirmed the walrus operator is not very useful once the next 
> candidate is
> no longer just a name.

I must disagree with the first sentence here regarding why the walrus operator 
was introduced.
I read through the PEP, and saw nothing about that in the Rationale.   I do see 
the loop-and-a-half
example, but that actually had its next candidate value near the top (just 
before a break).

I'm going to provide two loop-and-a-half segments to illustrate my 
interpretation
of this PEP and the purpose of the walrus operator:

Without the walrus:

total = 0
value = input()
while value >= 0:
 total += value
 value = input()
print(total)

With the walrus:

total = 0
while (value := input()) > 0:
 total += value
print(total)

In terms of the PEP -- I want to compare each input value to 0 for the loop 
test,
but I also want to preserve that value, to add to the total.   There is a 
subexpression
(input()) within a larger expression (compared to 0) that I wish to name for 
reuse.

Now contrast with this example:

Without the walrus:

replay = True
while replay:
play_game()
replay = input("Play again? ") in ['y','Y','yes','Yes']

(I think it silly to ask about playing again at first).

With the walrus:

replay = None
while replay==None or (replay := input("Play again? ") in ['y','Y','yes','Yes']:
 play_game()

To use the walrus operator here, I have to fabricate a value that would
allow me to bypass the input operation, that cannot be otherwise produced.
I do not find this second version any clearer or more intuitive than the first
(and the PEP did emphasize the value of clarity).

Now reading this in terms of the PEP, where I subexpression (the input)
in a larger expression (seeing if it is the list), I do not really seem to have
a compelling reason to name the value of that subexpression, since I am
not using it for any other purpose, so I could keep the input in the while
condition without using the walrus operator:

first_play = True
while first_play or input("Play again? ") in ['y','Y','yes','Yes']:
play_game()
first_play = False

I do not find this particularly clearer or better than my first version
with the test at the bottom, again since it requires me to do some extra
machinery to avoid the undesired input before the first repetition.
But I might also still argue that this is a little bit clearer than the
walrus alternative above.

My claim from these two examples is that the walrus is helpful to
reduce duplicating or recomputing subexpressions, not simply just
to facilitate code movement.   It is not at all useful for a while loop
condition if the subexpression you wish to evaluate depends on
whether or not this is the first iteration of the loop.

Which then gets me back to your own illustrated use-case for
which I had raised a few questions/objections to before:

while ((a, b) := next_couple(a, b))[1]:
   do needed calculations

What is the name of the value you wish to test?b
What is this actually testing?   element [1] of a tuple

So already the code is unclear (and was made worse
when you said the existing walrus operator forced you
to make a list of three elements, two assigned with the
walrus, and then using a subscript of [-1] to get what you wanted.
My proposed solution explicitly tested b, since that
seemed to be what was of interest:

 while b:
do needed calculations
 (a,b) = next_couple(a,b)

To which you had replied:
> But AIU the walrus operator was introduced so we no longer needed, to write 
> such code,
> with the calculation of the next candidate at the bottom and the test at the 
> top.
> You just confirmed the walrus operator is not very useful once the next 
> candidate is
> no longer just a name.

Okay, I would be happy to confirm my belief that the walrus is not very useful
when the thing you wish to test is not the same as the thing you with to assign.

But to relate this use case to my earlier loop-and-a-half examples:

(a,b) := next_couple(a,b)

presumes that there is are values for a and b to begin with for that first call 

Re: New assignmens ...

2021-10-27 Thread Christman, Roger Graydon
On 27/10/2021 at 12:45  Antoon Pardon wrote:
> However with the introduction of the walrus operator there is a
> way to simulate a significant number of one and a half loops.

> Consider the following:

 >do
 >   a = expr1
 >   b = expr2
 >   while 2 * a > b:
 >  more calculations

> We could write that now as

 >while [
 >a := expr1,
 >   b := expr2,
 >   2 * a > b][-1]:
 >  more calculations

Why don't you try this?

while 2 * (a := expr1) > (b := expr2):
  more calculations

It seems you are just compelled to create tuple and lists
in all of your use-cases, even when they serve no purpose.

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


Re: New assignmens ...

2021-10-25 Thread Christman, Roger Graydon
Message: 8
Date: Mon, 25 Oct 2021 11:20:52 +0200
From: Antoon Pardon 
To: python-list@python.org
Subject: Re: New assignmens ...
Message-ID: <5761dd65-4e87-8b8c-1400-edb821204...@vub.be>
Content-Type: text/plain; charset=utf-8; format=flowed
On 25/10/2021 11:20, Anton Pardon wrote:
> Suppose I would like to write a loop as follows:

 >while ((a, b) := next_couple(a, b))[1]:
 >do needed calculations


> What I can do is write it as follows:

> while [tmp := next_couple(a,b), a := tmp[0], b := tmp[1]][-1]:
 >do needed calculations

> I really don't see what is gained by "forcing" me to right the second code 
> over the first.

No, nobody is forcing you to right it the second way over the first.
Nobody is forcing you to use the walrus operator at all!

Instead, I would recommend something more like:

   while b:
 do needed calculations
 (a,b) = next_couple(a,b)

This requires even less typing than what you had before!

But it also raises a whole lot of problems with this particular example:
-- neither a nor b is defined in your sample while loop.   It seems you would
need to initialize a and b before your while loop (and mine)
-- is b truly a boolean value, or are you short-cutting some other value?
-- are a and b truly necessary parameters to next_couple, or are they just
there to remind the function of its previous return values?
If the latter, poerhaps you want a stream or list or something with yield

This example (and some of the others I have seen) just highlight how
programmers will take advantage of any new tool to help them write
worse code than if they did not have the tool.   In my mind, the walrus
operator was designed to serve a particular niche case like this one:

while (x := input()) > 0:

where not having the operator required duplicating the input() operation
both before the loop and at the end of the loop  -- or more complicated
cases where some additional operations had to be performed to get
that test value for the while condition (such as getting the b out of (a,b)).

But the walrus only adds a benefit if it is there to avoid the duplication
of the code that is used to obtain that test condition.   This next_couple
example does not qualify, since apparently (a,b) are initialized by some
other means (and not be a call to next_couple with undefined values)

Or the other abuse I saw recently about using the walrus operator:

while (self.ctr := self.ctr-1) > 0:

-- there was no compelling reason for a loop counter to be a class variable
(anyone who peeks at this counter when the loop is down would only see a zero)
-- this requires self.ctr to be initialized to a value one higher than the first
meaningful value (start at 11 if you want to count down from 10)
So my recommended alternative, which furthermore also takes less typing:

while ctr > 0:
  ...
  ctr = ctr-1

TL;DR:   The Walrus operator serves the purpose as described in its PEP
just as it is, and I see no compelling reason to expand its use.
It is there to reduce code size by eliminating a duplication of code,
If the code you write using the walrus operator is longer or more
complicated than the code would be without it, you are misusing it.

Roger Christman
Pennsylvania State University
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: new feature in Python

2020-09-30 Thread Christman, Roger Graydon
On 30/09/2020, yonatan <53770...@gmail.com> proposed:
> instead of
> con = "some text here"
> con  = con.replace("here", "there")

> we could do

> con = "some text here"
> con  .= replace("here", "there")

That would require a major rewrite of the grammer
of the Python language, which would probably be a bad thing.

The operands to all of those assignment operators are
complete objects in their own rights.   This 'replace'
is not an independent object, but a member of the
string object.   Without that "con." in front of it,
you would likely get the error about
"'replace' not defined"

For the grammar to be clean and orthogonal,
it would not be at all good to have a context-sensitivity
introduced to allow orphaned method names to be
permitted,  just because there was this ".=" token
somewhere earlier in the program statement.

Besides, I could foresee a lot of programming
errors when people would start to generalize this
operation to do things like:

list .= append(item)
list .= sort()

which would most certainly be incorrect.

Roger Christman
Pennsylvania State University
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Friday Finking: Limiting parameters

2020-07-11 Thread Christman, Roger Graydon
I'll preface this by saying I am a programming instructor
who still teaches from the ivory tower, so may not necessarily
reflect actual practice in industry.

But I have a very simple rule of thumb for limiting parameters:
One should be able to summarize what a function does in one or two
sentences,  e.g. computes the volume of a cone, or print address labels.
To fully understand the details of the task would certainly involve
listing the parameters, but I would generally expect that a practical
function would naturally put a cap on how much data is provided.
If you need to include more than 7 parameters to describe what
it is you want to do, you are probably doing more than one thing,
or doing something unnecessarily complicated.

I'll take your example with the address, and assume I want to
print a mailing label.I could certainly see you needing to print:
first name, middle initial, last name, house number, street name,
apartment number, town, state, country, zip code, (and maybe more),
and listing all of those individually would produce a very long list.

But these values really are not all that independent of each other.
A person's name can be viewed as a single value that happens to
have multiple parts (collect that into a tuple or class).   Similarly,
a street address is a single object with multiple parts.   These can
easily be delivered as complete objects for a short parameter list.

That does not necessarily mean that the function needs to know
the particular representation or form of that data.   Let those be
objects with getter methods for the data you wish, and have the
function document what methods it will attempt to call.   Then
any class that provides the expected methods would be suitable.

That would also greatly simplify some other features for the problem.
For example, "first name" "last name" really does not mean the same
thing as "individual name" "family name", when some countries
list the family name first.   So it might be better to have a name
object include a "full name" method for the print-mailing-address
function to call instead of giving it access to component parts.

TL;DR:  I expect each parameter to a function to be independent
or orthogonal to the others.   Values that are closely related to
each other can probably be encapsulated into a collection or object.
If you still end up with a large number of independent parameters,
I would question the simplicity of your function's intent.

Roger Christman
Pennsylvania State University
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Friday Finking: Poly more thick

2020-02-29 Thread Christman, Roger Graydon
Emending my own note from moments ago:

 def any_as_dict(*args, **kwargs):
if len(args) == 0:
my_dict = kwargs
elif type(args[0]) == type(dict()):
my_dict = args[0]
else:
my_dict = dict(args[0])
print(type(my_dict),my_dict)


>>> any_as_dict(a=1,b=2)
 {'a': 1, 'b': 2}
>>> any_as_dict({'a':1, 'b':2})
 {'a': 1, 'b': 2}
>>> any_as_dict([('a',1), ('b',2)])
 {'a': 1, 'b': 2}
>>> any_as_dict({('a',1), ('b',2)})
 {'b': 2, 'a': 1}
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Friday Finking: Poly more thick

2020-02-29 Thread Christman, Roger Graydon
DL Neil asked:

> How does one code a function/method signature so that
> it will accept either a set of key-value pairs,
> or the same data enclosed as a dict, as part of
> a general-case and polymorphic solution?


Will this do for you?

def any_as_dict(*args, **kwargs):
if len(args) == 0:
my_dict = kwargs
elif type(args[0]) == type(dict()):
my_dict = args[0]
else:
my_dict = dict(args)
print(type(my_dict),my_dict)


>>> any_as_dict(a=1,b=2)
 {'a': 1, 'b': 2}
>>> any_as_dict({'a':1, 'b':2})
 {'a': 1, 'b': 2}
>>> any_as_dict([('a',1), ('b',2)])
 {('a', 1): ('b', 2)}
>>> any_as_dict({('a',1), ('b',2)})
 {('b', 2): ('a', 1)}

This seems to address your apparent definition of
"key-value pairs" in the form of a=1, b=2
and my interpretation as key-value tuples,
either in a list, or set, or presumably any
iterable collection, in addition to taking an
actual dictionary.

Roger Christman
Pennsylvania State University
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: encapsulating a global variable (BlindAnagram)

2020-02-25 Thread Christman, Roger Graydon
> On Tue, 25 Feb 2020 3:06 PM BlindAnagram  wrote:

> My interest in this stems from wanting to keep the dictionary only
> available to the function that uses it and also a worry about being
> called from threaded code.

It seems like the simplest solution for this is to make
a completely new file (module) containing nothing but
the dictionary and this one function that uses it.
Then you can import the function from the module
wherever it is called without importing the dictionary.

The thing I find curious is that apparently no other
function is allowed to create or populate the dictionary
in the first place.   Is it practical to have the entire
dictionary statically defined?

Roger Christman
Pennsylvania State University
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Loop with Else Clause

2019-02-05 Thread Christman, Roger Graydon
-Original Message-
From: Python-list  On
Behalf Of DL Neil
Sent: Monday, February 4, 2019 11:29 PM
To: 'Python' 
Subject: Loop with else clause

What is the pythonic way to handle the situation where if a condition exists 
the loop should be executed, but if it does not something else should be done?


--


Just reading this by itself without seeing the illustrative problem, my first 
gut reaction was "while loop!"  but then it became more obvious that this was a 
one-off condition to decide to get started, as opposed to being the loop 
condition itself.


That being said, I would agree that you really cannot do better than the 
if-else already presented, since it is clearly a binary choice:  execute the 
complete loop, or don't if you can't.


I personally try to avoid the else part on both while loops and for loops 
because of this sort of confusion.  All other things being equal, having an 
else section is fundamentally the same thing as simply omitting the 'else:' and 
out-denting the consequence, and makes it very clear just what is going on.


The difference, of course, appears when you have a 'break' within that loop 
that exits prematurely.   And that's where the structured-programming purist in 
me starts to gibber in fear and loathing.  My purist self says that if 'break' 
is applicable, than exception handling is just as applicable with a much 
cleaner model, since you can control where to go next, whether to continue 
repeating, etc.


If I don't expect to get all the way through a for loop, I simply don't write a 
for loop -- I'll substitute with a while, moving the logical negation of the 
break condition into the while loop condition, making it very clear that I 
don't plan to make it to the end.  Unfortunately, the for loop is such a common 
Pythonic thing to do that I really can't say 'for/break' is unPythonic -- I can 
only substitute Lovecraftian adjectives (in my opinion, of course) to describe 
that construct.


But this whole little tangent of mine doesn't seem to apply to your situation 
at all,

and I don't there is a 'single' language element in any programming language I 
can think

of that does what you ask -- so stick with the cleaner: if (__): # loop; else: 
#don't loop


Roger Christman

Pennsylvania State University

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


Re: IDLE Default Working Directory

2018-11-13 Thread Christman, Roger Graydon
On 13 Nov 2018, at 09:51, Bev in TX  wrote:

> On Nov 12, 2018, at 5:50 PM, Terry Reedy  wrote:
>
> For me, open (command-O) opens 'Documents'.  I presume it should be easy 
> enough to move into a 'py' subfolder.

The whole point is for Idle -> File -> Open (or command-O) to automatically 
open to a specific folder.

Bev in TX


Thank you, Bev in TX for clarifying my question.  That is indeed what I seek.   
My course has proved cumbersome every time a student created a new program in 
class, since they would have to change folders.And when

I got to working with data files, I ended up with a little punt to avoid having 
to specify a complete path name to get to a workable directory.


My students are not programmers.  I have English majors, Education majors, and 
students in their first year at a University.  I won't say they are completely 
computer-illiterate, they can use a browser well enough.   But I expect none of 
them to have ever seen the command line, so I really don't want to go that 
route.


As far as activating IDLE on this Windows 10 system,

I go down to the search bar at the bottom left, type 'IDLE', and then up comes 
a list of various installations

we have lying around, including 2.7, 3.4, and 3.6 versions.   I have them just 
select the 3.6 version from the list to launch IDLE.I don't consider that 
quite the same as using a 'shortcut', since we are not clicking on any icon on 
the desktop.


I am not on the campus-wide labs right now, so I cannot really say much further 
-- and I haven't tried right-clicking on those items to see if configuration 
options show up, to talk to the %AppData% path, etc.


The Penn State computer labs are networked -- each computer has a C: drive, 
which I presume might be local to each machine -- but in any case, I think it 
is read-only

to the students.  And since they could easily sit down at a different machine 
on any day, I wouldn't want to rely on any configuration file or anything on 
the C drive anyway.


There is a networked U: drive (for users) that is campus wide, which is useful. 
 There is also a virtual V: drive, which simply maps to each individual's 
folder set aside for them on the U: drive.   That place would be ideal for my 
purposes as a place to save code and data files.


But the default directory is somewhere else.   I would

have to get back on campus before I can quote exactly,

but wherever it is a readonly file space that's not the

Desktop or My Documents, or who knows what.

I'd preferably like to reset the default to the V: drive

(or even create a Python folder on that virtual V: drive).


And the real challenge is to come up with the simplest

solution that I can explain or show to first-time programming students in under 
a minute, which therefore does not involve the command-line interface.

I don't want to scare half the students away in the very first class, just 
trying to configure their development environment.


If that's impossible, then I guess I'll have to fire a note off to the  
university tech support requesting them to play with that "Start In" option 
through %AppData%, or whatever it was.


Roger Christman

Pennsylvania State University
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: IDLE Default Working Directory

2018-11-12 Thread Christman, Roger Graydon
eryk sun  responded:

On 11/12/18, Christman, Roger Graydon  wrote:
>
> I looked in IDLE's own configuration menu, and didn't see anything there --
> and I fear that I might have to fight some Windows settings somewhere else
> instead.   I think this is Windows 10.

Modify the "Start in" field of the IDLE shortcut. You can use
environment variables, e.g. "%UserProfile%\Documents".


Unfortunately, since I do not have any administrative privileges, I do not 
think I have the ability to modify any of these shortcuts.  Nor do I know off 
hand how to set environment variables in a manner that would work consistently 
throughout the term, so that they persist for all logins.


Since this is Windows-y system, I can't just tell my students to edit a .cshrc. 
  Any other ideas?


Roger Christman

Pennsylvania State University
-- 
https://mail.python.org/mailman/listinfo/python-list


IDLE Default Working Directory

2018-11-12 Thread Christman, Roger Graydon
Could anyone tell me how to set up IDLE's default working directory, so that it 
would be in the same place for each startup?  (Like C:\Users\myname\Python)


I teach a course that mounts a lot of file space across the network and the 
default directory for all my students is a readonly directory, which means they 
have to adjust anytime they want to save a new program or use a complete path 
name to write to a new output file.   I would prefer that they wouldn't 
continually have to fight the system to save their code.


I looked in IDLE's own configuration menu, and didn't see anything there -- and 
I fear that I might have to fight some Windows settings somewhere else instead. 
  I think this is Windows 10.


Roger Christman

Pennsylvania State University
-- 
https://mail.python.org/mailman/listinfo/python-list