Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-15 Thread Mark Lawrence

On 14/06/2014 20:37, S Tareq wrote:





You appear to be having problems with your keyboard.  Could you please 
resend your message, stating precisely what you wanted to say.  Thank you.


--
My fellow Pythonistas, ask not what our language can do for you, ask 
what you can do for our language.


Mark Lawrence

---
This email is free from viruses and malware because avast! Antivirus protection 
is active.
http://www.avast.com


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-15 Thread diliup gabadamudalige
Thank you very much Allan! 100% clear.
I thank each and every one of you who contributed to all my question on the
above subject.
A lot of things became very clear.
May you all be well.



On Sun, Jun 15, 2014 at 3:15 AM, Alan Gauld 
wrote:

> On 14/06/14 13:53, diliup gabadamudalige wrote:
>
>  Say if I have a lot of Lists, strings and variables used to carry data
>> to and from various functions why can't I have a class with all these in
>> it?
>>
>
> You can but it should also have the functions that operate on the data
> too. Thats the point of classes they link function and data together
> so you don't need to pass lots of parameters around. If you have a class
> that jusat holds lots of disparate data items you might as well just use a
> list/tuple or dictionary. The value of classes is when you add behaviour or
> methods to the mix.
>
>
>
>  I thought on the lines of blood carrying various things to different
>> organs in the body.
>>
>
> But even there the blood has a distinct set of related items, it doesn't
> carry the food to your stomach or the video signals from
> your eye to your brain. And blood has operations - it can flow,
> coagulate, increase/decrease red-cell count etc. It has
> behaviour as well as data.
>
>
>  class Containers():
>>  def __init__(self):
>> self.last_selected_scale= ""
>> self.scale_notes = ""
>> self.arpeggionotes = ""
>> self.handplayed_notes = []
>> self.MIDIscale = []  # the MIDI scale to be played is here
>> self.play_MIDIscale = False
>> self.play_MIDIarpeggio = False
>> self.play_MIDI_scale_note = False
>> self.play_MIDI_arpeggio_note = False
>> self.MIDInote_inscale = 0
>>
>
> Now that could be a Tune... And it might have record/play/pause operations
>
>
>
>  now say if I play the MIDI keyboard, I collect the notes played which
>> will be appended to the list v.hanplayednotes. This will be done from a
>> function which will scan the keyboard and append played notes to that
>> list.
>>
>
> But that could be a method of the Tune sub-class, MidiTune, which knows
> how to record from a MidiSequencer object.
>
>
>  This is how I have used these variables, lists and strings in this
>> program. So far it has run error free.
>>
>
> The issue is not how to make it run - you can do that in assembler.
> The issue is how easy is it to read and how easy os it to modify and fix
> later. 80% of the cost of commercial software is in "maintenance"
> The goal of professional software engineers is to reduce maintenance
> costs even if that increases the initial 20% development budget.
>
>
>  Is this not correct or bad design. I know it is not the normal way of
>> using class but is it wrong?
>>
>
> Almost certainly, because it adds a layer of complexity for little or no
> gain.
>
> Whereas adding the methods to the class improves the maintainability and
> readability (and sometimes the performance, although that's a secondary
> benefit).
>
> HTH
>
> --
> Alan G
> Author of the Learn to Program web site
> http://www.alan-g.me.uk/
> http://www.flickr.com/photos/alangauldphotos
>
> ___
> Tutor maillist  -  Tutor@python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor
>



-- 
Diliup Gabadamudalige

http://www.diliupg.com
http://soft.diliupg.com/

**
This e-mail is confidential. It may also be legally privileged. If you are
not the intended recipient or have received it in error, please delete it
and all copies from your system and notify the sender immediately by return
e-mail. Any unauthorized reading, reproducing, printing or further
dissemination of this e-mail or its contents is strictly prohibited and may
be unlawful. Internet communications cannot be guaranteed to be timely,
secure, error or virus-free. The sender does not accept liability for any
errors or omissions.
**
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-14 Thread Alan Gauld

On 14/06/14 13:53, diliup gabadamudalige wrote:


Say if I have a lot of Lists, strings and variables used to carry data
to and from various functions why can't I have a class with all these in
it?


You can but it should also have the functions that operate on the data 
too. Thats the point of classes they link function and data together
so you don't need to pass lots of parameters around. If you have a class 
that jusat holds lots of disparate data items you might as well just use 
a list/tuple or dictionary. The value of classes is when you add 
behaviour or methods to the mix.




I thought on the lines of blood carrying various things to different
organs in the body.


But even there the blood has a distinct set of related items, it doesn't 
carry the food to your stomach or the video signals from

your eye to your brain. And blood has operations - it can flow,
coagulate, increase/decrease red-cell count etc. It has
behaviour as well as data.


class Containers():
 def __init__(self):
self.last_selected_scale= ""
self.scale_notes = ""
self.arpeggionotes = ""
self.handplayed_notes = []
self.MIDIscale = []  # the MIDI scale to be played is here
self.play_MIDIscale = False
self.play_MIDIarpeggio = False
self.play_MIDI_scale_note = False
self.play_MIDI_arpeggio_note = False
self.MIDInote_inscale = 0


Now that could be a Tune... And it might have record/play/pause operations



now say if I play the MIDI keyboard, I collect the notes played which
will be appended to the list v.hanplayednotes. This will be done from a
function which will scan the keyboard and append played notes to that list.


But that could be a method of the Tune sub-class, MidiTune, which knows 
how to record from a MidiSequencer object.



This is how I have used these variables, lists and strings in this
program. So far it has run error free.


The issue is not how to make it run - you can do that in assembler.
The issue is how easy is it to read and how easy os it to modify and fix 
later. 80% of the cost of commercial software is in "maintenance"

The goal of professional software engineers is to reduce maintenance
costs even if that increases the initial 20% development budget.


Is this not correct or bad design. I know it is not the normal way of
using class but is it wrong?


Almost certainly, because it adds a layer of complexity for little or no 
gain.


Whereas adding the methods to the class improves the maintainability and 
readability (and sometimes the performance, although that's a secondary 
benefit).


HTH
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.flickr.com/photos/alangauldphotos

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-14 Thread S Tareq



On Friday, 13 June 2014, 12:45, Steven D'Aprano  wrote:
 


On Fri, Jun 13, 2014 at 12:51:25PM +0530, diliup gabadamudalige wrote:
> Hi All!
> Hope everyone is
 well.
> 
> In my code there are many dictionaries and lists which are used in various
> functions. Is it better/pythonic/efficient to have these inside the
> function itself or declared at the beginning of the program in which case
> they will be global? They are all read only. I understand that global
> constants and variable have memory allocated to them but when declared
> inside a function are created on the fly, used and discarded. Please
> enlighten me further on this and correct me if i'm wrong.

A good question.

Depending on the size of these dictionaries and lists, worrying about 
efficiency here may be premature optimization. As they say:


   "We should forget about small efficiencies, say about 97% of 
    the time: premature optimization is the root of all evil."
    -- Donald Knuth


   "The First Rule of Program
 Optimization: Don't do it. The 
    Second Rule of Program Optimization (for experts only!): 
    Don't do it yet." -- Michael A. Jackson


   "More computing sins are committed in the name of efficiency
    (without necessarily achieving it) than for any other single 
    reason — including blind stupidity." -- W.A. Wulf


If these lists and dicts are small, say, fewer than a dozen items, the 
time to create and destroy them is probably trivial, especially if 
you construct them from constant literals. In that case, it's a 
matter of personal taste whether you prefer them as global constants or 
local to a function.

But if it takes a long time to build the list, then you definitely 
should move it outside the function and perform the initialisation step 
only once:

# This may take a while...
PRIMES = [prime(i) for i in range(1,
 101)]


If your lists really are read-only, then you should consider turning 
them into tuples:

# Not this:
SOME_ITEMS = ["this", "that", "another"]
# Better:
SOME_ITEMS = ("this", "that", "another")


One advantage of the tuple is that in recent versions of Python, the 
tuple may be compiled as a constant instead of being built at runtime. 
This is from Python 2.7:


py> from dis import dis
py> code = compile("x = [2, 4, 8]", "", "exec")
py> dis(code)
  1           0 LOAD_CONST               0 (2)
              3 LOAD_CONST               1 (4)
              6 LOAD_CONST               2 (8)
              9 BUILD_LIST     
          3
             12 STORE_NAME               0 (x)
             15 LOAD_CONST               3 (None)
             18 RETURN_VALUE


py> code = compile("x = (2, 4, 8)", "", "exec")
py> dis(code)
  1           0 LOAD_CONST               4 ((2, 4, 8))
              3 STORE_NAME               0 (x)
              6 LOAD_CONST               3 (None)
              9 RETURN_VALUE



-- 
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-14 Thread Steven D'Aprano
On Sat, Jun 14, 2014 at 06:23:08PM +0530, diliup gabadamudalige wrote:

> Say if I have a lot of Lists, strings and variables used to carry data to
> and from various functions why can't I have a class with all these in it? 

Of course you *can*, but you *should not*. Read on...

[...]
> so I declare
> 
> class Containers():
> def __init__(self):
> self.last_selected_scale= ""
> self.scale_notes = ""
> self.arpeggionotes = ""
etc.

> now i initiate the class with
> v=Containers()

So now you write code where everything you use starts with "v.". What 
does the v. do? How does it help your programming?

Answer: it doesn't. It just makes an extra two characters to type. 
Compare the code you would write if you just defined the variables 
directly:

# Option 1
last_selected_scale = ""
scale_notes = ""
arpeggionotes = ""

do_something(last_selected_scale)
do_another_thing(scale_notes, arpeggionotes)


# Versus option 2:
class Containers():
def __init__(self):
self.last_selected_scale = ""
self.scale_notes = ""
self.arpeggionotes = ""

v = Container()
do_something(v.last_selected_scale)
do_another_thing(v.scale_notes, v.arpeggionotes)



The two options do *exactly* the same thing, but Option 2 takes much 
more typing and reading. For what benefit?

The only benefit is if you might have multiple Containers at the same 
time:

keyboard_a = Container()
keyboard_b = Container()

do_something(keyboard_a.last_selected_scale)
do_another_thing(keyboard_b.scale_notes, keyboard_b.arpeggionotes)


Now you can play and record with two keyboards at the same time. 
(Perhaps you have four arms? *smile*) In this case, the extra cost of 
using a class pays for itself. Otherwise, it is just wasted effort.



-- 
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-14 Thread diliup gabadamudalige
Thank you all for those great clarifications. I learnt a lot from these.
My roots in programming are from the early 80s and with a gap of nearly 30
years till I restarted again last year in March with Python. :) So some of
the new concepts like classes are a bit alien to me but I am catching on.
I made a mistake by using the word variables on variables and constants
both. My design structure would most probably be quite unconventional to
most like Allen Gauld says. I am still learning and I like to jump into the
deep end and learn to swim there and so far have managed to stay alive! :)
I have gained immensely from these few emails and hope I can gain more
knowledge to write better code.

Say if I have a lot of Lists, strings and variables used to carry data to
and from various functions why can't I have a class with all these in it? I
thought on the lines of blood carrying various things to different organs
in the body. One common container class. Containers for data exchange
between all classes and functions.
so I declare

class Containers():
def __init__(self):
self.last_selected_scale= ""
self.scale_notes = ""
self.arpeggionotes = ""
self.handplayed_notes = []
self.MIDIscale = []  # the MIDI scale to be played is here
self.play_MIDIscale = False
self.play_MIDIarpeggio = False
self.play_MIDI_scale_note = False
self.play_MIDI_arpeggio_note = False
self.MIDInote_inscale = 0

now i initiate the class with
v=Containers()

now say if I play the MIDI keyboard, I collect the notes played which will
be appended to the list v.hanplayednotes. This will be done from a function
which will scan the keyboard and append played notes to that list.

This is how I have used these variables, lists and strings in this program.
So far it has run error free.

Is this not correct or bad design. I know it is not the normal way of using
class but is it wrong?

Thank you all in advance.


-- 
Diliup Gabadamudalige

http://www.diliupg.com
http://soft.diliupg.com/

**
This e-mail is confidential. It may also be legally privileged. If you are
not the intended recipient or have received it in error, please delete it
and all copies from your system and notify the sender immediately by return
e-mail. Any unauthorized reading, reproducing, printing or further
dissemination of this e-mail or its contents is strictly prohibited and may
be unlawful. Internet communications cannot be guaranteed to be timely,
secure, error or virus-free. The sender does not accept liability for any
errors or omissions.
**
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-13 Thread Cameron Simpson

On 14Jun2014 11:21, Steven D'Aprano  wrote:

On Fri, Jun 13, 2014 at 09:42:34PM +0530, diliup gabadamudalige wrote:

2. Lists that are read only are better off being tuples?


Possibly. It depends.

As a general rule, tuples may be used for heterogeneous data, lists
should be used for homogeneous data.


To make this less clear, I would say this is a useful rule some of the time. It 
certainly isn't the only criterion one might use for choosing between a tuple 
and a list.



What do I mean by this?

This is a good use for a tuple:
   customer = (name, address, phone_number, status, balance)

You have a fixed number of fields, and each field means something
different (they are hetrogeneous). You should not use a list for
something like this.


Were I using the "heterogeneous data" rule I would be advocaing going to whole 
hog and using a "namedtuple" from the "collections" module. This has the 
advantage of giving each element of the tuple a nice name so that you can refer 
to "customer.address" instead of using magic indices like "customer[1]". That 
makes the code easier to read and easier to write.


But if you're not using namedtuple-like attributes to access the tuple 
elements, then I would not be considering the "heterogeneous data" rule to be 
as relevant in my choice of tuple or list.


There are some advantages to using a tuple as a frozen list, which can't have 
its values modified nor have its size changed. Specificly, if that is your 
intent and your code later tried to change the values (because it is buggy) 
then Python will raise an exception immediately, making it easier to find your 
mistake. If you stick to a list for this situation then the buggy changes will 
go ahead and the error will only be apparent much later when you get the wrong 
results.


Fail early, fail often!

Conversely, there are downsides to using tuples as frozen lists. The most 
obvious is that you can't add lists and tuples together, just lists and lists.  
If you need to add tuples and lists all the time then the surround fiddliness 
required may be enough to push you back to using lists throughout.


Finally, another argument against mixing tuples and lists is simply that it may 
be early optimisation. Unless you're benefiting from the "you can't 
accidentally modify a tuple later" effect, just write it all with lists; it 
will be simpler. You can always come back later after the code is functioning 
correctly and think about tuples.


Cheers,
Cameron Simpson 
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-13 Thread Steven D'Aprano
Albert-Jan, I've been meaning to ask for a long time... I don't suppose 
you're hitting "Forward" rather than "Reply" in your posts are you? 
Because I've never seen replies from anyone else use the same style as 
your replies.

Further comments below.

On Fri, Jun 13, 2014 at 10:14:46AM -0700, Albert-Jan Roskam wrote:

> Hmm, if I create the namedtuple with 'verbose=True' it *really* makes clear 
> why it took so much longer.
> (what's '_property' btw? I know 'property' and the newer decorator wih the 
> same name, but not _property).

_property is just property renamed. If you read the source code to 
namedtuple, you will see something like the line:

_property = property

or possibly:

from builtins import property as _property

That's likely done to make it a local variable, and so a little faster 
(although I don't know why the author bothered, it will make so little 
difference), or possibly to prevent clashes in case the caller defines a 
field name called "property". I'm not sure, but they are my guesses.


[...]
>     v000 = _property(_itemgetter(0), doc='Alias for field number 0')
> 
>     v001 = _property(_itemgetter(1), doc='Alias for field number 1')
> 
>     v002 = _property(_itemgetter(2), doc='Alias for field number 2')

[snip 97 more lines]

Yes, thank you, we get the picture. No need to show 100 examples.



-- 
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-13 Thread Steven D'Aprano
On Fri, Jun 13, 2014 at 09:42:34PM +0530, diliup gabadamudalige wrote:
> Thank you all for these elaborate explanations.
> so would it be wrong to assume that,
> 1. the list or dict if 'large' and not mutated is better declared once in a
> Class and used throughout the program?

There is *no* advantage to writing this:

class Foo:
data = ['a', 'large', 'list']

result = function(Foo.data)


instead of this:

data = ['a', 'large', 'list']
result = function(data)


Just dumping things into a class is not very helpful. You should ask 
yourself:

* Does my code represent a "thing", like a string, or a web server,
  or a customer record? Then a class might be a good solution.

* Does this thing have data and functions that go together? For
  example, a customer record might have data like Account Balance,
  and a function like update_account_balance. Then a class might
  be a good solution.

* Could I have more than one of these "things" at the same time?
  For example, you obviously could have more than one string or 
  customer record. Then a class is probably a good solution.


If none of these things are true, then a class is probably a bad 
solution.


> or
> 2. Lists that are read only are better off being tuples?

Possibly. It depends.

As a general rule, tuples may be used for heterogeneous data, lists 
should be used for homogeneous data. What do I mean by this?

This is a good use for a tuple:

customer = (name, address, phone_number, status, balance)

You have a fixed number of fields, and each field means something 
different (they are hetrogeneous). You should not use a list for 
something like this.


This is a good use for a list:

[value, another_value, a_third_value, ...]

There is an arbitrary number of items, and each item represents the same 
kind of thing (they are homogeneous). Don't think of types, like 
"all the items are floats", but instead think "all the items are a 
person's height".

As a micro-optimization, you might treat tuple as a frozen-list. That's 
not so unusual that you will confuse people by it, but it is a little 
unusual, and a matter of personal taste.


> or
> 3.the list or dict if 'large' and not mutated is better declared once as a
> global variable and used throughout the program?

If it's not mutated, it isn't really a *variable* is it?

But yes, I would consider this the simplest thing that can work. This 
would be my preference.


> The variables, lists carrying variables, and dict. carrying variables are
> declared as a class. So why not include all above in the same class?
> Varables and constans which are used throughout the program in one class
> declared beofr the program enters the main executing loop?
> wouldn't this be fast and the memory usage static up to a point (for all
> declared items in the variables class)?

I'm afraid I don't understand this paragraph. Can you try explaining 
more carefully please?


(By the way: please trim unnecessary quoted text. Your email contained 
dozens of lines of double-quoted > > comments that had nothing to do 
with the questions you asked. If the comments aren't relevant, please 
delete them. Thank you.)



-- 
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-13 Thread Alan Gauld

On 13/06/14 19:20, diliup gabadamudalige wrote:


I declare the following dict at the beginning of the program.

KEY_SIGNATURES = {"C": [], "G": ["F"], "D": ["F", "C"], "A": ["F", "C",
"G"], "E": ["F", "C", "G", "D"], "B": ["F", "C", "G", "D", "A"], "F#":

now in the functions when ever I need to access i just use it.

eg:

sharps_or_flats = KEY_SIGNATURES[key]

or I can create it like this

class Variables():
def __init__(self, adv):
 self.KEY_SIGNATURES = {"C": [], "G": ["F"],

now I call the class with

v=Variables()

now the same dict is
v.Key_SIGNATURES






my questions:
which is better to use and why?


As always there is no absolute answer. It depends on what you
are doing in a wider context.

However from your message you may be missing the point of the class 
solution. The pointy of a class is to bring together the variables

*and the functions* that operate on those variables. So you should
not be doing  v.Key_SIGNATURES  from functions outside the class,
rather you should be defining your functions as methods of the
class and inside those methods using self.Key_SIGNATURES

Also a class called 'variables' is usually a bad design smell.
The class should be called something meaningful in the context
of your program. Something that represents the data and operations
that you have captured within it.

If you discover you have captured two unrelated concepts then
split the class into two. That will encourage reuse but also make
your code much more readable.


Do both remain in memory(separately of course) till I exit the program
once I run it? Will memory usage be the same?


For data this small what happens in memory should be the least of your 
worries. Its much more important to get a design that is readable, 
maintainable and reliable. Only when you have proved there is a

memory issue to solve do you need to start worrying about it.


will the creation of the dict take the same time in both above?


But if you are really worried about it use the timeit module or the 
profiler to find out, don't guess or rely on others guesses.



--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.flickr.com/photos/alangauldphotos

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-13 Thread diliup gabadamudalige
Thank you all for these elaborate explanations.
so would it be wrong to assume that,
1. the list or dict if 'large' and not mutated is better declared once in a
Class and used throughout the program?
or
2. Lists that are read only are better off being tuples?
or
3.the list or dict if 'large' and not mutated is better declared once as a
global variable and used throughout the program?

The variables, lists carrying variables, and dict. carrying variables are
declared as a class. So why not include all above in the same class?
Varables and constans which are used throughout the program in one class
declared beofr the program enters the main executing loop?
wouldn't this be fast and the memory usage static up to a point (for all
declared items in the variables class)?


On Fri, Jun 13, 2014 at 6:38 PM, Steven D'Aprano 
wrote:

> On Fri, Jun 13, 2014 at 05:10:28AM -0700, Albert-Jan Roskam wrote:
>
> > The other day I used collections.namedtuple and I re-initialized
> > Record (see below) with every function*) call. Bad idea! It looks
> > nicer because I did not need a global (and globals are baaad, mkay?),
> > but it was *much* slower. I processed a log of a few million lines, I
> > think.
> >
> > # bad --> time-consuming
> > import collections
> >
> > def do_something_with(raw_record):
> >Record = collections.namedtuple("_", " ".join("v%%03d" % i for i in
> range(100)))
> >return Record(*raw_record.split())
>
> Look at how much work you do here. First, you create a long string of
> the form:
>
> "v000 v001 v002 v003 ... v099"
>
> representing 1000 v-digits names. Then you create a brand new Record
> class that takes those 100 v-digits names as arguments. Creating that
> class requires building a string, parsing it as Python code, and then
> running it. (You're not expected to know that, but if you read the
> source code for namedtuple you will see that's how it works.) So
> creating that class is slow. Every time you call the function, it builds
> a new "v000 ... v099" string, from scratch, then builds a new class,
> also from scratch, and finally populates an instance of that class with
> 100 values from the raw_record.
>
> Only that last step needs to be done inside the function.
>
>
> > # better --> even though it uses a global variable
> > import collections
> >
> > Record = collections.namedtuple("_", " ".join("v%%03d" % i for i in
> range(100)))
>
> [Aside: you may find it easier to debug problems with this if you give
> the namedtuple class a sensible name, like "Record", rather than "_".]
>
> How is that a global *variable*? It's a global name, "Record", but it is
> no more a "variable" than it would be if you did:
>
> class Record(tuple):
> def __new__(cls, v000, v001, v002, ... , v099):
> # code goes here
>
> @property
> def v000(self):
> return self[0]
>
> # likewise for v001, v002, ... v099
> # plus additional methods
>
>
> namedtuple is a factory function which creates a class. Buried deep
> within it is a class statement, just as if you had written the class
> yourself. Normally, when you create a class, you don't treat it as a
> variable, you treat it as a constant, like functions. That is no
> different from classes you create with the class keyword. So "global
> variables are bad" doesn't apply because it's not a variable.
>
> Even if it were a variable, what really matters is not that it gets
> stored in the global scope, but whether or not it gets explicitly passed
> to functions as arguments, or implicitly modified secretly behind the
> scenes. For example:
>
> # Not bad
> data = ["put", "stuff", "here"]
> process(data)
> do_things_with(data)
>
>
> # Bad, for various reasons
> data = ["put", "stuff", "here"]
> process()  # process what?
> do_things_with()  # What are we doing things with?
>
>
>
> In the first case, "data" may be stored in the global scope, but inside
> each function it is treated as a regular local variable. Let's contrast
> how one might operate on a second set of data in each case:
>
> # Too easy
> process(some_other_data)
>
>
> # Ouch, this is painful
> save_data = data
> data = some_other_data
> process()
> data = save_data  # restore the previous value
>
>
> Global variables aren't bad because Moses came down from the mountains
> with a stone tablet that declares that they are bad. They're bad because
> they cause excessive coupling, they operate by side-effect, they spoil
> idepotent code, and they are implicit instead of explicit.
>
>
>
>
> > def do_something_with(raw_record):
> >return Record(*raw_record.split())
>
> Much more sensible!
>
>
>
> --
> Steven
> ___
> Tutor maillist  -  Tutor@python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor
>



-- 
Diliup Gabadamudalige

http://www.diliupg.com
http://soft.diliupg.com/

**
Th

Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-13 Thread diliup gabadamudalige
Thank you all for these elaborate explanations.
so would it be wrong to assume that,
1. the list or dict if 'large' and not mutated is better declared once in a
Class and used throughout the program?
or
2. Lists that are read only are better off being tuples?
or
3.the list or dict if 'large' and not mutated is better declared once as a
global variable and used throughout the program?

The variables, lists carrying variables, and dict. carrying variables are
declared as a class. So why not include all above in the same class?
Variables and constants which are used throughout the program in one class
declared before the program enters the main executing loop?
wouldn't this be fast and the memory usage static up to a point (for all
declared items in the variables class)?


On Fri, Jun 13, 2014 at 9:42 PM, diliup gabadamudalige 
wrote:

> Thank you all for these elaborate explanations.
> so would it be wrong to assume that,
> 1. the list or dict if 'large' and not mutated is better declared once in
> a Class and used throughout the program?
> or
> 2. Lists that are read only are better off being tuples?
> or
> 3.the list or dict if 'large' and not mutated is better declared once as a
> global variable and used throughout the program?
>
> The variables, lists carrying variables, and dict. carrying variables are
> declared as a class. So why not include all above in the same class?
> Varables and constans which are used throughout the program in one class
> declared beofr the program enters the main executing loop?
> wouldn't this be fast and the memory usage static up to a point (for all
> declared items in the variables class)?
>
>
> On Fri, Jun 13, 2014 at 6:38 PM, Steven D'Aprano 
> wrote:
>
>> On Fri, Jun 13, 2014 at 05:10:28AM -0700, Albert-Jan Roskam wrote:
>>
>> > The other day I used collections.namedtuple and I re-initialized
>> > Record (see below) with every function*) call. Bad idea! It looks
>> > nicer because I did not need a global (and globals are baaad, mkay?),
>> > but it was *much* slower. I processed a log of a few million lines, I
>> > think.
>> >
>> > # bad --> time-consuming
>> > import collections
>> >
>> > def do_something_with(raw_record):
>> >Record = collections.namedtuple("_", " ".join("v%%03d" % i for i in
>> range(100)))
>> >return Record(*raw_record.split())
>>
>> Look at how much work you do here. First, you create a long string of
>> the form:
>>
>> "v000 v001 v002 v003 ... v099"
>>
>> representing 1000 v-digits names. Then you create a brand new Record
>> class that takes those 100 v-digits names as arguments. Creating that
>> class requires building a string, parsing it as Python code, and then
>> running it. (You're not expected to know that, but if you read the
>> source code for namedtuple you will see that's how it works.) So
>> creating that class is slow. Every time you call the function, it builds
>> a new "v000 ... v099" string, from scratch, then builds a new class,
>> also from scratch, and finally populates an instance of that class with
>> 100 values from the raw_record.
>>
>> Only that last step needs to be done inside the function.
>>
>>
>> > # better --> even though it uses a global variable
>> > import collections
>> >
>> > Record = collections.namedtuple("_", " ".join("v%%03d" % i for i in
>> range(100)))
>>
>> [Aside: you may find it easier to debug problems with this if you give
>> the namedtuple class a sensible name, like "Record", rather than "_".]
>>
>> How is that a global *variable*? It's a global name, "Record", but it is
>> no more a "variable" than it would be if you did:
>>
>> class Record(tuple):
>> def __new__(cls, v000, v001, v002, ... , v099):
>> # code goes here
>>
>> @property
>> def v000(self):
>> return self[0]
>>
>> # likewise for v001, v002, ... v099
>> # plus additional methods
>>
>>
>> namedtuple is a factory function which creates a class. Buried deep
>> within it is a class statement, just as if you had written the class
>> yourself. Normally, when you create a class, you don't treat it as a
>> variable, you treat it as a constant, like functions. That is no
>> different from classes you create with the class keyword. So "global
>> variables are bad" doesn't apply because it's not a variable.
>>
>> Even if it were a variable, what really matters is not that it gets
>> stored in the global scope, but whether or not it gets explicitly passed
>> to functions as arguments, or implicitly modified secretly behind the
>> scenes. For example:
>>
>> # Not bad
>> data = ["put", "stuff", "here"]
>> process(data)
>> do_things_with(data)
>>
>>
>> # Bad, for various reasons
>> data = ["put", "stuff", "here"]
>> process()  # process what?
>> do_things_with()  # What are we doing things with?
>>
>>
>>
>> In the first case, "data" may be stored in the global scope, but inside
>> each function it is treated as a regular local variable. Let's contrast
>> how one might operate on a second set of data in ea

Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-13 Thread Albert-Jan Roskam


- Original Message -

> From: Steven D'Aprano 
> To: tutor@python.org
> Cc: 
> Sent: Friday, June 13, 2014 3:08 PM
> Subject: Re: [Tutor] global variables/constants versus    volatile    
> variables/constants
> 
> On Fri, Jun 13, 2014 at 05:10:28AM -0700, Albert-Jan Roskam wrote:
> 
>>  The other day I used collections.namedtuple and I re-initialized 
>>  Record (see below) with every function*) call. Bad idea! It looks 
>>  nicer because I did not need a global (and globals are baaad, mkay?), 
>>  but it was *much* slower. I processed a log of a few million lines, I 
>>  think.
>> 
>>  # bad --> time-consuming
>>  import collections
>> 
>>  def do_something_with(raw_record):
>>     Record = collections.namedtuple("_", " 
> ".join("v%%03d" % i for i in range(100)))
>>     return Record(*raw_record.split())
> 
> Look at how much work you do here. First, you create a long string of 
> the form:
> 
>     "v000 v001 v002 v003 ... v099"
> 
> representing 1000 v-digits names. Then you create a brand new Record 
> class that takes those 100 v-digits names as arguments. Creating that 
> class requires building a string, parsing it as Python code, and then 
> running it. (You're not expected to know that, but if you read the 
> source code for namedtuple you will see that's how it works.) So 
> creating that class is slow. Every time you call the function, it builds 
> a new "v000 ... v099" string, from scratch, then builds a new class, 
> also from scratch, and finally populates an instance of that class with 
> 100 values from the raw_record.
> 
> Only that last step needs to be done inside the function.
 
Hmm, if I create the namedtuple with 'verbose=True' it *really* makes clear why 
it took so much longer.
(what's '_property' btw? I know 'property' and the newer decorator wih the same 
name, but not _property).

In [1]: import collections

In [2]: Record = collections.namedtuple("_", " ".join("v%03d" % i for i in 
range(100)),verbose=True)
class _(tuple):
    '_(v000, v001, v002, v003, v004, v005, v006, v007, v008, v009, v010, v011, 
v012, v013, v014, v015, v016, v017, v018, v019, v020, v021, v022, v023, v024, 
v025, v026, v027, v028, v029, v030, v031, v032, v033, v034, v035, v036, v037, 
v038, v039, v040, v041, v042, v043, v044, v045, v046, v047, v048, v049, v050, 
v051, v052, v053, v054, v055, v056, v057, v058, v059, v060, v061, v062, v063, 
v064, v065, v066, v067, v068, v069, v070, v071, v072, v073, v074, v075, v076, 
v077, v078, v079, v080, v081, v082, v083, v084, v085, v086, v087, v088, v089, 
v090, v091, v092, v093, v094, v095, v096, v097, v098, v099)'

    __slots__ = ()

    _fields = ('v000', 'v001', 'v002', 'v003', 'v004', 'v005', 'v006', 'v007', 
'v008', 'v009', 'v010', 'v011', 'v012', 'v013', 'v014', 'v015', 'v016', 'v017', 
'v018', 'v019', 'v020', 'v021', 'v022', 'v023', 'v024', 'v025', 'v026', 'v027', 
'v028', 'v029', 'v030', 'v031', 'v032', 'v033', 'v034', 'v035', 'v036', 'v037', 
'v038', 'v039', 'v040', 'v041', 'v042', 'v043', 'v044', 'v045', 'v046', 'v047', 
'v048', 'v049', 'v050', 'v051', 'v052', 'v053', 'v054', 'v055', 'v056', 'v057', 
'v058', 'v059', 'v060', 'v061', 'v062', 'v063', 'v064', 'v065', 'v066', 'v067', 
'v068', 'v069', 'v070', 'v071', 'v072', 'v073', 'v074', 'v075', 'v076', 'v077', 
'v078', 'v079', 'v080', 'v081', 'v082', 'v083', 'v084', 'v085', 'v086', 'v087', 
'v088', 'v089', 'v090', 'v091', 'v092', 'v093', 'v094', 'v095', 'v096', 'v097', 
'v098', 'v099')

    def __new__(_cls, v000, v001, v002, v003, v004, v005, v006, v007, v008, 
v009, v010, v011, v012, v013, v014, v015, v016, v017, v018, v019, v020, v021, 
v022, v023, v024, v025, v026, v027, v028, v029, v030, v031, v032, v033, v03

Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-13 Thread Steven D'Aprano
On Fri, Jun 13, 2014 at 05:10:28AM -0700, Albert-Jan Roskam wrote:

> The other day I used collections.namedtuple and I re-initialized 
> Record (see below) with every function*) call. Bad idea! It looks 
> nicer because I did not need a global (and globals are baaad, mkay?), 
> but it was *much* slower. I processed a log of a few million lines, I 
> think.
> 
> # bad --> time-consuming
> import collections
> 
> def do_something_with(raw_record):
>    Record = collections.namedtuple("_", " ".join("v%%03d" % i for i in 
> range(100)))
>    return Record(*raw_record.split())

Look at how much work you do here. First, you create a long string of 
the form:

"v000 v001 v002 v003 ... v099"

representing 1000 v-digits names. Then you create a brand new Record 
class that takes those 100 v-digits names as arguments. Creating that 
class requires building a string, parsing it as Python code, and then 
running it. (You're not expected to know that, but if you read the 
source code for namedtuple you will see that's how it works.) So 
creating that class is slow. Every time you call the function, it builds 
a new "v000 ... v099" string, from scratch, then builds a new class, 
also from scratch, and finally populates an instance of that class with 
100 values from the raw_record.

Only that last step needs to be done inside the function.


> # better --> even though it uses a global variable
> import collections
> 
> Record = collections.namedtuple("_", " ".join("v%%03d" % i for i in 
> range(100)))

[Aside: you may find it easier to debug problems with this if you give 
the namedtuple class a sensible name, like "Record", rather than "_".]

How is that a global *variable*? It's a global name, "Record", but it is 
no more a "variable" than it would be if you did:

class Record(tuple):
def __new__(cls, v000, v001, v002, ... , v099):
# code goes here

@property
def v000(self):
return self[0]

# likewise for v001, v002, ... v099
# plus additional methods


namedtuple is a factory function which creates a class. Buried deep 
within it is a class statement, just as if you had written the class 
yourself. Normally, when you create a class, you don't treat it as a 
variable, you treat it as a constant, like functions. That is no 
different from classes you create with the class keyword. So "global 
variables are bad" doesn't apply because it's not a variable.

Even if it were a variable, what really matters is not that it gets 
stored in the global scope, but whether or not it gets explicitly passed 
to functions as arguments, or implicitly modified secretly behind the 
scenes. For example:

# Not bad
data = ["put", "stuff", "here"]
process(data)
do_things_with(data)


# Bad, for various reasons
data = ["put", "stuff", "here"]
process()  # process what?
do_things_with()  # What are we doing things with?



In the first case, "data" may be stored in the global scope, but inside 
each function it is treated as a regular local variable. Let's contrast 
how one might operate on a second set of data in each case:

# Too easy
process(some_other_data)


# Ouch, this is painful
save_data = data
data = some_other_data
process()
data = save_data  # restore the previous value


Global variables aren't bad because Moses came down from the mountains 
with a stone tablet that declares that they are bad. They're bad because 
they cause excessive coupling, they operate by side-effect, they spoil 
idepotent code, and they are implicit instead of explicit.




> def do_something_with(raw_record):
>    return Record(*raw_record.split())

Much more sensible!



-- 
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-13 Thread Albert-Jan Roskam



- Original Message -

> From: Steven D'Aprano 
> To: tutor@python.org
> Cc: 
> Sent: Friday, June 13, 2014 1:45 PM
> Subject: Re: [Tutor] global variables/constants versus volatile   
> variables/constants
> 
> On Fri, Jun 13, 2014 at 12:51:25PM +0530, diliup gabadamudalige wrote:
>>  Hi All!
>>  Hope everyone is well.
>> 
>>  In my code there are many dictionaries and lists which are used in various
>>  functions. Is it better/pythonic/efficient to have these inside the
>>  function itself or declared at the beginning of the program in which case
>>  they will be global? They are all read only. I understand that global
>>  constants and variable have memory allocated to them but when declared
>>  inside a function are created on the fly, used and discarded. Please
>>  enlighten me further on this and correct me if i'm wrong.
> 
> A good question.
> 
> Depending on the size of these dictionaries and lists, worrying about 
> efficiency here may be premature optimization. As they say:
> 
> 
>    "We should forget about small efficiencies, say about 97% of 
>     the time: premature optimization is the root of all evil."
>     -- Donald Knuth

The other day I used collections.namedtuple and I re-initialized Record (see 
below) with every function*) call. Bad idea!
It looks nicer because I did not need a global (and globals are baaad, mkay?), 
but it was *much* slower. I processed a log of a few million lines, I think.

# bad --> time-consuming
import collections

def do_something_with(raw_record):
   Record = collections.namedtuple("_", " ".join("v%%03d" % i for i in 
range(100)))
   return Record(*raw_record.split())

# better --> even though it uses a global variable
import collections

Record = collections.namedtuple("_", " ".join("v%%03d" % i for i in range(100)))

def do_something_with(raw_record):
   return Record(*raw_record.split())



*) the function contained more code, of course! 

Albert-Jan

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-13 Thread Steven D'Aprano
On Fri, Jun 13, 2014 at 12:51:25PM +0530, diliup gabadamudalige wrote:
> Hi All!
> Hope everyone is well.
> 
> In my code there are many dictionaries and lists which are used in various
> functions. Is it better/pythonic/efficient to have these inside the
> function itself or declared at the beginning of the program in which case
> they will be global? They are all read only. I understand that global
> constants and variable have memory allocated to them but when declared
> inside a function are created on the fly, used and discarded. Please
> enlighten me further on this and correct me if i'm wrong.

A good question.

Depending on the size of these dictionaries and lists, worrying about 
efficiency here may be premature optimization. As they say:


   "We should forget about small efficiencies, say about 97% of 
the time: premature optimization is the root of all evil."
-- Donald Knuth


   "The First Rule of Program Optimization: Don't do it. The 
Second Rule of Program Optimization (for experts only!): 
Don't do it yet." -- Michael A. Jackson


   "More computing sins are committed in the name of efficiency
(without necessarily achieving it) than for any other single 
reason — including blind stupidity." -- W.A. Wulf


If these lists and dicts are small, say, fewer than a dozen items, the 
time to create and destroy them is probably trivial, especially if 
you construct them from constant literals. In that case, it's a 
matter of personal taste whether you prefer them as global constants or 
local to a function.

But if it takes a long time to build the list, then you definitely 
should move it outside the function and perform the initialisation step 
only once:

# This may take a while...
PRIMES = [prime(i) for i in range(1, 101)]


If your lists really are read-only, then you should consider turning 
them into tuples:

# Not this:
SOME_ITEMS = ["this", "that", "another"]
# Better:
SOME_ITEMS = ("this", "that", "another")


One advantage of the tuple is that in recent versions of Python, the 
tuple may be compiled as a constant instead of being built at runtime. 
This is from Python 2.7:


py> from dis import dis
py> code = compile("x = [2, 4, 8]", "", "exec")
py> dis(code)
  1   0 LOAD_CONST   0 (2)
  3 LOAD_CONST   1 (4)
  6 LOAD_CONST   2 (8)
  9 BUILD_LIST   3
 12 STORE_NAME   0 (x)
 15 LOAD_CONST   3 (None)
 18 RETURN_VALUE


py> code = compile("x = (2, 4, 8)", "", "exec")
py> dis(code)
  1   0 LOAD_CONST   4 ((2, 4, 8))
  3 STORE_NAME   0 (x)
  6 LOAD_CONST   3 (None)
  9 RETURN_VALUE



-- 
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-13 Thread Dave Angel
diliup gabadamudalige  Wrote in message:
>
 there are many dictionaries and lists which are used in various functions. Is 
it better/pythonic/efficient to have these inside the function itself or 
declared at the beginning of the program in which case they will be global? 
They are all read only. I understand that global constants and variable have 
memory allocated to them but when declared inside a function are created on the 
fly, used and discarded. 
> 

(Please use text mail to post here, not html. Html messages can
 cause several kinds of problems in a text mailing list.
 )

If they are read-only, you don't want to waste time recreating
 them over and over.  Neither do you want to be repeating the code
 that initializes them. So make them either global or a class
 member, and be sure to name them all caps to signify they
 shouldn't be altered. 

-- 
DaveA

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-13 Thread ALAN GAULD
CCing the tutor list.
Please use ReplyAll when responding to the list.
 
Alan Gauld
Author of the Learn To Program website
http://www.alan-g.me.uk/

http://www.flickr.com/photos/alangauldphotos



>
> From: diliup gabadamudalige 
>To: Alan Gauld  
>Sent: Friday, 13 June 2014, 9:32
>Subject: Re: [Tutor] global variables/constants versus volatile 
>variables/constants
> 
>
>
>thanks Alan!
>
>in the program that i am writing i used a class called variables and declare 
>all variables i use in the program in the def __init__ section.
>so all variables which otherwise would have to be declared as global so that 
>they can be modified  by other functions are in a class. 
>Is this ok?
>The strings, lists and dictionaries which are not read only are used as locals 
>in functions and classes.
>If there is a string, list or dict. which is used in several functions is it 
>better to use a global or several locals?
>
>
>
>On Fri, Jun 13, 2014 at 1:25 PM, Alan Gauld  wrote:
>
>On 13/06/14 08:21, diliup gabadamudalige wrote:
>>
>>
>>In my code there are many dictionaries and lists which are used in
>>>various functions. Is it better/pythonic/efficient to have these inside
>>>the function itself or declared at the beginning of the program in which
>>>case they will be global?
>>>
>>
If you are sharing a set of data structures between several functions thats 
often a sign they should be in a class. The data then becomes the class 
instance attributes and the functions become the methods.
>>
>>
>>
>>global constants and variable have memory allocated to them but when
>>>declared inside a function are created on the fly, used and discarded.
>>>
>>
That's not usually the main issue when deciding for global/local.
>>Its more about the maintainability of the code and the over
>>use of side effects which makes the code difficult to read.
>>If the data is read only then things are not so bad and globals
>>can be an OK solution.
>>
>>hth
>>-- 
>>Alan G
>>Author of the Learn to Program web site
>>http://www.alan-g.me.uk/
>>http://www.flickr.com/photos/alangauldphotos
>>
>>___
>>Tutor maillist  -  Tutor@python.org
>>To unsubscribe or change subscription options:
>>https://mail.python.org/mailman/listinfo/tutor
>>
>
>
>
>-- 
>
>Diliup Gabadamudalige
>
>http://www.diliupg.com
>http://soft.diliupg.com/
>
>**
>This e-mail is confidential. It may also be legally privileged. If you are not 
>the intended recipient or have received it in error, please delete it and all 
>copies from your system and notify the sender immediately by return e-mail. 
>Any unauthorized reading, reproducing, printing or further dissemination of 
>this e-mail or its contents is strictly prohibited and may be unlawful. 
>Internet communications cannot be guaranteed to be timely, secure, error or 
>virus-free. The sender does not accept liability for any errors or omissions.
>**
>
>
>
>___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] global variables/constants versus volatile variables/constants

2014-06-13 Thread Alan Gauld

On 13/06/14 08:21, diliup gabadamudalige wrote:


In my code there are many dictionaries and lists which are used in
various functions. Is it better/pythonic/efficient to have these inside
the function itself or declared at the beginning of the program in which
case they will be global?


If you are sharing a set of data structures between several functions 
thats often a sign they should be in a class. The data then becomes the 
class instance attributes and the functions become the methods.



global constants and variable have memory allocated to them but when
declared inside a function are created on the fly, used and discarded.


That's not usually the main issue when deciding for global/local.
Its more about the maintainability of the code and the over
use of side effects which makes the code difficult to read.
If the data is read only then things are not so bad and globals
can be an OK solution.

hth
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.flickr.com/photos/alangauldphotos

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] global variables/constants versus volatile variables/constants

2014-06-13 Thread diliup gabadamudalige
Hi All!
Hope everyone is well.

In my code there are many dictionaries and lists which are used in various
functions. Is it better/pythonic/efficient to have these inside the
function itself or declared at the beginning of the program in which case
they will be global? They are all read only. I understand that global
constants and variable have memory allocated to them but when declared
inside a function are created on the fly, used and discarded. Please
enlighten me further on this and correct me if i'm wrong.

Thank you for your time and may you be well.
-- 
Diliup Gabadamudalige

http://www.diliupg.com
http://soft.diliupg.com/

**
This e-mail is confidential. It may also be legally privileged. If you are
not the intended recipient or have received it in error, please delete it
and all copies from your system and notify the sender immediately by return
e-mail. Any unauthorized reading, reproducing, printing or further
dissemination of this e-mail or its contents is strictly prohibited and may
be unlawful. Internet communications cannot be guaranteed to be timely,
secure, error or virus-free. The sender does not accept liability for any
errors or omissions.
**
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor