Re: [Tutor] lists, name semantics

2015-04-18 Thread Cameron Simpson

On 18Apr2015 22:03, Bill Allen  wrote:

On Apr 18, 2015 4:11 PM, "boB Stepp"  wrote:

On Sat, Apr 18, 2015 at 3:28 PM, Bill Allen  wrote:
> On Apr 18, 2015 7:50 AM, "Peter Otten" <__pete...@web.de> wrote:
>> You can test your newfound knowledge by predicting the output of the
>> following script:
>>
>> a = [1, ["x", "y"], 3]
>> b = a[:]
>>
>> a[1][1] = "hello!"
>>
>> print(a) # [1, ['x', 'hello!'], 3]
>> print(b) # what will that print?
>>
>> Think twice before you answer. What is copied, what is referenced?

> print(b) will print the original copy of a which b now references which

is

> [1, ["x", "y"], 3]

Uh, oh! You should have checked your work in the interpreter before
replying! Peter is being very tricky!! (At least for me...) Look again
at that list inside of a list and... [...]


Ok, just tried it out.  In this example b=a and b=a[:] seem to yield the
same results even after the change to a, which I do not understand.  Should
not b be a copy of a and not reflect the change?


Because is it a _shallow_ copy. Doing this:

 b = a[:]

produces a new list, referenced by "b", with the _same_ references in it as 
"a". a[1] is a reference to this list:


 ["x", "y"]

b[1] is a reference to the _same_ list. So "a[:]" makes what is called a 
"shallow" copy, a new list with references to the same deeper structure.


So this:

 a[1][1] = "hello!"

affects the original x-y list, and both "a" and "b" reference it, so printing 
either shows the change.


By contrast, this:

 a[1] = ["x", "hello"]

_replaces_ the reference in "a" with a reference to a new, different, list.

Sometimes you want a "deep" copy, where "b" would have got a copy of the 
iriginal x-y list. See the "copy" module's "deepcopy" function, which supplies 
this for when it is needed:


 https://docs.python.org/3/library/copy.html#copy.deepcopy

Cheers,
Cameron Simpson 

Draw little boxes with arrows.  It helps.   - Michael J. Eager
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] lists, name semantics

2015-04-18 Thread Cameron Simpson

On 18Apr2015 23:26, boB Stepp  wrote:

On Sat, Apr 18, 2015 at 11:08 PM, Cameron Simpson  wrote:

Sometimes you want a "deep" copy, where "b" would have got a copy of the
iriginal x-y list. See the "copy" module's "deepcopy" function, which
supplies this for when it is needed:

 https://docs.python.org/3/library/copy.html#copy.deepcopy


In this reference, part of it states:

"Two problems often exist with deep copy operations that don’t exist
with shallow copy operations:

Recursive objects (compound objects that, directly or indirectly,
contain a reference to themselves) may cause a recursive loop.
Because deep copy copies everything it may copy too much, e.g.,
administrative data structures that should be shared even between
copies."

If I am understanding things correctly, should not that last sentence
read instead:

"...structures that should *not* be shared even between copies." ???


No, the text is correct.

Suppose you have a graph of objects where some single object A is referenced in 
mulitple places:


 /--> O1 v
 G <  A
 \--> O2 ^

If I make a deepcopy of "G" I want this:

 /--> O1copy v
 Gcopy <  Acopy
 \--> O2copy ^

i.e. a _single_ copy "Acopy" of "A", again referenced from 2 places in the 
copied graph.


Without deepcopy()'s object tracking you would get something like this:

 /--> O1copy > Acopy1
 Gcopy <
 \--> O2copy > Acopy2

i.e. two distinct copies of "A". Changes to "Acopy1" would not affect "Acopy2".

Cheers,
Cameron Simpson 

They said it couldn't be done/they said nobody could do it/
But he tried the thing that couldn't be done!/He tried - and he couldn't do it.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] lists, name semantics

2015-04-18 Thread Cameron Simpson

On 19Apr2015 15:09, Cameron Simpson  wrote:

On 18Apr2015 23:26, boB Stepp  wrote:

On Sat, Apr 18, 2015 at 11:08 PM, Cameron Simpson  wrote:

Sometimes you want a "deep" copy, where "b" would have got a copy of the
iriginal x-y list. See the "copy" module's "deepcopy" function, which
supplies this for when it is needed:

https://docs.python.org/3/library/copy.html#copy.deepcopy


In this reference, part of it states:

"Two problems often exist with deep copy operations that don’t exist
with shallow copy operations:

Recursive objects (compound objects that, directly or indirectly,
contain a reference to themselves) may cause a recursive loop.
Because deep copy copies everything it may copy too much, e.g.,
administrative data structures that should be shared even between
copies."

If I am understanding things correctly, should not that last sentence
read instead:

"...structures that should *not* be shared even between copies." ???


No, the text is correct.


Um, my explaination was incomplete.

The first sentence quoted explains why it is necessary for deepcopy keep track 
of copied objects in order to correctly duplicate objects just once instead of 
twice or more, let alone in an unbounded way if there is a loop (A->B->C->A).  
It does this with a "memo" dictionary of already copied objects so it can know 
them when it sees them again.


The second sentence "Because deep copy copies everything it may copy too much, 
e.g., administrative data structures that should be shared even between copies" 
is an issuewhich is addressed lower down when mentioning the __copy_ and 
__deepcopy__ methods. And it is not necessarily obvious.


Suppose you've got a data structure of objects, which should broadly be copied.  
However, _internally_, these objects may use some external facility. Further, 
suppose that facility can't be copied; perhaps it is a reference to a databse 
or something built around something like that. Like this:


 G -> A
   -> B
   -> _open_database

When you deepcopy that data sctructure you want to copy everything, but _not_ 
copy the external facility object. So for the above example, after the deepcopy 
you want this:


 Gcopy -> Acopy
   -> Bcopy
   -> _open_database

i.e. the same reference to the database, but copies of "A" and "B".

If you give "G"'s class a .__deepcopy__ method, then that will be called by 
deepcopy() to make a copy of "G" by calling "G.__deepcopy__(memodict)". And G's 
class will define its __deepcopy__ method to copy "A" and "B" but not 
"_open_database".


Most classes do not need this and deepcopy() just copies everything.

Does this clarify things?

Cheers,
Cameron Simpson 

No wonder these courtroom dramas are so popular. Half the population are
lawyers, judges, or some other kind of criminal.- Jake Vest 1986
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] introspection

2015-04-21 Thread Cameron Simpson

On 21Apr2015 09:59, Alex Kleider  wrote:

On 2015-04-20 22:21, Danny Yoo wrote:

What's supposed to happen in this situation?
##
class Person(object):
   def __init__(self): pass

j = Person()
john = j
jack = j
##

What single name should we get back from the single Person object
here?  "j", "john", or "jack"?


I was hoping that it would be possible to create a function
that would do the following:

def my_name(some_object):
 return some_object.__name__

so, using what you entered above..

my_name(j)

'j'

my_name(john)

'john'

my_name(jack)

'jack'

But I see what I think you and others have been trying to explain to 
me: that the expression some_object.__name__, if it existed, would 
indeed be schizophrenic since it would be an attribute of the object, 
not the name(s) to which  it is bound.


But it would not be schizophrenic to write a function that returned a name 
arbitrarily, by inspecting locals(). It depends whether you only need a name, 
or if you need "the" name.


Write yourself a "find_name_from_locals(local_map, value)" function that 
reports. That will (a) get you a partial answer and (b) cement in your mind 
what is possible and why. Easy and useful!


Cheers,
Cameron Simpson 

Technique will get you through times of no strength a lot better than
strength will get you through times of no technique.- the Nealomatic
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] calling a method directly

2015-04-21 Thread Cameron Simpson

On 21Apr2015 09:03, alan.ga...@btinternet.com  wrote:

On 21/04/15 05:19, Jim Mooney wrote:

Is there any difference between these two since they give the same result,
and when is the second preferred?


x = 'ABE'
x.lower()

'abe'

str.lower(x)

'abe'


They are essentially the same method being accessed in two
different ways.
The first via the instance,
the second via the class.


Though only because 'x' is directly a str. Not some other class. In Jim's 
example we _know_ 'x' is a str. In general one is less sure, and often one 
hopes not to care!



It's a  bit like when you call a superclass method in OOP:

class C:

...   def f(s): print 'in C'
...

class D(C):

...   def f(s):
... C.f(s)
... print 'and D'
...   def g(s): print 'only D'
...

In the first line of D.f() you invoke C's foo method
by referring to C and passing the local self as the object.


Worth pointing out that this is almost always the only time you cant to call 
via the class directly. And that it is actually common in subclass method 
implementations, particularly __init__, where on must often go:


 class D(C):
   def __init__(self, blah...):
 # initialise the common "C" class related stuff
 C.__init__(self, ...)
 # intialise the specific "D" class related stuff
 ... D-specific-stuff-here ...

[...]

There are very few cases where the class version is preferred,
you nearly always use the instance technique.


Indeed. Not least because (a) you don't always know or even care what class an 
object is and (b) objects themselves can have callable attributes.


Cheers,
Cameron Simpson 

Applications Programming is for dullards who can't do Systems Programming.
   - David Rose, d...@werple.apana.org.au
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Is it possible to "backport" the datetime module of Python 3.3 to Python 3.2?

2015-04-21 Thread Cameron Simpson

On 21Apr2015 22:50, Steven D'Aprano  wrote:

On Tue, Apr 21, 2015 at 12:31:53PM +0100, Mark Lawrence wrote:


Python is very strong in guaranteeing backward compatibility, so why not
copy the 3.3 pure Python code to your 3.2 setup and see what happens?


Normally backwards compatibility refers to the other way: 3.3 will run
3.2 code. To have 3.2 run 3.3 code is *forward compatibility*.


Yes, but it can depend on where you stand.

Mark was talking about taking the 3.3 datetime module code and running it on 
3.2. So in this context, he is suggesting that the _code_ in the 3.3 datetime 
module is probably backward compatible - it has presents features but does not 
depend on 3.3 aspects of the language, and therefore may well run on 3.2.


Cheers,
Cameron Simpson 

The most annoying thing about being without my files after our disc crash was
discovering once again how widespread BLINK was on the web.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Please disable “digest mode” before participating

2015-04-26 Thread Cameron Simpson

On 26Apr2015 15:20, Dave Angel  wrote:

On 04/26/2015 08:07 AM, Ben Finney wrote:

That doesn't reply to the original message. So it lacks the threading
provided by the “In-Reply-To” field, since you're not replying to the
original message. [...]


When I used to subscribe here using digest, and reading with 
Thunderbird, I'd see each message as an attachment.  To reply to one, 
I first opened the appropriate attachment, and did a Reply-List to it. 
WOrked well.


I took a quick look, for another forum which I monitor using the 
digest, and it looks like the same approach would still work.  For 
occasional posting.


Did you check the digest for Mesaage-ID headers for each message item? Most 
digests lack them and as such, replies cannot be stitched together correctly.


You may have been using a mailer with a "group messages by subject" 
(mis?)feature, which may have merely made it look like it worked well.


Cheers,
Cameron Simpson 

I swear to god, officer, I'm fixing this bridge. Just go divert traffic.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Please disable “digest mode” before participating

2015-04-26 Thread Cameron Simpson

On 26Apr2015 22:07, Ben Finney  wrote:

Jim Mooney  writes:

On 25 April 2015 at 18:03, Ben Finney  wrote:
> Digest mode should only ever be used if you know for certain you will
> never be responding to any message.

That brings up a great shortcut if you use gmail. If you select some
text before reply that's All that is sent.


That doesn't reply to the original message. So it lacks the threading
provided by the “In-Reply-To” field, since you're not replying to the
original message.
It also lacks [...]


Yes, but it _does_ point an easy way for people from top-posting 
do-not-trim-quotes cultures to adopt the technophile's 
trim-quotes-for-relevance style which is so useful in discussion (versus 
chatter).


Apple Mail also supports this handy "use the selected text for the context 
quote" technique and I think a number of the other OSX based mail programs.


It doesn't cut it for multipoint quote1-reply1 quote2-reply2 messages, but it 
is a great jumping off point for people new to the method.


_If_ the OP has abandoned digest mode, Jim's pointer is very useful.

Before then I agree that it is far less so, but that is because digests are 
very unfortunate.


Cheers,
Cameron Simpson 

Never belong to any party, always oppose privileged classes and public
plunderers, never lack sympathy with the poor, always remain devoted to
the public welfare, never be satisfied with merely printing news, always
be drastically independent, never be afraid to attack wrong, whether by
predatory plutocracy or predatory poverty. - Joseph Pulitzer, 1907 Speech
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Function works one time then subsequently fails

2015-04-28 Thread Cameron Simpson

On 28Apr2015 20:58, Jim Mooney Py3winXP  wrote:

This is really puzzling me. I'm parsing a string to do some simple math
operations and practice tossing functions around. My parser works on the
first run, then it continually fails on the same input.


[...]

numbers = []

[...]

def parse_string(math_string):
   """Input: A math string with a verbal or mathematical operation
   and two valid numbers to operate on. Extra numbers and operations
   are ignored. Output: A tuple containing a function corresponding
   to the operation and the two numbers. Returns None on failure.
   """
   operation = None
   tokens = math_string.split()
   for token in tokens:
   if token in operations:
   operation = operations[token]
   elif test_number(token) != None:
   numbers.append(test_number(token))
   if len(numbers) > 1:
   break

[...]

At a first glance numbers is a global. It is reset to [] at program start, but 
never again. So you're appending to it forever. I have not investigated further 
as to how that affects your program's flow.


Cheers,
Cameron Simpson 

There are two ways of dealing with this problem: one is complicated and
messy, and the other is simple and very elegant. We don't have much time
left, so I'll just show you the complicated and messy way.
- Richard Feynman, 1981
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Function works one time then subsequently fails

2015-04-28 Thread Cameron Simpson

On 28Apr2015 22:27, Jim Mooney Py3winXP  wrote:

On 28 April 2015 at 21:27, Cameron Simpson  wrote:

At a first glance numbers is a global. It is reset to [] at program start,
but never again. So you're appending to it forever. I have not investigated
further as to how that affects your program's flow.


Took you less time to find that than me. I, of course, realized I forgot to
empty the number list on each time through the parse loop, After I posted
;')  Seems to work okay otherwise, although criticism of Pythonicity is
welcome. I just wanted to practice tossing functions around. I'll put it
into a user input loop and work it. It won't catch everything. I have to
study regexes for that.


Basicly, you should almost never have a global variable. There is a host of 
special circumstances where globals solve some specific problems. But by and 
large, don't do it without a very concrete reason.


If numbers had been local to the parse function you would never have been 
bitten by this. There's no need for it to be global; you can return the 
operator and the operands (numbers) easily from the parse function.



At this point I'm starting to lose track and have to think of better ways
to organize so I recall and understand what I'm doing. I know there are
general tuts on that but that's just reading. Is there a python-specific
tut on it where I could follow actual code along with the interpreter to
reinforce things? Or, what is the official word for
organize-so-you-don't-forget-or-get-confused so I can search google with it?


"functional decomposition"?

One rule of thumb is that functions should be short. That way you can generally 
keep their purpose and internal oparations in your head in one go, and the 
whole thing also fits on your screen.


As with all things, sometimes that cannot be reasonably achieved, but it is 
usually so.


We can pick over your code as well if you like. Should we?

Cheers,
Cameron Simpson 

If this experiment we're doing works, then I will follow up and push it as
hard as possible. And if it doesn't work, I will write a science-fiction
novel where it does work. It's a win-win situation.
- John Cramer on his experiment for possible cuasality violation
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed?

2015-04-29 Thread Cameron Simpson

On 29Apr2015 12:12, boB Stepp  wrote:

... (3) install git if needed ...


It seems Git is needed, but I am not allowed to install it on the
Solaris workstation. So is there a way around this?


What do you mean by "install"? Bear in mind that while you may be forbidden 
from installing git in the main areas (/usr, /usr/local, whatever), you may be 
free to install it in your own home directory. It is just an executable...


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


Re: [Tutor] Fwd: Function works one time then subsequently fails

2015-04-29 Thread Cameron Simpson

On 29Apr2015 08:34, Jim Mooney Py3.4.3winXP  wrote:

On 28 April 2015 at 22:40, Cameron Simpson  wrote:

We can pick over your code as well if you like. Should we?


Sure, but let me include the full working program after fixup. Although I
still have to write another program to feed it random problems to work it
out. It's a bit spacey, but I ran it through the pep8 program and it
suggested that. I think two spaces between such tiny functions is overkill,
though.

"""
Takes the name of a binary math operation and two numbers from input,
repeatedly, and displays the results until done
"""

def add(a, b):
   return a + b


def subtract(a, b):
   return b - a


def minus(a, b):
   return a - b


These could all do with docstrings. add() is pretty obvious, but the 
distinction between minus() and subtract() could do with elaboration.


Also, I would be inclined to define minus() in terms of subtract(), not because 
it is faster but because it establishes an equivalence.



def multiply(a, b):
   return a * b


def divide(a, b):
   return a / b


operations = {'add': add, '+': add, 'plus': add, 'subtract': subtract,
'subtracted': subtract,
 '-': minus, 'minus': minus, 'multiply': multiply, '*':
multiply, 'multiplied': multiply,
 'times': multiply, 'divide': divide, '/': divide, 'divided':
divide}


I'd make this much more vertical, like this:

 operations = {'add': add,
   '+': add,
   'plus': add,
   'subtract': subtract,
   'subtracted': subtract,

Easier to maintain, easier to read, easier to modify, and if you use version 
control you will get much more meaningful diff output with changes, which aids 
code review (which more or less equates to readability and maintainability).



def test_number(astring):
   """
   Input: A string that should represent a valid int or float. Output:
   An int or float on success. None on failure.
   """
   for make_type in (int, float):
   try:
   return make_type(astring)
   except ValueError:
   pass
   return None


If this is a test function, it should return True or False.

Other have already remarked on this in other threads: the Pythonic way to do 
this is usually to attempt the conversion and let an exception get out:


 def numberify(astring):
 return float(astring)

Consider the calling code. What are you going to do with it. I see you probe 
first, which makes some sense in lexical analysis:



def parse_string(math_string):
   """Input: A math string with a verbal or mathematical operation
   and two valid numbers to operate on. Extra numbers and operations
   are ignored. Output: A tuple containing a function corresponding
   to the operation and the two numbers. Returns None on failure.
   """
   operation = None
   tokens = math_string.split()
   numbers = []
   for token in tokens:
   if token in operations:
   operation = operations[token]
   elif test_number(token) != None:
   numbers.append(test_number(token))
   if len(numbers) > 1:
   break
   if operation is None or len(numbers) < 2:
   return None
   else:
   return operation, numbers[0], numbers[1]


As a lexical exercise probing (test then act) is pretty common and normal.  

However, an alternative way to structure this is the "ask for forgiveness" 
approach:


 try:
   operation = operations[token]
 except KeyError:
   value = numberify(token)
   numbers.append(value)

This will raise ValueError if it is neither an operation nor a number.

The practice of raising an exception permits a mode of programming where both 
your code and the caller can broadly write the code as though values are 
generally valid, and avoids a lot error catching verbiage that obscures the 
core logic.


In that vein, you would also modify the function to raise an exception 
(typically ValueError) for other invalid math_strings. The advantage here is 
that the caller can use your function like this:


 operation, *arguments = parse_string(math_string)

and not perform any special testing for getting None back. Instead, the caller 
can plow on as though the math_string was valid as well. An exception can 
bubble up to a suitable catch point, such as the main loop which reads strings 
from the user.



instructions = '''Enter two numbers and one of the four basid math
operations,
either mathematical or verbal. i.e. 3 + 2, 12 divided by 14, 10 minus 4,
etc.
Enter done to quit.
'''
try:
   user_input = input(instructions)
   while True:
   if user_input == 'done':
   break


While most programs will accept a special token 

Re: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed?

2015-04-29 Thread Cameron Simpson

On 29Apr2015 22:10, boB Stepp  wrote:

On Wed, Apr 29, 2015 at 9:40 PM, Cameron Simpson  wrote:

On 29Apr2015 12:12, boB Stepp  wrote:

... (3) install git if needed ...


It seems Git is needed, but I am not allowed to install it on the
Solaris workstation. So is there a way around this?


What do you mean by "install"? Bear in mind that while you may be forbidden
from installing git in the main areas (/usr, /usr/local, whatever), you may
be free to install it in your own home directory. It is just an
executable...


On the smart enterprise where we (now) do our clinical planning they
are very strict: no installing any external software; no accessing the
Internet; no email; etc. Not all centers adhere to this level of
strictness, but ours does. [...] But I am reluctant to do
anything that I am not allowed to replicate on smart enterprise. I am
trying to keep it as close to identical to the actual clinical
environment as I can.


And fair enough too. I frequently wish our developers' dev environments more 
rigorously modelled the target environment.



Perhaps this is misguided on my part?


Not necessarily.

But I would be inclined to distinguish your working tools from the target 
environment.


For example, I commend you making your dev environment as close to identical to 
the actual clinical environment as you can. But I wouldn't deprive yourself of 
tools that enhance your code management practices without affecting that 
environment.


For example, there is much to be said for tracking your changes with a tool 
like git or hg. It encourages your to annotate your changes, and lets you 
review history to see when and why some change occurred, especially if a new 
bug has arisen. Distributed version control systems like git and hg also make 
it easier to work on distinct changes to the same code as separate work 
processes; of course the price for such a workflow is that you need to merge 
the two things later and ensure that they do not interact badly.


If you're serious about keeping the two environments very similar, you could 
always do your _coding_ on a third platform (a laptop or whatever) using your 
desired tools and _deploy_ the code to the dev (and later, prod) environments 
from there, keeping the dev environment pristine. By "deploy", that can be as 
simple as copying the code to the target.


Just thoughts; of course you must choose practices that suit your needs and 
plans.


Cheers,
Cameron Simpson 

Nothing is impossible for the man who doesn't have to do it.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Python property()

2015-05-16 Thread Cameron Simpson
As Alan and I disagree on this, to a degree, I thought I would follow up to add 
another perspective. Remember that it is _only_ perspective; Alan's opinions 
are sound and have good reasons. So are mine:-) We place different values on 
the costs and benefits here.


On 17May2015 00:27, alan.ga...@btinternet.com  wrote:

On 16/05/15 20:25, daaku gee wrote:

I think I understand what's going on here.  What I don't understand is
if/when to use property instead of a normal attribute.

1. Is 'property' used widely? Do you use it?


No,
Yes, occasionally


For me: somewhat, and yes.

[...snip...]

2. Would you use it only when you need to validate or calculate the value
to be assigned to an attribute or is there any other place for 'property()'
to be used?


Those are the main use cases for me.
Calculating values can be an important one though,
especially if it avoids the need for lots of methods
to update some attribute like size. You can calculate
it at runtime and expose the method to look like a
data item.

But that in itself can be done by a method,
the real driver to a property is when I'm using the
class in a polymorphic relationship with other classes
that do have a data attribute and I want mixed access
with a common interface.


Here we differ, at least in where we draw the line. I am very fond of the 
"property to calculate a value". It makes for more readable code:


 foo.volume() + bah.volume()
versus
 foo.volume + bah.volume

with less syntactic noise.

The "foo" and "bah" objects here might compute their volume from their more 
basic attributes, perhaps length, height etc.


For Alan, using a property here provides no fundamental advantage over a method 
call, especially since a property _is_ a method call underneath. He feels that 
it breaks the OO model and as he mentions above, makes polymorphic use harder 
because different types of objects might readily provide a .volume() method but 
not a property.


For me, when the property such as .volume is (a) a basic thing trivially and 
_repeatably_ computed from the other attributes and (b) cheap (usually O(1) to 
compute, not requiring complex and expensive operations) and (c) having no side 
effects such as creating files etc then I may often choose to use a property.


To me, the method/property distinction is in how the value it thought of:

A "computed", potentially complex or changing thing. This is a method.

A "direct" and simple thing, almost free to compute and (usually) stable. This 
may be a property.


If you need to pass parameters other than "self", obviously it must be a 
method.



3. If there is value in learning and using property, kindly explain it or
point me to a document/writeup/book that I should read to get a better
understanding.


Oddly enough I'm currently reviewing a book that addresses
this quite well in a chapter on properties. But it won't
be published till later in the year so not much help to
you just now.

Personally I wouldn't worry about them until you think you've
found a real use for them. There are plenty other things to
be doing first!


I'm in agreement here.

Become comfortable with methods and using them. Until that is second nature you 
won't have much feel for when you may choose to use a property.


Cheers,
Cameron Simpson 

Heavier-than-air flying machines are impossible.
 --Lord Kelvin, president, Royal Society, 1895.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] ls *.py[co] >> .hidden

2015-05-21 Thread Cameron Simpson

On 21May2015 17:52, Laura Creighton  wrote:

If you keep appending the results of ls to your .hidden file
it will grow to enormous size. [...]

sort -u .hidden >newhidden #or whatever you want to call it
mv newhidden .hidden


Or:

 sort -u -o .hidden .hidden

Cheers,
Cameron Simpson 

[...] post-block actions should be allowed everywhere, not just on
subroutines. The ALWAYS keyword was agreed upon as a good way of doing
this, although POST was also suggested. This lead to the semi-inevitable
rehash of the try- catch exception handling debate. According to John
Porter, "There is no try, there is only do. :-)"
- from the perl6 development discussion
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Is there a way to use "with" across suite boundaries?

2015-05-24 Thread Cameron Simpson

On 22May2015 22:56, Jim Mooney Py3.4.3winXP  wrote:

'''I was using with open...:, but I'm printing a header in one function,
calling a looping
function to print detail lines, then returning to the calling function to
print
the footer. But that didn't work since the with statement only seems to work
with the lexical suite and the file wasn't open in the detail print
function. Is there
a way around this, other than passing the file as I have here? Also, is it a
good idea to pass a file handle like that or is there a better way?


It is just fine. Example:

 with open("blah", "w") as blahfp:
   print("header", file=blahfp)
   print_details(blahfp, ...)
   print("footer", file=blahfp)

 def print_details(fp, blah_info):
   ... loop using blah_info to write data to "fp"

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


Re: [Tutor] Yielding from a with block

2015-05-27 Thread Cameron Simpson

On 27May2015 23:27, Oscar Benjamin  wrote:

On 23 May 2015 at 10:52, Peter Otten <__pete...@web.de> wrote:

import csv


I'm just wondering what other people think about this. Should code
like make_lines below be discouraged?


In my opinion, no.


def make_lines():
with open('co2-sample.csv') as co2:
yield htbegin
for linelist in csv.reader(co2):
yield from fprint(linelist)
yield htend


def fprint(linelist):
yield ("{}{}{}"
   "{}{}{}\n").format(*linelist)
yield '\n'


There's a fundamental contradiction between the with and yield
statements. With means "don't exit this block without running my
finalisation routine". Yield means "immediately exit this block
without doing anything (including any finalisation routines) and then
allow anything else to occur".


Not really. Yield passes a return value back to the iterator user and _pauses_ 
execution of the generator. The generator's execution context is _still_ inside 
the "with".


Certainly if the user/consumer of the generator does not consume all the way to 
the end then the "with" exit code won't fire. At least in a timely fashion; 
might it fire during the cleanup phase? I'd think so.


However, the common circumstance is that the consumer does run to the end of 
the iterator, and therefore the "with" exit process _will_ run when because 
that is a standard part of the generator's execution.


BTW, I think including the fprint() function here is a furphy; it doesn't 
affect the issue discussed.



Using yield inside a with statement like this renders the with
statement pointless:


This is not true.


either way we're really depending on __del__ to
execute the finalisation code. So it with or without the with
statement it will work fine on CPython. On other implementations it
may or may not close the file with or without the with statement. IOW
the with statement is not able to provide the guarantees normally
expected of it when used this way.


If make_lines() above runs to completion then the "with" exit process will also 
run and everything will be fine.


It is only when make_lines() is not completely consumed that the file may not 
be closed in a timely fashion.


Why? Because the consumer does not get to see end-of-iterator until 
make_lines() actually returns, and that directly implies completion of the 
"with" exit phase.



It's usually fairly trivial to rearrange things so that this doesn't happen:

def wrap_header_footer(fin):
   yield htbegin
   for linelist in csv.reader(fin):
   yield from fprint(linelist)
   yield htend


I would not encourage this kind of thing except in quite special circumstance.  
For your example, failure to completely consume make_ines() will result in 
invalid HTML output (missing closing "htend", for example). So the result of 
the entire process will be invalid anyway, with the leaked open file just 
another side effect.


Normally (ignoring unbounded iterators), the same scenario will apply: you 
always iterate to the end of somehting like your example because to do 
otherwise will usually result in an invalid/incorrect final result. So while 
technically the risk you describe exists, in practice it will almost never 
occur unless the larger program outcome also results in failure of some kind.


Cheers,
Cameron Simpson 

I object to doing things that computers can do. - Olin Shivers
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to close a Tkinter window from a different thread?

2015-05-27 Thread Cameron Simpson

On 27May2015 16:42, boB Stepp  wrote:

Python 2.4.4, Solaris 10
I realize that this is a bit old, but I got severely sidetracked! ~(:>)

[...]

On Mon, Apr 20, 2015 at 2:10 AM, Alan Gauld  wrote:

I would suggest forgetting about windows and think about
the processes that create them. Use the OS tools (via
the os module) to see if the first process is still running.
If so kill the process - which will in turn kill the window.


Is this a reasonable way to determine if a given pid is still active?
I found this at:

http://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid

import os

def check_pid(pid):
   """ Check For the existence of a unix pid. """
   try:
   os.kill(pid, 0)
   except OSError:
   return False
   else:
   return True

I realize that this will also return True if I don't have permissions
to kill, or some such.


Yes it is reasonable and normal. However the clean way to do it involves an 
extra test:


try:
os.kill(pid, 0)
except except OSError as e:
if e.errno == errno.EPERM:
  return True
return False
else:
return True

Do bear in mind that process ids repeat. So on a busy system (or if your own 
program is very long lived and the original process exited a long time ago) you 
might be polling that pid as used by something unrelated.


However, if you started the process directly and it has not been wait()ed for, 
then the pid will not be available for reuse and you will be ok.



You can find the process based on its name or based on
its PID which you could store in a file somewhere
(like in /tmp?)


I can implement this, but thinking about this anew has led to a
concern. Hypothetically, if I check for the existence of a running
process based on this stored pid, what is the likelihood that the pid
will be reassigned to something other than one of my program's windows
left open?


As discussed above. Possible but unlikely. And if you are the creator of the 
original process you can control the situation.


Cheers,
Cameron Simpson 

Processes are like potatoes.- NCR device driver manual
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Generate Prime Numbers

2015-05-29 Thread Cameron Simpson

On 29May2015 18:48, alan.ga...@btinternet.com  wrote:

On 29/05/15 16:28, Mirage Web Studio wrote:

def IsDivisibleBy3(number):#string variable
v=0
for c in number:
v=v+int(c)
if v%3==0:
return True
else:
return False


def IsDivisibleBy3(number):#string variable
   return not int(number) % 3


To illustrate that there isn't just One Right Way, I would code the above like 
this:


 def IsDivisibleBy3(number): #string variable
 return int(number) % 3 == 0

Alan's code relies on "not" using an expressions "nonzero"ness as a boolean 
value. I _much_ prefer to directly state the test instead of relying on magic 
numeric=>boolean effects.


The only other remark I would make is that it is probably a ba idea to write 
this function to take a string. It expresses a numerics test - make it take a 
number! Do the string conversion-to-int outside the function before it is 
called.



def IsDivisibleBy7(number):#string variable


See above, but maybe better still

def isDivisibleByN(number, N):
  return not int(number)%N


Indeed, but again I would write an outright numeric expression and not rely on 
"not(numeric-expression)".



def IsPrime(number):


Google for the "sieve of eratosthenes"
Or look it up on wikipedia.
That will give one of several possible
improvements to your algorithm.


Plus, it is incredibly easy to code the SoE in Python. So easy that I once did 
it in about a minute in a Code Wars session. It is a lovely algorithm which is 
easy to remember.



primelist=[]

for i in range (11,20,2):
number=str(i)
print "checking ",i

if IsPrime(number):


Note, you are starting with a number, then converting
it to a string then in your functions converting it
back to a number.
That's crazy!


Indeed! Numbers throughout if at all possible.

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


Re: [Tutor] unittest with random population data

2015-05-30 Thread Cameron Simpson

On 30May2015 12:16, Sydney Shall  wrote:

Following advice from you generous people, I have chosen a project >that 
interests me, to develop some knowledge of python.
My projest is a simulation of a biological population.
I have a base class and a simulation function, which uses instances of 
the class.
This, after many months of work and lots of advice, now seems to work 
well. It generates sensible data and when I write a small test program 
it gives sensible output.

Now I want to learn to use unittest.
I have written a unittest class which works OK.
But the problem I have is that because I use the random module to 
populate my initial arrays, my data is not strictly predictable even 
though I am using seed(0). So the tests return many *fails* because 
the numbers are not exactly correct, although they are all rather 
close, consistent with the sigma value I have chosen for the spread of 
my population. I do of course use *almostEqual* and not *Equal*.


First of all, several people have posted suggestions for getting identical 
results on every run.


However, there is another approach, which you might consider. (And use in 
addition, not inseadt of, the reproducable suggestions).


It is all very well to have a unit test that runs exactly the same with a test 
set of data - it lets you have confidence that algorithm changes do not change 
the outcome. But on for that data set.


You say that your results are "all rather close, consistent with the sigma
value I have chosen for the spread of my population". I would advocate making 
some "contraint" tests that verify this property for _any_ input data set.


Then you can run with random and _changing_ input data sets to verify that your 
code produces the expected _kind_ of results with many data sets.


So you would have one test which ran with a fixed data set which confirms 
preidctable unchanging results. And you have other tests with run with randomly 
chosen data and confirms that outcomes fall within the parameters you expect.  
You can apply those checks ("outcome in range") to both sets of tests.


As an exmaple, I have a few classes which maintain data structures which are 
sensitive to boundary conditions. The glaring example is a numeric range class 
which stores contiguous ranges efficiently (a sequence of (low,high) pairs). It 
has a few add/remove operations which are meant to maintain that sequence on 
ordered minimal form. cutting and merging adjacent ranges is very easy to get 
wrong, very sensitive to off-by-one logic errors.


So my tests for this class include some random tests which do random 
unpredictable add/remove operations, and run a consistency check on the object 
after each operation. This gives me good odds of exercising some tricky 
sequence which I have not considered explicitly myself.


You can see the test suite here:

 https://bitbucket.org/cameron_simpson/css/src/tip/lib/python/cs/range_tests.py

It has a bunch of explicit specific tests up the top, and then the random 
consistency test down the bottom as "test30random_set_equivalence".


Cheers,
Cameron Simpson 

MS-Word is Not a document exchange format - Jeff Goldberg
http://www.goldmark.org/netrants/no-word/attach.html
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] unittest with random population data

2015-06-03 Thread Cameron Simpson

[ I've taken this discussion back to the tutor list. - Cameron ]

On 01Jun2015 18:14, Sydney Shall  wrote:

On 31/05/2015 03:00, Cameron Simpson wrote:

You say that your results are "all rather close, consistent with the sigma
value I have chosen for the spread of my population". I would advocate
making some "contraint" tests that verify this property for _any_ input
data set.

Then you can run with random and _changing_ input data sets to verify
that your code produces the expected _kind_ of results with many data sets.

[...]

range class which stores contiguous ranges efficiently (a sequence of
(low,high) pairs). It has a few add/remove operations which are meant to
maintain that sequence on ordered minimal form. cutting and merging
adjacent ranges is very easy to get wrong, very sensitive to off-by-one
logic errors.

So my tests for this class include some random tests which do random
unpredictable add/remove operations, and run a consistency check on the
object after each operation. This gives me good odds of exercising some
tricky sequence which I have not considered explicitly myself.

You can see the test suite here:
 https://bitbucket.org/cameron_simpson/css/src/tip/lib/python/cs/range_tests.py


I have studied the material you indicated and it has been most
helpful. I think that I have understood the principle involved, but I
have had some problem implementing it.

The range tests are mostly clear to me but there is one aspect I 
cannot follow.
You use in this suite imports from Range, including Range, overlap, 
spans and Span.
Are these programs that you have written? If so, are they specific to 
your set up or are they generic? If so, is it possible to obtain these 
programs?


The "cs.range" is a module of my own. As you might imagine, cs.range_tests has 
the entire purpose of testing cs.range. cs.range is here:


 https://bitbucket.org/cameron_simpson/css/src/tip/lib/python/cs/range.py

Feel free. Since it in turn has some dependencies the easiest way to get it is 
to use "pip" to install it, as pip will also fetch and insteall its 
dependencies. But if you just want something to read, fetch and enjoy.


I have established a very primitive test suite based on your cs.range >notions 

and it works fine, but it would be better, I am sure, to do it >properly.

There are many other people whose test writing ability surpasses mine.  But 
you're welcome to learn anything you can from mine, and to ask questions.  

Finally, I have one comment for the respected Moderator, if he is not 
out on a walk in the highlands in this cold  and wet weather.


I have taken the liberty of raising my problem here rather than 
elsewhere, because I have observed that the biological and bio-medical 
community, who always come late to new notions, is now rapidly 
discovering  python. A great deal of work in these fields involve 
either stochastic simulations or statistical problems of analysis. The 
latter are more or less straight-forward, but the simulations are not.


You might ask a separate question on the python-l...@python.org about 
simulations. It has a wider audience than the tutor list and may well include 
people doing simulation work, or who know where to look.


Thanks for all the help. You people are a model of how we could 
perhaps civilize humanity.


Nah. We might all be striving to be a model of how humanity might be when 
civilised though...


Cheers,
Cameron Simpson 

You my man are a danger to society and should be taken out of society for all
our sakes. As to what is done to you once removed I couldn't care less.
   - Roy G. Culley, Unix Systems Administrator
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] string delimiters

2015-06-03 Thread Cameron Simpson

On 03Jun2015 14:16, Alex Kleider  wrote:

On 2015-06-03 12:53, Alan Gauld wrote:
...

If this is really about parsing dates and times have
you looked at the datetime module and its parsing/formatting
functions (ie strptime/strftime)?


I asssume strftime gets its name from 'string from time.'
What about strptime? How did that get its name?


No, they both come from the standard C library functions of the same names, 
being "(f)ormat a time as a string" and "(p)arse a time from a string". The 
shape of the name is because they're "str"ing related functions, hence the 
prefix.


See "man 3 strptime" and "man 3 strftime".

Cheers,
Cameron Simpson 

A program in conformance will not tend to stay in conformance, because even if
it doesn't change, the standard will.   - Norman Diamond 
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] string delimiters

2015-06-03 Thread Cameron Simpson

On 03Jun2015 17:35, richard kappler  wrote:

Perhaps the better way for me to have asked this question would have been:

How can I find the location within a string of every instance of a
character such as ']'?


With the str.find method!

 s = 'a]b]c'
 pos = s.find(']')
 while pos >= 0:
   print("pos =", pos)
   pos = s.find(']', pos + 1)

Obviously you could recast that as a generator funciton yielding positions for 
general purpose use.


Cheers,
Cameron Simpson 

Serious error.
All shortcuts have disappeared.
Screen. Mind. Both are blank.
- Haiku Error Messages 
http://www.salonmagazine.com/21st/chal/1998/02/10chal2.html
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] line iteration in a file

2015-06-03 Thread Cameron Simpson

On 03Jun2015 22:37, richard kappler  wrote:

Figured out the string delimiters problem, thanks for all the help. Now
I've run into another.

I've used the re.finditer that I think it was Peter suggested. So I have:

for line in file:
   s = line
   t = [m.start() for m in re.finditer(r"]", s)]
   q = len(t)

which works fine, in testing it finds the number and position of the ]'s in
any line I throw at it. I then wrote a series of if/elif statements based
on q, in other words

if q == 1:
   do something
elif q == 2:
   do something else
elif q == 3:
   do a third thing
else:
   pass

as I looked through enough example to figure out that the most ]'s I can
have is 3, but the pass is there just in case.

I keep getting a list index out of range error, and my best guess is that
it's because t and q are set on the first line read, not each line read, is
that right? If not, what might be the problem and either way, how do I fix
it?


Please post a self contained example (i.e. small complete code, not snippets) 
and a transcribe of the full error message with stack backtrace.  What you have 
above is not enough to figure out what is going wrong. If what you display 
above is accurate then t and q are set for every line read.


Another remark, what is the use of your "else: pass" code? Normally one would 
put some action here, such as raising an exception for the unhandled value or 
issuing a warning.


Cheers,
Cameron Simpson 

My computer always does exactly what I tell it to do but sometimes I have
trouble finding out what it was that I told it to do.
   - Dick Wexelblat 
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


tutor@python.org

2015-06-11 Thread Cameron Simpson

On 11Jun2015 18:55, alan.ga...@btinternet.com  wrote:

On 11/06/15 14:25, Michelle Meiduo Wu wrote:

I read some document and found Pytest can be used to write
simpler code compared with using unittest in Python.


Yes, but PyTest (and unittest) are for testing units of Python
code. So they really only apply if your application is written
in Python.


Though if you like the framework, you could write very thin Python wrappers 
calling something else, and test them. Might be more trouble thatn it is worth 
though.



And in any case you should really have written
all the unit tests long before completing your application.


Ah, the S-word :-)

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


Re: [Tutor] method conflict?

2015-07-02 Thread Cameron Simpson

On 02Jul2015 17:39, Jim Mooney Py3.4.3winXP  wrote:

Okay, it appears the method in a class has its own ID, but all
instantiations of that method have identical IDs. But what happens if we
have a huge number of instantiations trying to access the identical method
at the same time?


Um, they all get given access to the method? I'm not sure what you think should 
be happening here:



class MyClass:
   def setdata(self, data):
   self.data = data
   def getdata(self):
   print(self.data)


MyClass.setdata



id(MyClass.setdata)

40676568

f = MyClass()
g = MyClass()


Two instances of the class.


id(f.setdata)

43576616

id(g.setdata)

43576616


Two references to the same method obtained from the class.


d = MyClass()
id(d.setdata)

43576616


And a third.

Steven D'Aprano posted a decent explaination in your other thread ("Are the 
methods in a class copied or just linked to?"); it would have been helpful if 
your post had stayed in that thread - it is essentially the same discussion.


So all your "d.setdata" expressions consult various places in order to find the 
method definition, and they all find it in the class. And so you are given the 
same method every time, and thus the same id.


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


Re: [Tutor] String Problem

2015-07-06 Thread Cameron Simpson

On 06Jul2015 15:44, Crusier  wrote:

Dear All,

I have used the urllib.request and download some of the information from a
site.

I am currently using Python 3.4. My program is as follows:

import urllib.request

response = urllib.request.urlopen('
http://www.hkex.com.hk/eng/ddp/Contract_Details.asp?PId=175')

saveFile = open('HKEX.txt','w')
saveFile.write(str(response.read()))
saveFile.close()

And the result is as follows:

d align="right"> - 0
[...]

Please let me know how to deal with this string. I hope I could put onto a
table first. Eventually, I am hoping that I can able to put all this
database. I need some guidance of which area of coding I should look into.


Look into the BeautifulSoup library, which will parse HTML. That will let you 
locate the TABLE element and extract the content by walking the rows (TR) and 
cells (TD).


Start here:

 http://www.crummy.com/software/BeautifulSoup/bs4/doc/

You can install bs4 using pip, or in other ways:

 http://www.crummy.com/software/BeautifulSoup/bs4/doc/#installing-beautiful-soup

Cheers,
Cameron Simpson 

30 years ago, I made some outrageous promises about AI. I didn't deliver.
Neither did you. This is all your fault. - Marvin Minsky, IJCAI'91 (summary)
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Socket Module

2015-07-12 Thread Cameron Simpson

On 12Jul2015 22:36, Nym City  wrote:

Hello,
I am working on a 2 individual programs. In the first program, I am taking in a 
list of domains in .csv format and want to get the associated IPs.
In the second program, I want to import in a list of IP .csv and than get the 
associated domains out.
Eventually I want to get both of the above programs to write out to the same 
.csv file that they are reading from- in the next column. But I am not there 
yet.
Doing research I came across the following 
example:http://python.about.com/od/pythonstandardlibrary/qt/dnscheck.htm
From the link above, doing domain -> IP would be easier to begin with. Here are 
the two variations of my code:

Variation 1:
import csv
import socket

domains = open('top500domains.csv', 'r')
for domain in domains:


You're getting a whole line here, including the traling newline. Add this line:

   print("domain=%r" % (domain,))

at the start of the loop to see this.


    domain = socket.gethostbyname(str(domains))


There's no point converting a line to str; a line is a str. If you're wokring 
from example code I suppose you might have mistyped "strip".


Anyway, you're passing a string ending in a newline to gethostbyname. It will 
not resolve.



    print(domains + "\n")
For the code above, I receive the following error on run: socket.gaierror: 
[Errno -2] Name or service not known.


As the exception suggests. When debugging issues like these, _always_ put in 
print() calls ahead of the failing function to ensure that you are passing the 
values you think you're passing.



Variation 2:
import csv
import socketdomains = []

with open('top500domains.csv', 'r') as f:
    for line in f:
    line = line.strip()
    domains.append(line)

hostbyname_ex = socket.gethostbyname_ex(str(domains))


gethostbyname_ex takes a single hostname string. You are passing a list of 
strings.



print(hostbyname_ex)
I receive the same error as the first variation.
Please share your advice and let me know what I am doing wrong. The 
top500domains.csv list is attached.


Plenty of mailing list software strips attachments. In future, unless the file 
is large, just append the contents below your message (with some explaination).


Cheers,
Cameron Simpson 

Life is uncertain.  Eat dessert first.  - Jim Blandy
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] _ vs. _name vs. __name vs. name_ vs. __name__ usages

2015-07-27 Thread Cameron Simpson
e to indicate their flavour. That works just fine.  
But when I want to access the object, "type" is also a natural name for the 
parameter:


 def check_type(self, type):
   return self.type == type

While that works, it means you have lost access to the predefined Python type() 
function inside that bit of code. Which can be bad. Even if you do not use the 
function, it makes your code confusing for other programmers (== you several 
months later) because they have an expectation of its meaning.


Way of addressing this all involve just using another name. Common ways include 
"name_", "n" (trivial short term variable) or a misspelling. For example, 
saying "klass" instead of "class".



5) __name__ is meant to be used only by the creators of Python for
their special built-in methods, such as __init__, __new__, etc.


Yes, but in the sense that they have predefined meanings. If you are 
implementing a mapping (a class that has methods and access like a dictionary), 
you will need to define methods using these names to implement the API.


So don't make up your own!


Are my understandings above correct or flawed?


Yes.


For (3), it seems to me that one would normally be able to use the
simpler _name construction from (2).  What would be a best-practice
example of when name mangling *should* be used?


Well, people rarely use _name as a function parameter, unless it is a 
private/secret parameter for special internal use.


So I would write this:

 def check_type(self, type_):
   return self.type == type_

instead of using "_type". because "type_" here is a _public_ parameter for 
people to use. Using "_type" would mislead.



Likewise, it seems that normally (4) should never be needed, though I
have a feeling that I have seen something in tkinter recently that
suggests some exceptions, but I cannot (yet) bring it to mind.


(4) is never required, but is often convenient.


And for (5), surely I should never violate this one?  It seems that in
some future edition of Python they might add any particular __name__
that I might try to use presently in their future version of Python
(however miniscule that possibility might actually be).


Yes: don't make up new __name__s. But you will _implement_ some __name__s at 
some point.


Cheers,
Cameron Simpson 

On the one hand I knew that programs could have a compelling and deep logical
beauty, on the other hand I was forced to admit that most programs are
presented in a way fit for mechanical execution, but even if of any beauty at
all, totally unfit for human appreciation.  - Edsger W. Dijkstra
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Mailbox

2015-07-29 Thread Cameron Simpson

On 29Jul2015 21:55, ltc.hots...@gmail.com  wrote:

I have a second and unrelated question:

I tried to work backward  to see if there is a logic error associated with a 
variable is being skipped over:

#top of code, initialize variable
output_list = ["default"]


Curious: why not just make this an empty list: []

[...snip...]

count = 0
fname = raw_input("Enter file name: ")
if len(fname) < 1 : fname = "mbox-short.txt"
for line in fname:
   line = line.strip()
   if not line.startswith('From '): continue
   line = line.split()
count = count + 1
print len(line)
fh = open(fname)
print "There were", count, "lines in the file with From as the first word"

[...snip...]

My first observation would be that "count = count + 1" is not inside the loop.  
That means that it fires just once, _after_ the loop. So it will always be 1.


Also, what is the purpose of this line:

 line = line.split()

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


Re: [Tutor] String Attribute

2015-08-01 Thread Cameron Simpson

On 31Jul2015 17:21, Ltc Hotspot  wrote:

Mark:
Is this any better, message sent from GMail?
Regards,
Hal


Looks better to me.

Cheers,
Cameron Simpson 


On Fri, Jul 31, 2015 at 5:02 PM, Mark Lawrence 
wrote:


On 31/07/2015 19:57, ltc.hots...@gmail.com wrote:

I believe that this is the third time that you've been asked to do
something about the amount of whitespace that you're sending to this list.

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

Mark Lawrence

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


Re: [Tutor] scratching my head

2015-08-02 Thread Cameron Simpson

On 02Aug2015 23:01, ALAN GAULD  wrote:

On 02/08/15 22:44, Clayton Kirkwood wrote:

for dir_path, directories, files in os.walk(main_dir):
for file in files:
#print( " file = ", file)
#   if( ("(\.jpg|\.png|\.avi|\.mp4)$") not in file.lower() ):


Python sees that as a single string. That string is not in your filename.


#if(  (".jpg" or ".png" or ".avi" or ".mp4" )  not in file.lower()

[...]

But you could use a loop:

found = False
for s in (".jpg",".png",".avi",".mp4"):
   found = test or (s in file.lower())
if not found: ...


if(  ".jpg" not in file.lower() and
 ".png" not in file.lower() and
 ".avi" not in file.lower() and
 ".mp4" not in file.lower() ):


Whether that's any better than your combined test is a moot point.


Alan has commented extensively on the logic/implementation errors. I have a 
suggestion.


Personally I'd be reaching for os.path.splitext. Untested example below:

 from os.path import splitext
 
 for dir_path, directories, files in os.walk(main_dir):
   for file in files:
 prefix, ext = splitext(file)
 if ext and ext[1:].lower() in ('jpg', 'png', 'avi', 'mp4'):
   

which I think is much easier to read.

BTW, I'd be using the variable names "filename" and "filenames" instead of 
"file" and "files": in python 2 "file" is a builtin function (though long 
deprecated by "open()") and in any case I'd (personally) expect such a name to 
be an _open_ file. As opposed to "filename", which is clearer.


Cheers,
Cameron Simpson 

Rudin's Law:
 If there is a wrong way to do something, most people will do it every time.
Rudin's Second Law:
 In a crisis that forces a choice to be made among alternative courses of
 action, people tend to choose the worst possible  course.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] scratching my head

2015-08-02 Thread Cameron Simpson

On 02Aug2015 16:15, Clayton Kirkwood  wrote:

Behalf Of Cameron Simpson
Sent: Sunday, August 02, 2015 3:35 PM

[...]

Personally I'd be reaching for os.path.splitext. Untested example below:

  from os.path import splitext
  
  for dir_path, directories, files in os.walk(main_dir):
for file in files:
  prefix, ext = splitext(file)
  if ext and ext[1:].lower() in ('jpg', 'png', 'avi', 'mp4'):


which I think is much easier to read.

BTW, I'd be using the variable names "filename" and "filenames" instead of
"file" and "files": in python 2 "file" is a builtin function (though long
deprecated by "open()") and in any case I'd (personally) expect such a

name

to be an _open_ file. As opposed to "filename", which is clearer.


Thanks, that should also help a lot. Now time to look at splitext, and the
ext and ext[1:.


The "[1:]" is because "ext" will include the dot.


I appreciate your comments also about the variable names.
Any comments on the problems lower in the file?


Maybe you'd better reraise these problems again explicitly.

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


Re: [Tutor] scratching my head

2015-08-03 Thread Cameron Simpson

On 03Aug2015 08:12, Laura Creighton  wrote:

I think people are giving you sub-optimal advice.

Python has a module in the standard library for doing exactly what
you want to do -- match files with certain extensions.

See: https://docs.python.org/2/library/fnmatch.html

It's unix style file matching, but I am fairly certain this works
on windows also.  I don't have a windows machine to test and make sure.


That depends. This is the tutor list; we're helping Clayton debug his code as 
an aid to learning. While it's good to know about the facilities in the 
standard library, pointing him directly at fnmatch (which I'd entirely 
forgotten) is the "give a man a fish" approach to help; a magic black box to do 
the job for him.


Besides, I'm not sure fnmatch is much better for his task than the more direct 
methods being discussed.


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


Re: [Tutor] scratching my head - still

2015-08-04 Thread Cameron Simpson

On 05Aug2015 12:46, Steven D'Aprano  wrote:

On Tue, Aug 04, 2015 at 05:52:15PM -0700, Clayton Kirkwood wrote:

As seen below (closely), some filenames are not being removed while others
are, such as in the first stanza, some pdfs are removed, some aren't. In the
second stanza, Thumbs.db makes it through, but was caught in the first
stanza. (Thanks for those who have proffered solutions to date!)
I see no logic in the results. What am I missing???


You are modifying the list of files while iterating over it, which plays
all sorts of hell with the process. Watch this:

[... detailed explaination ...]

The lesson here is that you should never modify a list while iterating
over it. Instead, make a copy, and modify the copy.


What Steven said. Yes indeed.

Untested example suggestion:

 all_filenames = set(filenames)
 for filename in filenames:
   if .. test here ...:
 all_filenames.remove(filename)
 print(all_filenames)

You could use a list instead of a set and for small numbers of files be fine.  
With large numbers of files a set is far faster to remove things from.


Cheers,
Cameron Simpson 

In the desert, you can remember your name,
'cause there ain't no one for to give you no pain.  - America
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Fraction Class HELP ME PLEASE!

2015-08-06 Thread Cameron Simpson

On 06Aug2015 16:55, Quiles, Stephanie  wrote:
I need to do the following assignment. I need to know how do i hard code an 
example for each of the operators I am implementing? What i have so far is 
below? He said he does not care if we plug in some numbers or if we have user 
input numbers, however I am unsure of how to write a program that tests each 
operator? Or can i write one that tests all of them? I don’t know where to 
start with this. Please help!


For someone who doesn't know where to start, you seem to have a lot of decent 
looking code. Is the code below all yours? If so, a good start.


Also, please try to preserve the indentation when pasting in code; indentation 
is critical in Python as you know and incorrect indentation, when not an 
outright syntax error, can be a source of bugs. I'll presume your code was 
originally indented correctly.


Note that in this list we _do_ like code to be pasted inline where it can be 
seen directly and commented on like any other part of the message text. We're 
not big on attachments or links to external things (other than doco citations 
like your reference to the operators Python page).



You may implement as many of these operators as you like (such as isub,
itruediv, etc.) You MUST indicate in your header information which operators
you are implementing, and you MUST hard code an example for each.


"Header information" is usually an opening comment. So perhaps start the 
program with text like this:


 # Here is a Fraction class implementing variaous operators. It currently
 # supports:
 #
 # + (addition)
 # - (subtraction)
 # * (multiplication)
 # / (true division)
 #

and so forth.

Regarding examples and tests, one workable approach to to make your program 
work as a "main program". The idea is that is invoked as a main program it will 
run the examples or tests.


As your code sits now it could be used as a module - someone could place it 
into python's library tree and import it, and use your Fraction class.  
However, you can of course run it directly at the command prompt, eg:


 % python your-fraction-file.py

When you do that, the code is still imported as a module but with the special 
name '__main__'. So what a lot of python modules do is have a "main" function 
which is to be fired only in the command line circumstance, such as:


 def main():
   F1 = Fraction(1, 2) # 1/2
   F2 = Fraction(2, 3) # 2/3
   print("F1 =", F1)
   print("F2 =", F2)
   print("F1 + F2 =", F1 + F2)
   print("F1 - F2 =", F1 - F2)
   print("F1 * F2 =", F1 * F2)

In order to make your program work as both an importable module which defines 
the Fraction class but does not run the main function and also as a main 
program which defines the class and then runs the main function you put this 
piece of boilerplate code on the very bottom of the program:


 if __name__ == '__main__':
   main()

which checks if you're invoking it directly from the command line. If so, run 
the main function.


Hopefully that gives you an idea about hardwiring examples also.

Regarding tests, you might write a simple function like this:

 def check(label, computed, expected):
   ok = computed == expected
   if ok:
 print(label, 'OK', computed, '==', expected)
   else:
 print(label, 'BAD', computed, '!=', expected)
   return ok

Then you might consider modifying your main program to run tests instead of 
bare examples, replacing:


 print("F1 + F2 =", F1 + F2)

with:

 check("F1 + F2", F1 + F2, Fraction(7, 6))

Because check() returns whther the check was ok, you might even count the 
number of failures for some kind of report:


 fail_count = 0
 ...
 if not check("F1 + F2", F1 + F2, Fraction(7, 6)):
   fail_count += 1
 ... more checks ...
 print(fail_count, "failures")

and so forth.

This also gets you test code so that you can test your own program for 
correctness before submitting your assignment.


Feel free to return to this list with updated code and new questions.

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


Re: [Tutor] Fraction Class HELP ME PLEASE!

2015-08-06 Thread Cameron Simpson
method.

All the __name__ methods and attributes in Python are considered part of the 
language, and typically and implicitly called to implement things like 
operators (i.e. F1+F2 calls F1.__ad__(F2)).


You should not make up __name__ methods: they are reserved for the language.  
There are at least two downsides/risks here: first that you think this will be 
used, when it will not - the code will never be run and you will wonder why 
your call does not behave as you thought it should. The second is that some 
furture update to the language will define that name and it will not mean what 
you meant when you used it. Now your code _will_ run, but not do what a user 
expects!


BTW, the jargon for the __name__ names is "dunder": .__add__ is a "dunder 
method"; derived from "double underscore", which I hope you'd agree is a 
cumbersome term.



def main():
   F1 = Fraction(1,2)
   F2 = Fraction(2,3)
   print("F1 = ", F1)
   print("F2 = ", F2)


print() adds a space between the comma separate items, you don't need to 
include one inside the quotes.



   print("Add Fractions: F1 + F2=", Fraction.__add__(F1, F2))


Any reason you've not fired this implicitly? Like this:

   print("Add Fractions: F1 + F2=", F1 + F2)

Actually, you can make a case for doing both in your main program to show that 
they do the same thing.



   print("Subtract Fractions: F1 - F2=", Fraction.__sub__(F1, F2))
   print("Multiply Fractions: F1 * F2=", Fraction.__mul__(F1, F2))
   print("True Division with Fractions: F1 / F2=", Fraction.__truediv__(F1, F2))
   print("Exponentiation with Fractions: F1 // F2=", Fraction.__pow__(F1, F2))


Shouldn't this be "**"?


   print("Is F1 Greater than F2?:", Fraction.__gt__(F1, F2))
   print("Is F1 less than F2?:", Fraction.__lt__(F1, F2))
   print("Is F1 Equal to F2?:", Fraction.__eq__(F1, F2))
   print("Is F1 different than F2?:", Fraction.__ne__(F1, F2))
   print ("Is F1 same as F2?:", Fraction.__is__(F1, F2))


Here you want to avoid this. Firstly, Python has an "is" operator, and it does 
not have a dunder method. Secondly, in what way does your __is__ differe from 
__eq__?



   print("Is:", Fraction.__iadd__(F1, F2))

if __name__ == '__main__':
   main()


Otherwise this is all looking promising. Does it run correctly for you?

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


Re: [Tutor] Fraction Class HELP ME PLEASE!

2015-08-07 Thread Cameron Simpson
 ...
   
   '''
   F1 = ...
   ...

When you put a string inside a function or class, immediately under the "def" 
or "class" line, that string is called a docstring as it is intended as 
documentation for that function or class. The Python language actually collects 
it and saves it as the .__doc__ attribute of the function or class, and you can 
get it back later.


In the interactive Python interpreter (which you get when you just run the 
command "python"), you can call the help() function on something and have the 
docstring recited back at you. So at the python prompt you can type:


   help(main)

and be told about it. By putting docstrings on your Fraction class and also on 
each of its methods you make that information available via help() later.


Otherwise, good luck.

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


Re: [Tutor] Pep 8, about indentation

2015-08-07 Thread Cameron Simpson

On 06Aug2015 11:03, ALAN GAULD  wrote:

On 06/08/15 04:40, Steven D'Aprano wrote:

Um, the oldest standard for TABs is *eight* spaces, not 3 or 4,


Yes, but that comes from the days of mechanical typewriters not any 
study of code comprehension.

[...snip...]

I beg to differ a little. Old _teletypes_ and terminals used 8 character TAB 
spacing.


Mechanical typewriters had slidable lugs to position to totally arbitrary spots 
with a lever motion triggered by a key labelled "Tab", which was very useful 
for typing tabular information, hence the name. There's no "8" in there!


My personal habit is to have my terminals, editors such as vi, pagers like less 
etc interpret the TAB byte code to mean align to the next 8 column position.  
That is the common default meaning.


However, when _editing_ I tell vi that when I press TAB it is to insert enough 
SPACE characters to get to the next 4 column position. In this way I have the 
convenience of a TAB key to advance rapidly when needed, and my code comes out 
composed entirely with spaces so that my spacing in not mispresented to others.


In short, I use the TAB _key_ to aid typing. But I avoid embedded TAB 
characters into my text, because they are subject to arbitrary interpreation by 
others.


Cheers,
Cameron Simpson 

I had a *bad* day. I had to subvert my principles and kowtow to an idiot.
Television makes these daily sacrifices possible. It deadens the inner core
of my being.- Martin Donovan, _Trust_
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Pep 8, about indentation

2015-08-07 Thread Cameron Simpson

On 07Aug2015 12:19, Alex Kleider  wrote:

On Aug 7, 2015 1:18 AM, Cameron Simpson  wrote:

However, when _editing_ I tell vi that when I press TAB it is to insert enough
SPACE characters to get to the next 4 column position.


How do you do that?
I've got vim set up so a CTRL-T while in insert mode does that (and CTRL-D does 
the opposite) but don't know how to make use of the tab key.


^T and ^D have done that since time immemorial in vi, no special setup 
required.  I pretty much never use ^T but I do use ^D to back out an indent 
level.


These are my settings relevant to tabs and indenting:

 set autoindent
 set expandtab
 set shiftwidth=2
 set tabstop=4

In order:

 autoindent: start the next line's text on the same indent as this one

 expandtab: write spaces instead of a TAB character

 shiftwidth: how far the < and > shift-text operations move

 tabstop: the multiple used to tabstops - every 4 columns for me

Happy to post my other settings should anyone care.

Cheers,
Cameron Simpson 

Swiftkey, [...] teaches one the lamentable lesson that most
English speakers start most sentences, phrases and sub-clauses
with 'I'. One does not use the word often oneself and it therefore
strikes one as a little unfair that one's texts and emails so often
end up littered with implications of egocentricity. - Stephen Fry
http://www.stephenfry.com/2012/04/03/four-and-half-years-on/9/
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] [off-topic] vi/vim editor settings (was: Pep 8, about indentation)

2015-08-08 Thread Cameron Simpson

On 07Aug2015 21:50, Alex Kleider  wrote:

On 2015-08-07 20:56, Cameron Simpson wrote:

autoindent: start the next line's text on the same indent as this one
expandtab: write spaces instead of a TAB character
shiftwidth: how far the < and > shift-text operations move
tabstop: the multiple used to tabstops - every 4 columns for me


Thanks!
Here is what I've got in my ~/.vimrc file:
set autoindent
set shiftwidth=4
set expandtab
set textwidth=72
set scrolljump=2
set scrolloff=2

I'll add
set tabstop=4


Happy to post my other settings should anyone care.


... and yes, I for one certainly do "care."
I'd very much like to see your other settings.


Ok. Here are my other vi settings which I think useful (it seems I have plenty 
which aren't).  Vim specific settings follow after that.


 set autowrite
   Automatically save the file when switching to another. Saves tedious :w and 
   also worrying about whether I should, not to mention all those "file 
   modified" warnings.


 set ignorecase
   Saves fiddling with shift keys.

 set nowrapscan
   Searches do not resume from the top of the file if nothing found below the 
   current position. I used to have this on, but now consider this more 
   informative.


 set optimize
 set redraw
   I forget, probably dates from editing over a 300baud modem.

 set report=1
   Threshold for reporting changed lines.

 set showmatch
   Highlight matching open/close bracket. Handy for nested stuff. And C code.

 set noterse
   Longer warnings and other messages.

 set writeany
   Trust me, I'm a doctor. (I'm not.)

 map! \c c...@zip.com.au
 map! \C Cameron Simpson <\c>
   Insert mode macros to recite my email, short and long.
   I've got matching ones for my partner's email, very often CCed or 
   attributed.


 map!  :stop
a
   Suspend the editor, just as with ^Z in the shell.

 map!  a
   Redraw the screen then resume inserting.

 map!  I
 map!  i
 map!  A
 map!  lli
   Emacs mode motion: start of line, left, end of line, right, resume insert 
   mode.


 map # :n #
z.
   Edit the previous file. Very very handy.
 map g Gz.
   Go to line and position it in the centre of the screen.

 map q ZZ
   Save and quit.

 map t :ta
   Commence "go to tag".

 map Y y$
   Yank to end of line.

 map  1G}-:.r!exec /dev/tty; readline -B 'Attach: '
IAttach: 
   My uber-convenient "attach file" macro. In mutt (my mailer) an "Attach:" 
   header gets turned into a real attachment. So this macro runs a bit of 
   shell to issue the prompt "Attach: " and accept the filename you typ, _with 
   filename completion!_. And inserts that as an Attach: header. When I leave 
   the editor, mutt adds the file to the attachments for this message.


 set bg=dark
   My terminals have a dark background.

 syntax reset
 syntax on
   I like my syntax highlighting.

 set wildmenu wildmode=list:longest
   Make vim's filename completion act more like zsh's, which I find far more 
   ergonomic than bash's. Essentially: complete as much as you can and 
   _immediately_ show me the remainder without an extra TAB keystroke.


 set ignorecase
 set smartcase
   Case insensitive searches unless there is an uppercase letter in the search 
   string.


 set incsearch
   Show the first match in the file as you type the search regexp.

 set backupcopy=yes
   I prefer to overwrite the original file instead of making a new one and 
   cutting it in with rename(). The former edits the file I intended to edit.  
   The latter breaks hardlinks and has to do silly hoop jumping with symlinks.  
   Gah! Do what I say, not what you think I want!


 set noswapfile
 set swapsync=
   Vim's fetish for .swp files drives me mad, especially if one loses remote 
   sessions regularly or terminal emulators die or one coworks with others in 
   the same directories or simply closes one's laptop one a whim or moves 
   around. I save files very regularly anyway, so I pretty much never lose a 
   significant edit.


 set nofsync
   Trust the filesystem, the filesystem is your friend. Once I've handed the 
   file to the OS (i.e. written it) I do not want to shout at the OS: not get 
   that onto the disc, now! Especially when fsync() means sync(0 on many 
   filesystems i.e. write _all_ pending disc I/O before returning, often with 
   a huge and visible hit to the system behaviour.


 set scrolloff=2
   Like you, keep some screen context.

 set t_Co=256
   Yes, my terminal have lots of colours.

 set ttyfast
   Better display instead of lower bandwidth display.

 set spellfile=~/rc/vim/spellfile.utf-8.add
   Additional words to augument the spelling table.

 set spelllang=en_gb
   British English.

 set nospell
   Spell checking off by default.

 let g:loaded_netrw = 1
   I forget. Anyone?

 map  :set hlsearch! nospell! 
   F3 turns off highlighting.

and when co

Re: [Tutor] Help

2015-08-10 Thread Cameron Simpson

On 09Aug2015 19:10, Shannon Callahan  wrote:

Sorry for my lack of clear explanation. Yes, I am having problem to install
python into my mac laptop.

-I am trying to install python into my mac laptop


Macs normally ship with Python installed already, version 2.7.

If you need a specific version, for example Python 3, you can fetch installers 
for the current versions here:


 3.4.3:  https://www.python.org/downloads/release/python-343/
 2.7.10: https://www.python.org/downloads/release/python-2710/


-I am trying to learn how to execute the possible finished code


Generally you execute python code from the command line by handing it the 
filename or module name, eg:


 python filename.py
 python -m module.name


-I am trying to create a code so I can transfer it into SD card so I can
put it into raspberry pi.


You will need a text editor. There are any number of things.

Regarding the transfer, your raspberry should have an ethernet socket. You'll 
need to plug it into your network. Then you can scp the files to the raspberry 
without mucking around with SD cards.



-I am trying to have it able to hear like three specific commands such as
"hey, hello, sir".
-I am trying to execute the code that able to make a connect between
raspberry pi to breadboard to ringer component.


I cannot help you with these. What degree of programming knowledge or 
experience do you have?



To answer your questions;
- what you are trying to do; mimic sound detector from specific trigger
words
- what you have done so far; Struggle to download python and create code


Download links above. You will have to pick an editor. The Mac offers the 
textedit app and the usual command line based editors. Make sure you're using a 
text editor, which makes plain text files. Not a word processor.



- what result you hope to get; able to make code to execute detect trigger
words that cause a ring.
- the actual result you have got.; none.


Start by making sure you have a working Python. Write an utterly trivial Python 
program and run it. For example, make a file "foo.py" containing:


 print("Hello world!")

and run it:

 python foo.py

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


Re: [Tutor] Help

2015-08-10 Thread Cameron Simpson

On 10Aug2015 18:07, ALAN GAULD  wrote:

PS.
What is SDSU?


Google told me San Diego State University.

Cheers,
Cameron Simpson 

To be positive: To be mistaken at the top of one's voice.
Ambrose Bierce (1842-1914), U.S. author. The Devil's Dictionary (1881-1906).
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Help

2015-08-10 Thread Cameron Simpson

On 10Aug2015 11:40, Alex Kleider  wrote:

On 2015-08-10 11:13, Emile van Sebille wrote:

On 8/10/2015 10:07 AM, Alan Gauld wrote:


PS.
What is SDSU?


San Diego State University I'd guess.

Emile


South Dakota State is the other possibility.


They seem to addreviate to sdstate. At least as a domain name, while San Diego 
State University actually uses sdsu. Maybe the race _is_ always to the swift.


Cheers,
Cameron Simpson 

Airplanes are interesting toys but of no military value.
 --Marechal Ferdinand Foch, Professor of Strategy, Ecole
   Superieure de  Guerre.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] a few question about my evolving program

2015-08-11 Thread Cameron Simpson
11-05-28 17.13.38.jpg', '2011-05-28 17.26.37.jpg', '2012-02-02
 20.16.46.jpg', '218.JPG', 'honda accident 001.jpg', 'honda accident
 002.jpg', 'honda accident 003.jpg', 'honda accident 004.jpg', 'honda
 accident 005.jpg', 'honda accident 006.jpg', 'honda accident 007.jpg',
 'Image (1).jpg', 'Image.jpg', 'IMG.jpg', 'IMG3.jpg', 'IMG00040.jpg',
 'IMG00058.jpg', 'IMG_0003.jpg', 'IMG_0004.jpg', 'IMG_0005.jpg',
 'IMG_0007.jpg', 'IMG_0008.jpg', 'IMG_0009.jpg', 'IMG_0010.jpg', 'Mak diploma
 handshake.jpg', 'New Picture.bmp', 'temp 121.jpg', 'temp 122.jpg', 'temp
 220.jpg', 'temp 320.jpg', 'temp 321.jpg', 'temp 322.jpg', 'temp 323.jpg',
 'temp 324.jpg', 'temp 325.jpg', 'temp 326.jpg', 'temp 327.jpg', 'temp
 328.jpg', 'temp 329.jpg', 'temp 330.jpg', 'temp 331.jpg', 'temp 332.jpg',
 'temp 333.jpg', 'temp 334.jpg', 'temp 335.jpg', 'temp 336.jpg', 'temp
 337.jpg', 'temp 338.jpg', 'temp 339.jpg', 'temp 340.jpg', 'temp 341.jpg',
 'temp 342.jpg', 'temp 343.jpg']

 if current_filename in target_directory_file_list:
   print("IN! (unexpected!)")
 else:
   print("NOT IN")

If the small program works correctly, that may point you to the issue in your 
larger program.


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


Re: [Tutor] a few question about my evolving program

2015-08-12 Thread Cameron Simpson
n of what correct results should be. For that, we 
always want the original code of that smallest example rather than an anecdote.  
We want to be sure that what we're inspecting is what you're inspecting.


The other thing we often want is the original problem (which you've described); 
often people come with their specific solution to a larger problem. Which is 
fine as long far as it goes, but sometimes the larger problem has a better, 
less cumbersome solution.


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


Re: [Tutor] Python help

2015-08-13 Thread Cameron Simpson

On 13Aug2015 10:34, ALAN GAULD  wrote:

On 13/08/15 02:01, IDN3 wrote:

[...snip...]

Condition: If c is less than 5, then the loop will continue; else, it will
end.



3.   *Problem 2:*Print a string variable that states the number of loops
required to meet the condition for Problem 1.


This is a simple bit of math.
You don't need to run the loop to figure out the answer,
just write an equation.


Maybe so, but for an arbitrarily weird condition running the loop may be the 
way to go. Therefore I would imagine he is being asked to print how many times 
that loop ran. So he should just print that value after the loop finishes (i.e 
outside the loop).



My attempt below.  I used a while loop even though the question is saying
IF/THEN/ELSE.


You obviously did not send the whole question.
I don't see any mention of if/then/else?


Actually, the question's "Condition:" section is written in exactly those 
terms.



To my knowledge loops in Python have to be while/for.  Also,
it seems like the question is missing some direction, but I could be
wrong.


The way I would read your "Cndition:" requirement is that it is describing what 
kind of decision must be made every time the loop commences. It is not telling 
you to use Pythons "if" statement. So just putting the correct condition at the 
top of the "while" loop is what you want.


Cheers,
Cameron Simpson 

If you lie to the compiler, it will get its revenge.- Henry Spencer
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Searching through files for values

2015-08-13 Thread Cameron Simpson

On 13Aug2015 16:48, Jason Brown  wrote:

I'm trying to search for list values in a set of files.  The goal is to
generate a list of lists that can later be sorted.  I can only get a match
on the first value in the list:

contents of value_file:
value1
value2
value3
...

The desired output is:

file1 value1
file1 value2
file2 value3
file3 value1
...

Bit it's only matching on the first item in vals, so the result is:

file1 value1
file3 value1

The subsequent values are not searched.


Rhat is because the subsequent values are never loaded:


filenames = [list populated with filenames in a dir tree]
vals = []
value_file = open(vars)
for i in value_file:
   vals.append(i.strip())
   value_file.close()


You close value_file inside the loop i.e. immediately after the first value.  
Because the file is closed, the loop iteration stops.  You need to close it

outside the loop (after all the values have been loaded):

   value_file = open(vars)
   for i in value_file:
   vals.append(i.strip())
   value_file.close()

It is worth noting that a better way to write this is:

   with open(vars) as value_file:
   for i in value_file:
   vals.append(i.strip())

Notice that there is no .close(). The "with" construct is the pynthon syntax to 
use a context manager, and "open(vars)" returns an open file, which is also a 
context manager. A context manager has enter and exit actions which fire 
unconditionally at the start and end of the "with", even if the with is exited 
with an exception or a control like "return" or "break".


The benefit of this is after the "with", the file will _always" get closed. It 
is also shorter and easier to read.



for file_list in filenames:
   with open(file_list) as files:
for items in vals:
for line in files:
if items in line:
print file_list, line


I would remark that "file_list" is not a great variable name. Many people would 
read it as implying that its value is a list. Personally I would have just 
called it "filename", the singular of your "filenames".


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


Re: [Tutor] SQLite, Python and SQL injection attacks

2015-08-14 Thread Cameron Simpson

On 14Aug2015 13:40, boB Stepp  wrote:

I was just looking at the sqlite3 docs at
https://docs.python.org/3/library/sqlite3.html?highlight=sqlite#module-sqlite3
and found the following cheery news:

"Usually your SQL operations will need to use values from Python
variables. You shouldn’t assemble your query using Python’s string
operations because doing so is insecure; it makes your program
vulnerable to an SQL injection attack ..."

There followed this recommendation:

"Instead, use the DB-API’s parameter substitution. Put ? as a
placeholder wherever you want to use a value, and then provide a tuple
of values as the second argument to the cursor’s execute() method..."

I have to be honest -- I would have fallen into this potential trap if
I had not read this.  It is not clear to me yet how the recommendation
avoids this issue.  Does the placeholder enforce some sort of type
checking so that arbitrary SQL strings will be rejected?


Well, better to say that it transcribes the values correctly, possibly with 
some type checking. You run the same risk constructing shell command lines too, 
which is why "shell=True" is generally discourages with subprocess.Popen.


So if you have:

 SELECT FROM tablename WHERE columnvalue = ?

and you have it a python string like "foo;bah", the SQL API will take care of 
quoting the string so that the ";" is inside the quotes. Likewise if the string 
contains SQL end of string markers (quotes). And if the value cannot be 
transcribed the API should raise an exception.


IN this way you know that the structure of the query has been preserved 
correctly. _And_ you do not need to worry about quoting values (or otherwise 
transcribing them) correctly; that is a solved and debugged problem.


You code is simpler and robust.

Cheers,
Cameron Simpson 

The Fano Factor, where theory meets reality.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] try and file existence

2015-08-14 Thread Cameron Simpson

On 14Aug2015 18:28, Clayton Kirkwood  wrote:

try:
   fp = open( user_preferences )
except( PermissionError ):
else:
   with open(user_preferences ) as f:

I originally only had the bottom open statement. Ran but file didn't exist,
and my run failed with file doesn't exist. I figured I'd check to see if the
file existed. This is one of those situations where a search of
documentation for fd_exist (which I thought I'd seen once), or exist turns
up either nothing or nothing relevant. I finally found that the try: clause
with the open statement might help and I copied the snippet to my code. I am
getting an indentation error: expected an indent block. What is wrong, and
what is the best way to find out if a file exists?


In purely syntactic terms you need some code in the suite under the "except" 
clause, and you don't want the brackets:


   try:
   fp = open( user_preferences )
   except PermissionError as e:
   print("open(%r) fails: %s" % (user_preferences, e))
   else:
   with open(user_preferences ) as f:

In logical terms, the "with" is not wanted - you're opening the file again.  
Leaving aside the logical issue there, this structure (test then operate) is 
also racy: suppose the file has its attributes changed or is removed between 
the first open and the second.


Next: you're catching PermissionError. That normally means that you have not 
got rights for opening the file; you will get a different exception if the file 
does not exist. You're being too precise if you want both.


But maybe you don't. You need to decide 

Finally, the usual Python pattern is not to catch exceptions _at all_ unless 
you have a deliberate polciy plan for what to do. Normally you would have some 
function looking like this:


 def read_prefs(filename):
   prefs = {}
   with open(filename) as fp:
 ... read preferences, save in prefs dict for example ...
   return prefs

If the file is missing or you have no permissions, that will raise an 
exception. Let it!


Then in an outer layer of your program you might catch the exception, where you 
can make a policy decision because you have a wider view of what is going on:


 try:
   prefs = read_prefs(prefs_filename)
 except FileNotFoundError as e:
   print("warning: file not found: %r: %s" % (prefs_filename, e))
   # proceed with empty preferences, not an error
   prefs = {}

This bit of code catches _only_ FileNotFoundError on the (presumed) policy that 
a missing preferences file is ok - your program will proceed with default 
behaviours - but any _other_ kind of exception is not expected - let your 
program abort! Do not proceed!


Cheers,
Cameron Simpson 

Capitalism is the extraordinary belief that the nastiest of men, for the
nastiest of reasons, will somehow work for the benefit of us all.
- John Maynard Keynes
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] try and file existence

2015-08-15 Thread Cameron Simpson

On 15Aug2015 15:20, Clayton Kirkwood  wrote:

Behalf Of Laura Creighton

[..]

To: boB Stepp 
In a message of Sat, 15 Aug 2015 14:24:21 -0500, boB Stepp writes:
>I understand your points, but wonder then what is the intended use for
>os.path.exists()?  That is, in what types of circumstances would it be
>both appropriate and safe to use?

If you want to locate dangling symlinks,  os.path.exists will return False, so
the symlink is there, but the file it pointed to is long gone.


Can't you do that with os.path.open() and get a value in os.path.status? (I
think that is the thing to call)


Open does more that os.stat (which is what os.path.exists uses underneath).

There are plenty of times you will want to know a file exists but not have 
permission to open it. Also, open can have side effects if the target file is a 
device or a socket/pipe.


Always use the smallest thing you can to achieve an effect: stat is smaller 
than open.


Cheers,
Cameron Simpson 

Q: How many user support people does it take to change a light bulb?
A: We have an exact copy of the light bulb here and it seems to be
  working fine.  Can you tell me what kind of system you have?
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] variable naming conventions

2015-08-15 Thread Cameron Simpson

On 15Aug2015 18:24, D Wyatt  wrote:

It seems every book I read these days uses camel case for variable names in
Python.  I was once told that using underscores is preferred.  Is there a
preference in the Python community or does it really matter?  I'd like to
instill good habits while I'm learning.


PEP 8 is lowercase with underscores for normal variables. Class names tend to 
be CamelCase. I try to follow this. One advantage in staying with this is that 
you share this convention with the stdlib and with a lot of other Python code, 
which make it easier for you to read because it aligns with your own habits.  
Ideally, anyway.


If you're not invested in another style, and not working in someone else's 
codebase with its own conventions, try PEP 8.


Cheers,
Cameron Simpson 

Oh, what tangled webs we weave,
   when first we practice to deceive.
   And when we've practiced for awhile,
   How we do improve our style!- Dorothy Parker
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Using lambda

2015-08-24 Thread Cameron Simpson

On 24Aug2015 12:08, rakesh sharma  wrote:

I am beginner in pythonI see the use of lambda has been for really
simple ones as in the numerous examples over the net.Why cant we
use lambda in another one like

g = lambda x: (lambda y: y + 1) + 1

when I am able to do that in two lines

>>> h = lambda x: x + 1
>>> h(12)
13
>>> y = lambda x: h(x) + 1
>>> y(1)
3


Hi,

First, please include more whitespace in your posts to make them easier to 
read. If you are includining line breaks etc, I think something is eating them.


Regarding your question, you can do what you ask. You suggestion was:

 g = lambda x: (lambda y: y + 1) + 1

The thing you've missed is that a lambda is a function; you need to call it.  
Your example only defines a lambda but doesn't call it. Try this:


 g = lambda x: (lambda y: y + 1)(x) + 1

which passes x through to the inner lambda:

 >>> g(12)
 14

So yes, you can do it. But as you can see it doesn't make for very readable 
code. Lambdas are ok for small expressions. When things get more complex it is 
worth breaking them up.


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


Re: [Tutor] Query regarding loop problem

2015-08-29 Thread Cameron Simpson

On 29Aug2015 22:37, Martin Mwaka  wrote:

I would be grateful for some help please.  I have recently started learning
python and I am attemping to write a programme where a user enters a number
between 1 and 5, and the computer generates random numbers until an
equivalent number is achieved.  The code (see below) runs, but the else
part of the loop does not run when the computer generates an equivalent
number. I have tried to resolve this a number of ways and have run the code
under a debugger, but cannot work out why the else part is not running.  I
would be grateful for your help / guidance with this.

[...]

import random
computerNumber = 0
myNumber = input("Input a number between 1 and 5: ")
print ("Your chosen number is: ", myNumber)
computerNumber = input("Press enter to prompt the computer to enter a
number: ")

while computerNumber != 0:
   if myNumber != computerNumber:
   computerNumber = random.randint(1,5)
   print ("Your chosen number is ", myNumber,": Computer number is: ",
computerNumber)
   print ("Numbers do not match.")
   prompt = input("Press enter to prompt the computer to enter a
number: ")
   else:
   print ("MyNumber is ", str(myNumber),": Computer number is: ",
str(computerNumber))
   print ("We have a match.")


Looks like you assign the new number to "prompt" instead of to "myNumber".

Cheers,
Cameron Simpson 

In theory, there is no difference between theory and practice.
In practice, there is. - Yogi Berra
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to parse a mailing list thread?

2015-09-19 Thread Cameron Simpson

On 19Sep2015 21:46, chandan kumar  wrote:

I am looking for a python module which i can use to parse mailing thread
and extract some information from it.

Any pointer regarding that would be helpful.


You should describe where the email messages are stored. I'll presume you have 
obtained the messages.


Construct a Message object from each message text. See the email.message 
module:


 https://docs.python.org/3/library/email.message.html#module-email.message

Every message has a Message-ID: header which uniquely identifies it. Replies to 
that message have that id in the In_Reply-To: header. (If you're parsing usenet 
newsgroup messages, you want the References: header - personally I consult 
both.)


The complete specification of an email message is here:

 http://tools.ietf.org/html/rfc2822

and the email.message module (and the other email.* modules) makes most of it 
easily available. If you need to parse email addresses import the 
"getaddresses" function from the "email.utils" module.


Constuct a graph connecting messages with the replies. You're done!

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


Re: [Tutor] Exception Handling

2015-10-02 Thread Cameron Simpson

On 03Oct2015 00:51, ALAN GAULD  wrote:

On 02/10/15 23:57, Nym City via Tutor wrote:

socket.gaierror: [Errno 11004] getaddrinfo failed

...

for name in ListOfHostNames:
try:
ResolveHostname = socket.gethostbyname(name)
print(ResolveHostname)
newFile.write(ResolveHostname + "\n")
print(ResolveHostname)
except socket.herror as e:
newFile.write("No resolution available for %s" % (name) + "\n")


You are catching herror but your code is resulting in gaierror.

Add socket.gaierror to your except line.

   except (socket.herror, socket.gaierror):
   newFile.write("No resolution available for %s" % (name) + "\n")

see if that works


Just a followon remark: always try to print the exception when you're not 
certain of what it will be or what to do with it. So I'd augument Alan's code 
like this:


except (socket.herror, socket.gaierror) as e:
newFile.write("No resolution available for %s: %s" % (name, e) + "\n")

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


Re: [Tutor] Mutable data type in python

2015-10-02 Thread Cameron Simpson

On 02Oct2015 22:22, Anshu Kumar  wrote:

When we invoke the same function inside a function (recursive function), i
want to keep track of some data across all function invocation so i should
have shareable type but built in data types string, int are not helping as
they are immutable they are changed while next invocation.

I could use lists which are mutable but sometimes i find it not suitable
for example when i need only single number or string.


Please provide some more context, perhaps with an example of what you're trying 
to do. What follows is general advice which may not be what you need. Anyway...


What you use depends very much on what you need (trite, but true). Numbers and 
strings are not themselfs mutable.


I'm presuming you want some kind of shared state that continues over the 
recursion, for example a record of what nodes have already been visiting while 
traversing a graph with loops: if you follow a loop you want to stop instead of 
circling/recursing forever.


When I do this I usually form the function somewhat like the below. Let's 
suppose we're walking a graph whose nodes have a ".children" attribute which is 
a list of child nodes. And that the graph might have loops (this node might be 
a child or subchild of itself).


 def traverse(node, seen=None):
   ''' Traverse the graph from `node`, printing each node's name.
   `seen`: if not None, a set of nodes already visited.
   '''
   if seen is None:
 seen = set()
   seen.add(node)
   print(node.name)
   for child in node.children:
 if child not in seen:
   traverse(child, seen)

So the paramater "seen" is your mutable object keeping track of which nodes 
have been visited. You add this node to "seen", then visit any children which 
are not in "seen". You pass "seen" to the traverse() of each child, so all the 
function calls share the same "seen" object.


So in this case we're using a set. There's any number of different things you 
might use depending on what you need to keep track of.


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


Re: [Tutor] how to unittest cli input

2015-10-10 Thread Cameron Simpson

On 10Oct2015 17:41, Alex Kleider  wrote:

I'm trying to follow a test driven development paradigm (using
unittest) but can't figure out how to test functions that collect
info from the command line such as the following.


Aside: I'd say "the standard input" , not "the command line"; to me the latter 
connotes to command line arguments fro sys.argv.


Anyway, ...

I would supply test data either as a string in the unit tests or as a file kept 
with the source tree eg:


 os.path.join(os.path.dirname(__file__), 'test_data.txt')

and then parameterise the input source in you functions. For example:

 def collect_data(src=None):
 if src is None:
 src = sys.stdin

and supply src.

However, you'r eusing input(), which unconditionally uses stdin and stdout. In 
that circumstance I'd consider this:


 def collect_data(src=None, out=None):
 if src is None:
 src = sys.stdin
 if out is None:
 out = sys.stdout
 ostdin = sys.stdin
 sys.stdin = src
 ostdout = sys.stdout
 sys.stdout = out
 ret = {}
 ret['first'] = input("Enter your first name: ")
 ... etc ...
 sys.stdout = ostdout
 sys.stdin = ostdin

Note that this is not thread safe because sys.stdin is a global, but it should 
work for testing.


Anyway, perhap that gives you some way forward.

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


Re: [Tutor] how to unittest cli input

2015-10-11 Thread Cameron Simpson

On 11Oct2015 09:29, Alex Kleider  wrote:

On 2015-10-10 18:10, Cameron Simpson wrote:
   However, you'r eusing input(), which unconditionally uses stdin and
   stdout. In that circumstance I'd consider this:
[... temporarily replace stdin and stdout with test data ...]

Yes indeed, and thank you for your input.
Here's where I'm going with your suggestion:
[...]
test_data = 'test_src.txt'

def data_collection_wrapper(collect, source=None):
   """
   """
   if source:


Minor remark: I would write "if src is not None:". In principle the empty 
string is also "falsey" like None, making your plain "if src:" slightly 
unreliable. Be precise!



   ostdin = sys.stdin
   ostdout = sys.stdout
   src = open(source, 'r')
   sys.stdin = src
   out = open('/dev/null', 'w')  # Dump the prompts.
   sys.stdout = out

   ret = collect()

   if source:
   src.close()
   out.close()
   sys.stdin = ostdin
   sys.stdout = ostdout

   return ret


def collect_data():
   ret = {}
   ret['first'] = input("Enter your first name: ")
   ret['last'] = input("Enter your last name: ")
   ret['phone'] = input("Your mobile phone #: ")
   return ret


That looks like what I had in mind.

If you expect to do this with several functions you could write a context 
manager to push new values for stdin and stdout, call a function and restore.


The "contextlib" stdlib module provides a convenient way to write trivial 
context managers using the "@contextmanager" decorator, which wraps a generator 
function which does the before/after steps. Have a read. I'd be inclined to 
write something like this (untested):


 import sys
 from contextlib import contextmanager

 @contextmanager
 def temp_stdinout(src, dst):
   ostdin = sys.stdin
   ostdout = sys.stdout
   sys.stdin = src
   sys.stdout = dst
   yield None
   sys.stdin = ostdin
   sys.stdout = ostdout

and then in your test code:

 with open(source) as src:
   with open('/dev/null', 'w') as dst:
 with temp_stdinout(src, dst):
   ret = collect()

This has several benefits. Primarily, a context manager's "after" code _always_ 
runs, even if an exception is raise in the inner section. This means that the 
files are always closed, and the old stdin and stdout always restored. This is 
very useful.


You'll notice also that an open file is a context manager which can be used 
with the "with" statement: it always closes the file.


You also asked (off list) what I meant by parameterisation. I mean that some of 
your difficult stems from "collect_data" unconditionally using stdin and 
stdout< and that you can make it more flexible by supplying the input and 
output as paramaters to the function. Example (not finished):


 def collect_data(src, dst):
 ret = {}
 ret['first'] = input("Enter your first name: ")
 ret['last'] = input("Enter your last name: ")
 ret['phone'] = input("Your mobile phone #: ")
 return ret

Now, the input() builtin always uses stdin and stdout, but it is not hard to 
write your own:


 def prompt_for(prompt, src, dst):
 dst.write(prompt)
 dst.flush()
 return src.readline()

and use it in collect_data:

 def collect_data(src, dst):
 ret = {}
 ret['first'] = prompt_for("Enter your first name: ", src, dst)
 ret['last'] = prompt_for("Enter your last name: ", src, dst)
 ret['phone'] = prompt_for("Your mobile phone #: ", src, dst)
 return ret

You can also make src and dst optional, falling back to stdin and stdout:

 def collect_data(src=None, dst=None):
 if src is None:
 src = sys.stdin
 if dst is None:
 dst = sys.stdout
 ret = {}
 ret['first'] = prompt_for("Enter your first name: ", src, dst)
 ret['last'] = prompt_for("Enter your last name: ", src, dst)
 ret['phone'] = prompt_for("Your mobile phone #: ", src, dst)
 return ret

Personally I would resist that in this case because the last thing you really 
want in a function is for it to silently latch onto your input/output if you 
forget to call it with all its arguments/parameters. Default are better for 
things that do not have side effects.



def main():
   print(collect_data())  # < check that user input works
   # then check that can test can be automated >
   print(data_collection_wrapper(collect_data,
   src=test_data))

if __name__ == "__main__":
   main()

Perhaps data_collection_wrapper could be made into a decorator (about
which I am still pretty naive.)

It'll take more studying on m

Re: [Tutor] Guidance on using custom exceptions please

2015-10-12 Thread Cameron Simpson

On 13Oct2015 10:37, Steven D'Aprano  wrote:

On Mon, Oct 12, 2015 at 02:55:43PM +, David Aldrich wrote:

Consider a 'send' method that sends a message to another system via a
socket.  This method will wait for a response before returning.  There
are two possible error conditions:

[...]

So, my question is, what's the pythonic way of doing this?  Should I
subclass RuntimeError for each possible error condition?  E.g.:

   class MessageTimeoutError(RuntimeError): pass
   class IllegalResponseError(RuntimeError): pass


I don't think you should be subclassing RuntimeError at all. I'm not
quite sure what exception you should subclass, but I am confident it
shouldn't be RuntimeError.

Help on class RuntimeError in module exceptions:

class RuntimeError(StandardError)
   Unspecified run-time error.


I tend to use RuntimeError for program logic errors (code paths that shoudn't 
happen, like not handling an option combination). I would not use it for this.



Since you are working with sockets, I think a socket error might be most
useful:

import socket  # which I expect you are already doing

class MessageTimeoutError(socket.error): pass
class IllegalResponseError(socket.error): pass

Or possibly inherit from the same exception class that socket.error
inherits from: IOError.


I have mixed feeling about this; I feel that socket.error or IOError should 
reflect actual OS level or IO subsystem errors, not higher level program 
discrepancies such as invalid packet data. I would be included to subclass 
StandardError.


Antipattern example: I discovered yesterday that PILLOW raises OSError when it 
doesn't recognise an image file's content. I consider that a bad choice; I'd 
prefer ValueError probably - there's been no OS level failure like lack of 
permission to open the file.


On that basis, I recommend either just raising a ValueError for an invalid 
packet or subclassing it.



I'm not certain that you actually need MessageTimeoutError since the
socket module itself already defines a socket.timeout error that will be
raised on a timeout. Just re-use that.


That seems reasonable, if he's using the recv timeout facility.

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


Re: [Tutor] Beautiful Soup

2015-10-12 Thread Cameron Simpson

On 12Oct2015 21:21, Crusier  wrote:

I am using Python 3.4. I am trying to do some web scraping at this moment.
I got stuck because there is an IndexError: list index out of range if I
put stock_code = (18). My desire output is that the script is able to
detect print out the recent price whether it is up, down or unchanged.


Just a remark: you write:

 var = (value)

a lot. It's ok, but needless and also slightly prone to turning into a tuple if 
there's a stray comma. Anyway...


It would be helpful to have the exact error message. You say "there is an 
IndexError: list index out of range", but that can occur in several places in 
your code. Normally Python will print a stack trace indicating the specific 
place in your code where the exception occurred.


Please always include the complete error message when asking for help.

[...]

   print('Now is trading at UP', item.select('.up2')[0].text)


Everywhere you have [0] you may get an IndexError if the select returns an 
empty list, because there will be no element 0.



   elif item.select('.down2') == item.select('.down2'):


I'm curious: how can this test ever be false?

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


Re: [Tutor] Guidance on using custom exceptions please

2015-10-13 Thread Cameron Simpson

On 13Oct2015 13:43, David Aldrich  wrote:

Thanks for all the answers to my question, they were all helpful.

I have one more question, which regards style.  Suppose my 'send' method is in 
its own module: TxControl, along with the custom exceptions:

TxControl.py:

class MessageTimeoutError(Exception): pass
class UndefinedMessageTypeError(Exception): pass

def send(msg)
etc.

Then it seems that an importer of that module must include the module name when 
referencing the exceptions:

import TxControl

try:
   send(msg)
except (TxControl.MessageTimeoutError, TxControl.UndefinedMessageTypeError) as 
err:
   # Exception processing

Including 'TxControl' seems a bit tedious, and is even worse if TxControl 
imports exceptions from yet another module and allows them to pass up the 
stack.


Without ignoring others' arguments for keeping the full names, you can also go:

 from TxControl import send, MessageTimeoutError, UndefinedMessageTypeError

and just use them unqualified like any other name you might import.

The core issue, to me, is: are the exception names nice and descriptive (they 
look ok to me) and is the module you're using them in not using other 
exceptions of similar name and purpose (i.e. how confusing might the 
unqualified named be)?


Also bear in mind that you can do this:

 from TxControl import send as tx_send, MessageTimeoutError as TxTimeoutError, 
 UndefinedMessageTypeError as TxUndefinedMessageType


which gets you more descriptive names for local use. If course, if these 
exceptions are widely used in many contexts (many other code pieces) then you 
might want to stick with the original names for consistency.


Cheers,
Cameron Simpson 

Go not to the elves for counsel, for they will say both no and yes.
- Frodo, The Fellowship of the Ring
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Create complex dictionary

2015-10-22 Thread Cameron Simpson

On 22Oct2015 23:19, jarod...@libero.it  wrote:

Hi!!I would like to prepare a dictionary with complex structure:

complex = {name ="value",surname="po",age=poi)


Well, in Python you'd write the above like this:

 complex = {'name': "value", 'surname': "po", 'age': poi}


What is the most pythonic way to build   a dictionary of dictionary?


Your description is a bit vague, but it sounds like a dictionary or 
dictionaries is a reasonable way to do it. Example:


 records = {}
 complex = {'name': "value", 'surname': "po", 'age': poi}
 records['key1'] = complex
 complex = {'name': "value2", 'surname': "xy", 'age': poi2}
 records['key2'] = complex

Nothing wrong with that if it fits what you actually need to do.

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


Re: [Tutor] noob python question

2015-10-25 Thread Cameron Simpson

On 25Oct2015 16:16, bob5487  wrote:

Reading *Learn Python the Hard Way* Zed Shaw
All good so far but got to Ex 42 dealing with classes...

I get a TypeError: getattr(): attribute name must be a string when I run the
program...

I looked online, python reference manual 3rd edition, etc...
I was wondering if anyone has experience with this book because I hit a road
block


As always with this list, please post the code you're trying. Even if we had 
the book (I do not, personally), we don't know if your failing code matches the 
code in the book, or if the code in the book is correct.


So please post the code, and the complete error message your computer gives 
you.


Also not that getattr takes a string, per the error message. So to fetch the 
.foo attribute from some object "o" you would write:


 attribute = getattr(o, 'foo')

Note the quotes.

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


Re: [Tutor] How do I (idiomatically) determine when I'm looking at the last entry in a list?

2015-10-28 Thread Cameron Simpson

On 28Oct2015 14:48, Flynn, Stephen (L & P - IT)  
wrote:

Python 3.

I'm iterating through a list and I'd like to know when I'm at
the end of the said list, so I can do something different. For example

list_of_things = ['some', 'special', 'things']
for each_entry in list_of_things:
print(each_entry)
if each_entry == list_of_things[-1]: # do something special to
last entry
...etc

Is this the idiomatic way to detect you're at the last entry in a list
as you iterate through it?


If it really is a list then enumerate is your friend.

 list_of_things = ['some', 'special', 'things']
 last_index = len(list_of_things) - 1
 for index, each_entry in enumerate(list_of_things):
   print(each_entry)
   if index == last_index:
 ... special stuff for the last index ...


For context, I'm working my way through a (csv) file which describes
some database tables. I'm building the Oracle DDL to create that table
as I go. When I find myself building the last column, I want to finish
the definition with a ");" rather than the usual "," which occurs at the
end of all other column definitions...


This is a bit different, in that you are probably not using a list: you don't 
know how long the sequence is.


I build things like that this way:

 fp.write('CREATE TABLE wibble\n(')
 sep = '\n   '
 for item in items:
   fp.write(sep)
   fp.write(... column definition for item ...)
   sep = ',\n   '
 fp.write('\n);\n')

i.e. instead of printing the separator _after_ each item, print it _before_.  
That way you can special case the first occasion and use a comma for each 
successive occasion.


Cheers,
Cameron Simpson 

Why is it whatever we don't understand is called a 'thing'? - "Bones" McCoy
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Unable to retreive the stock code

2015-11-16 Thread Cameron Simpson

On 16Nov2015 15:41, Crusier  wrote:

I am currently trying to download the stock code. I am using Python
3.4 and the code is as follows:

[...]

   for link in soup.find_all("a"):
   stock_code = re.search('/d/d/d/d/d', "1" )
   print(stock_code, '', link.text)

[...]

I am trying to retrieve the stock code from here:
1
or from a href.


Well it looks like you have all the needed libraries. You're doing a few things 
wrong above. Firstly, to match a digit you need "\d", not "/d". Secondly, your 
use of "re.search" searches the literal string "1" instead of, presumably, 
the value of link.text. Thirdly, the return from "re.search" is not a stock 
code but a "match object"; I would not call it "stock_code" but 
"stock_code_match".  That will contain a reference to the stock code; since 
your regexp matches the stock code then stock_code_match.group(0) will return 
the actual matched text, the stock code.


Fix that stuff and see where you are.

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


Re: [Tutor] Python 3.5 console logging

2015-12-01 Thread Cameron Simpson

On 30Nov2015 16:50, Tyler Smithers  wrote:

I am doing a project for my school and i am trying to find out how to make
a event log. But every where i look all it has is just making a text
document and it having in their what they put in their script.


That is normally what an event log it; a text file recording significant 
events. This can be done simply with print() calls or more elaborately via the 
logging module.



But i cant
find out how to code python into recording everything that happens when i
run the program. And can you please help me soon because i don't have much
time. Thank you!


When you say everything, what do you mean? Normally people don't want that 
("everything" might mean every python code line traversed, or every internal 
python opcode executed, etc). Normally that is an insane amount of details, and 
people normally just want to know significant events (user logged in, did this, 
was refused that, files opened/closed or stuff like that).


You'll need to elaborate a bit more on what you're trying to achieve here.

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


Re: [Tutor] Python 3.5 console logging

2015-12-03 Thread Cameron Simpson

On 01Dec2015 11:31, Laura Creighton  wrote:

He may be looking for something like the logging facility of Gnu screen.


Or the venerable "script" command. But I suspect he wants something else.

Cheers,
Cameron Simpson 

The worst tyrannies were the ones where a governance required its own logic on
every embedded node. - Vernor Vinge
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Beginner: Socket object and packets

2015-12-05 Thread Cameron Simpson

On 05Dec2015 13:21, Marc Eymard  wrote:

Hi tutor,
I am trying to locate the first blank line in the first received packet when 
pinging an internet server using a socket object.


First up: everything ALan already said.

Next:

Note that the HTTP response need not all be in a single packet, though that is 
not your problem.


My assumption is there will be a mandatory blank line right after the 
http headers in accordance with the http protocol.


There certainly should be.


Consider the following:
import socket
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect( ('www.py4inf.com/code/', 80) )
mysock.send('GET http://www.py4inf.com/code/' + ' HTTP/1.0\n\n')
data_str = mysock.recv(700)

My question:

Why is the following statement False when there is an actual blank 
line in the received packet:

   '\n\n' in data


1: You will be getting bytes backup from the server (obviously so in Python 3 
and implicitly in Python 2).


2: The HTTP protocol, like most internet text protocols, ends lines with the 
bytes '\r\n', not just '\n'.


Therefore you should expect the bytes '\r\n\r\n' in the response data.

However, you should have discovered this already by doing some debugging. Since 
you're clearly not getting the response you expected, the very first step on 
your part should be to print our the received data, for example by adding:


 print(repr(data_str))

after your recv() call. Then you could inspect the received data and probably 
have seen the '\r' characters.


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


Re: [Tutor] reading an input stream

2015-12-24 Thread Cameron Simpson

On 24Dec2015 13:54, richard kappler  wrote:

I have to create a script that reads  xml data over a tcp socket, parses it
and outputs it to console. Not so bad, most of which I already know how to
do. I know how to set up the socket, though I am using a file for
development and testing, am using lxml and have created an xslt that does
what I want with the xml, and it outputs it to console.

What I'm not really sure of, each xml 'message' is preceeded by an STX
(\x02) and ends with an ETX (\x03). These 'messages' (Danny, are you noting
I don't say -lines- anymore? :-)  ) need to be parsed and output whole as
opposed to partial.

My concern is, there will actually be numerous machines sending data to the
tcp socket, so it's entirely likely the messages will come in fragmented
and the fragments will need to be held until complete so they can be sent
on whole to the parser. While this is the job of tcp, my script needs to

I think what I need to do would be analogous to (pardon if I'm using the
wrong terminology, at this poing in the discussion I am officially out of
my depth) sending the input stream to a buffer(s) until  the ETX for that
message comes in, shoot the buffer contents to the parser while accepting
the next STX + message fragment into the buffer, or something analogous.

Any guidance here?


Since a TCP stream runs from one machine to another (may be the same machine); 
presumably your actually have multiple TCP streams to manage, and at the same 
time as otherwise you could just process one until EOF, then the next and so 
on. Correct?


My personal inclination would start a Thread for each stream, and have that 
thread simple read the stream extracting XML chunks, and then .put each chunk 
on a Queue used by whatever does stuff with the XML (accept chunk, parse, etc).  
If you need to know where the chunk came from, .put a tuple with the chunk and 
some context information.


Does that help you move forward?

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


Re: [Tutor] Read from large text file, find string save 1st string of each line where it appeared.

2015-12-28 Thread Cameron Simpson

On 29Dec2015 03:12, Steven D'Aprano  wrote:

On Mon, Dec 28, 2015 at 04:50:05PM +0530, sutanu bhattacharya wrote:

suppose 61746245  is my searching string. so o/p will be

[...]


I don't understand the question.
What is "o/p"?


"output"

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


Re: [Tutor] method, type?

2016-01-05 Thread Cameron Simpson

On 05Jan2016 20:58, Alex Kleider  wrote:

#!/usr/bin/env python3
# OS: Ubuntu 10.4LTS

# My code:

class JournalLineItem(object):
   """
   """

   def __init__(self, account, debit_or_credit, amount):
   self.account = account
   self.debit_or_credit = debit_or_credit
   self.amount = float(amount)

   def show(self):
   return ("ACNT: {}  ${:0.2f} {}".
   format(self.account, self.amount, self.debit_or_credit))

   def get_line_item(text):
   return JournalLineItem(*text.split())

def test():
   print(
   JournalLineItem.get_line_item("2435 Dr 25.33").show())

if __name__ == "__main__":
   test()

   myquestion = """

What kind of a method/function is get_line_item?


As written, it is an instance menthod that _thinks_ it is a static method. Not 
that that was what you intended :-)



From what I've read (and not fully understood)
static methods and class methods must have
@staticmethod and @classmethod on the line above them.


As written, you could put @staticmethod above it - it is an ordinary function 
that resides in the class to associate its functionality with the class.


However, what you are probably better off with is @classmethod, for reasons I 
will explain below.


Instance methods expect their first parameter to be the instance (self) and 
class methods expect their first parameter to be the class. This is arranged 
implicitly when you call the method via an instance or class.



get_line_item works as I wanted but it's clearly not the
usual type of method and I don't know how to categorize it.


It is confused. There is nothing in the Python language that requires the 
instance to be called "self", that is just convention. So your method thinks 
that the instance is "text", and works on that. So you could do this:


 jli = JournalLineItem(account, debit_or_credit, amount)
 jli.get_line_item()

and the call would go ahead, but fail because a JournalLineItem has no .split 
method. And you can't do this:


 jli = JournalLineItem(account, debit_or_credit, amount)
 jli.get_line_item("2435 Dr 25.33")

because, since it is an instance method, Python implicitly passes in the 
instance (jli) as the first parameter, so the call is equivalent to:


 JournalLineItem.get_line_item(jil, "2435 Dr 25.33")

but the function only expected a single parameter. Badness ensues.


It's an instance creator- is there a better term?


Generally these are called factories. Normally you would either write this as a 
class method:


 @classmethod
 def get_line_item(cls, text):
   return cls(*text.split())

which will get JournalLineItem when you call it as in your example:

 item = JournalLineItem.get_line_item("2435 Dr 25.33")

but will get the right subclass if you subclass JournalLineItem:

 class SpecialJournalLineItem(JournalLineItem):
   ...

 special_item = SpecialJournalLineItem.get_line_item("2435 Dr 25.33")

Alternatively, if you never expect to subclass this, you could just declare it 
as a normal function outside the class entirely:


 def get_line_item(cls, text):
   return JournalLineItem(*text.split())

Often these functions or methods are called from_blah, so the outside-the-class 
function might be called "JournalLineItem_from_text", and the inside the class 
@classmethod one might be called "from_text". So you might write:


 jli = JournalLineItem.from_text("2435 Dr 25.33")

which reads well and allows you to subclass JournalLineItem later. Therefore I 
would recommend the @classmethod approach. And stylisticly, I would put that up 
the top, just under __init__.


Hoping this helps rather than confuses,
Cameron Simpson 
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] method, type?

2016-01-06 Thread Cameron Simpson

On 06Jan2016 18:57, ALAN GAULD  wrote:

On 06/01/16 14:46, Steven D'Aprano wrote:

It would be reasonable to make this a factory function declared in the
global module level. But I think making it a classmethod is better.


I won't put up much of an argument here. In C++ or Java I'd
definitely say use a class method. But it seems to me that I've
seen more factory functions in modules than class method factories.
But that's not been a detailed analysis just a gut feel for what
seems idiomatic in Python. It also seems easier for beginners
to grasp than the more esoteric notion of class methods.


Most of my factories are global functions, but that is mere historic artifact.  
As a direct consequence of explaining this to Alex Kleider I'm moving 
aggressively to using @classmethod for this, naming them ".from_*" unless I 
have some amazing reason not to.



... ensures that if you subclass the class, you automatically
get a valid constructor as well.


Wouldn't it return an instance of the superclass rather than
the sub class? You'd need to override it wouldn't you?


No, when you call:

 SubClass.from_blah(...)

where from_blah is defined in the superclass, the leading "cls" parameter is 
the subclass because you invoked it through the subclass, just as you get the 
leading "self" instance parameter when you invoke an instance method through 
the instance. That's one reason that @classmethod is so nice here.


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


Re: [Tutor] method, type?

2016-01-06 Thread Cameron Simpson

On 07Jan2016 00:06, ALAN GAULD  wrote:

On 06/01/16 23:00, Cameron Simpson wrote:


... ensures that if you subclass the class, you automatically
get a valid constructor as well.


Wouldn't it return an instance of the superclass rather than
the sub class? You'd need to override it wouldn't you?


No, when you call:

  SubClass.from_blah(...)

where from_blah is defined in the superclass, the leading "cls" parameter is
the subclass because you invoked it through the subclass,


Yes, but my point is that constructors by their nature tend
to be very  specific.


That wasn't what you said; because cls comes in as a parameter you will 
inherently get the subclass.


To your point: I don't think factory methods are necessarily very different in 
a subclass. Sometimes?  Often?  I think it is pretty variable.  In principle 
factory functions need not vary much more than any other method.  And like any 
other method, if it is special then it needs an override.



For example a constructor that fetches data from a database
will embed a SQL query that is table specific and so may be
completely wrong for a sub class (unless it somehow shares
the superclass's table).


Or if the table name (or table definition from some mapping) is a parameter of 
the subclass. I would try to make it so myself.



Similarly reading from a network it
will only pull the fields necessary for the superclass from
the message. Indeed the trigger message it sends to the
server to initiate the transfer may well have the class
details included. So although you might wind up with an
object whose type is subclass, its details may be totally
wrong or even fail to operate (if the table has no
corresponding ID for example).


Shrug. So in these cases you either need to have per-class parameters or have 
to override the factory methods as required. Like anything else. I don't think 
this is an argument against @classmethod factory functions, merely an argument 
against inattention when subclassing.



It would certainly work for a few cases but I suspect
most real-world constructors will fail unless overridden.
Other class methods are much more likely to work OK. (For
example those maintaining a cache of instances or simply
keeping a count) I'm just dubious about constructors
because they are so specific about where/how they obtain
their data. (Unless you get very clever about how you
use cls to access meta-data, or maintain some kind of
config mapping (possibly as class attributes) to tell
the constructor what to do.


I agree it won't also work, or work smoothly. But parameters or metadata from 
the class/subclass may be quite viable - that is the great convenience of the 
cls parameter to class methods. Once all this stuff starts getting too hard to 
look after you're probably in either don't-subclass territory, or providing 
common methods/mechanisms with mixins (i.e. a lookalike class instead of a 
subclass).


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


Re: [Tutor] reading an input stream

2016-01-07 Thread Cameron Simpson

On 07Jan2016 12:14, richard kappler  wrote:

On Thu, Jan 7, 2016 at 12:07 PM, James Chapman  wrote:

From an architectural POV I'd have a few listener threads that upon
receipt would spawn (or take from a pool is a better approach) a worker
thread to process the received data.


As would I.


That's the plan, if I'm understanding you correctly. We've brainstormed the
threading, haven't written any of it yet.


The code you've posted should be fine for testing a single connection.

I'd be doing 2 things to what you posted, myself:

 - use plain old .read to collect the data and assemble the XML packets

 - decouple your XML parsing from the collection and packet parsing

To the first, I suspect that when you have our packets arriving rapidly you are 
either dropping data because the data overflows your 8192 recv size or you're 
getting multiple logical packets stuffed into a buffer:


 recv #1:
   \x02xml...\x03\x02partial-xml

 recv #2:
   tail-of-previous-xml\x03\x02more-xml...

which would definitiely get your XML parser unhappy.

Instead, gather the data progressively and emit XML chunks. You've got a TCP 
stream - the TCPServer class will do an accept and handle you an _unbuffered_ 
binary stream file from which you can just .read(), ignoring any arbitrary 
"packet" sizes.  For example (totally untested) using a generator:


 def xml_extractor(fp):
   ''' Read a continuous stream of bytes from `fp`, yield bytes to be parsed 
   elsewhere. An arbitrary size of 8192 bytes is used to request more data; it 
   doesn't say anything about any underlying network packet size.

   '''
   # a (buffer, offset) pair of ungathered data
   buffer = b''
   offset = 0
   # locate start of XML chunk
   while True:
 if offset >= len(buffer):
   buffer = fp.read1(8192)
   offset = 0
   if not buffer:
 # EOF: exit generator
 return
 # examine the next byte
 b = buffer[offset]
 offset += 1
 if b == 0x02:
   # opening delimiter
   break
 warning("discard byte 0x%02x", b)
   # gather XML chunk
   chunks = []
   while True:
 endpos = buffer.find(b'\x03', offset)
 if endpos < 0:
   # no delimiter, collect entire chunk
   chunks.append(buffer[offset:])
   offset = len(buffer)
 else:
   # collect up to the delimiter
   chunks.append(buffer[offset:endpos])
   offset = endpos + 1
   break
 # keep collecting...
 if offset >= len(buffer):
   buffer = fp.read1(8192)
   offset = 0
   if not buffer:
 error("EOF: incomplete final XML packet found: %r", b''.join(chunks))
 return
   # yield the XML bytes
   yield b''.join(chunks)
   chunks = None   # release chunks so memory can be freed promptly

This reads bytes into a buffer and locates the 0x02...0x03 boundaries and 
yields the bytes in between. Then your main stream decoder just looks like 
this:


 for xml_bytes in xml_extractor(fp):
   # decode the bytes into a str
   xml_s = xml_bytes.decode('utf-8')
   ... pass xml_s to your XML parser ...

All of this presumes you have a binary file-like object reading from your TCP 
stream. And since we're suggesting you spawn a Thread per connection, I'm 
suggesting you use the TCPServer class from the socketserver module, using its 
ThreadingMixin. That gets you a threading TCP server.


Query: do the cameras connect to you, or do you connect to the cameras? I'm 
presuming the former.


So the surround framework would create a TCPServer instance listening on your 
ip:port, and have a handler method which is given a "request" parameter by 
TCPServer. That object has a .rfile property which is a read-only binary stream 
for reading from the socket, and _that_ is what we refer to as `fp` in the code 
above.


Setting up the TCPServer is pretty simple. Lifting the essential bits from some 
code of my own (again, untested):


 from socketserver import TCPServer, ThreadingMixIn, StreamRequestHandler

 class MyServer(ThreadingMixIn, TCPServer):
   def __init__(self, bind_addr):
 TCPServer.__init__(self, bind_addr, MyRequestHandler)

 class MyRequestHandler(StreamRequestHandler):
   def handle(self):
 fp = self.rfile
 for xml_bytes in xml_extractor(fp):
   # decode the bytes into a str
   xml_s = xml_bytes.decode('utf-8')
   ... pass xml_s to your XML parser ...

 # start the server
 S = MyServer( ("hostname", ) )
 S.serve_forever()

One critical bit in the above is the use of .read1() in the xml_extractor 
function: that calls the underlying stream's .read() method at most once, so 
that it behaves like a UNIX read() call and may return a "short" read - less 
than the maximum supplied. This is what you need to return data as soon as it 
is r

Re: [Tutor] reading an input stream

2016-01-07 Thread Cameron Simpson

On 08Jan2016 08:52, Cameron Simpson  wrote:
[...]
Instead, gather the data progressively and emit XML chunks. You've got a TCP 
stream - the TCPServer class will do an accept and handle you an _unbuffered_ 
binary stream file from which you can just .read(), ignoring any arbitrary 
"packet" sizes.  For example (totally untested) using a generator:

[...]

Just a few followup remarks:

This is all Python 3, where bytes and strings are cleanly separated. You've got 
a binary stream with binary delimiters, so we're reading binary data and 
returning the binary XML in between. We separately decode this into a string 
for handing to your XML parser. Just avoid Python 2 altogether; this can all be 
done in Python 2 but it is not as clean, and more confusing.


The socketserver module is... annoyingly vague about what the .rfile property 
gets you. It says a "a file-like object". That should be a nice io.BytesIO 
subclass with a .read1() method, but conceivably it is not. I'm mentioning this 
because I've noticed that the code I lifted the TCPServer setup from seems to 
make a BytesIO from whole cloth by doing:


 fp = os.fdopen(os.dup(request.fileno()),"rb")

You'd hope that isn't necessary here, and that request.rfile is a nice BytesIO 
already.


In xml_extractor, the "# locate start of XML chunk" loop could be better by 
using .find exactly as in the "# gather XML chunk"; I started with .read(1) 
instead of .read1(8192), which is why it does things byte by byte.


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


Re: [Tutor] reading an input stream

2016-01-07 Thread Cameron Simpson

On 07Jan2016 17:22, richard kappler  wrote:

On Thu, Jan 7, 2016 at 5:07 PM, Cameron Simpson  wrote:



Just a few followup remarks:

This is all Python 3, where bytes and strings are cleanly separated.
You've got a binary stream with binary delimiters, so we're reading binary
data and returning the binary XML in between. We separately decode this
into a string for handing to your XML parser. Just avoid Python 2
altogether; this can all be done in Python 2 but it is not as clean, and
more confusing.



Love to, can't. Splunk uses 2.7 so that's what we have to work with. That
will not change in the forseeable future. Doing other homework right now,
but will more closely review this and the other posts that have come in
since I left work later tonight or first thing in the morning.


Ok. You should still be ok, but things like bs[0] == 0x02 will need to be bs[0] 
== '\x02' and so forth, because you get str objects back from reads.


The rest of the suggested code should still broadly work.

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


Re: [Tutor] basic threading question

2016-01-07 Thread Cameron Simpson

On 07Jan2016 14:26, richard kappler  wrote:

See previous posts on 'looping generator' for details about the code and
project.

The brief version, I am reading and parsing a data stream through a socket,
several actually. Each new connection spawns a thread that reads and
parses. Should the client close, I want the thread to terminate. Everything
I've read says you don't kill threads, but if the client closes, the socket
closes, and the thread is just sitting there, hanging.

If the socket.recv returns 0 bytes, the docs tell me that means the client
closed and therefore the server socket closes as well. If I do something in
the thread target function like:

   data_chunks = connection.recv(8192)
   if len(data_chunks) == 0:
break

len(data_chunks)==0 tells me the socket is closed, but does the break kill
the thread? How do I prove that if it does?


The break doesn't kill the thread, but if the recv loop is all your thread's 
main function does, then sure: when the function exits, the thread exits. For 
example:


 T = Thread(target=gather_func)
 T.start()
 ...

 def gather_func():
   while True:
 data_chunks = connection.recv(8192)
 if len(data_chunks) == 0:
   break
 ... do stuff with data_chunks ...

Then you break exits the loop. Then the function returns since there's no more 
code in the function after the loop. And then the Thread exits because the 
function it was running has finished. There is no need to kill the Thread here.


You can wait for the Thread with T.wait() and probe it with T.is_alive(); see 
the threading module documentation.


BTW, I still recommend you drop use of .recv() and use .read1() to assemble 
packets. See your main discussion.


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


Re: [Tutor] method, type?

2016-01-07 Thread Cameron Simpson

On 08Jan2016 10:19, Steven D'Aprano  wrote:

[...]

"factory" methods (typically called '.from_*') can be:


Maybe I should have said "often" instead of "typically", if I said "typically".  
I think they read well that way and there are several stdlib functions named 
this way as a precedent. I'm aiming for the notion "make a Foo from this or 
that or something else (3 distinct methods/functions, all taking arguments a 
bit different from the core __init__)".



1. a normal function outside the class, or
2. a class method (would allow subclassing.)


"Factory methods" just means a method which you, the creator or author,
thinks of as a factory. What's a factory? A function or method which
takes a bunch of arguments and creates something useful.

It's a pretty vague definition, because it's a pretty vague term.


It's mostly vague if you take the "everything is an object in Python" stance.  
Which is strictly true, but it is often useful to be thinking of a factory 
function as an alternative to the bare ClassName(args-for-__init__) 
constructor, where those arguments are not convenient. Such as Alex's 
JournalLineItem construction from a line of text.


[...]

"alternative constructor" (what Petter Otten and Steven DAprano
call it,)


Alternative in the sense of "not the default", that is all.


would be best placed immediately after __init__.


*shrug*
It doesn't matter where you put it inside the class. That is entirely a
matter of personal taste.


I suggested this as a style thing (of course, inherently a matter of personal 
taste:-) I like functions with the same purpose to be textually close together.


[...]

[Alan Gauld] recommends making it a factory
function (defined at the module level, outside the class.)


That's a matter of personal taste, and one which I happen to disagree
with. Look at the design of the built-in classes like dict. We have
dict.fromkeys(), not a global fromkeys() function.


I'm largely with Steven here rather than Alan, partly because a classmethod 
subclasses nicely (with all the caveats Alan alluded to - if you do this then 
your subclasses _may_ need to override the extra constructor just as they may 
need to override other methods), and partly because it keeps the constructor 
inside the class definition, which I find conceptually tidier.



Steven DAprano calls it a Python3 regular function/ a Python2
broken method and mentions the Descriptor protocol and how
'methods' are initially simply functions that are then converted
to methods (bound) as required. In my case it would be an
'unbound' method which works in 3 but not in Python2.

Cameron Simpson indicated that putting @staticmethod above my 'method'
would be OK (although not preferred.)  Present or absent, my method
still functions the same way.


Only because you're just calling it from the class. As soon as you
create an instance and call the method from that, you'll see why it
is broken :-)


Aye. While we're on what staticmethod and classmethod accomplish, we could stop 
treating them like magic. Have you (alex) written any decorators? They are 
functions which accept a function definition and return a wrapper function with 
tweaked behaviour. So the notation:


 @foo
 def func1(blah):

defines "func1" and then calls "foo(func1)". "foo" returns a new function 
definition, and the class binds _that_ definition to its "func1" method.


So...


The table provided by Peter Otten (very helpful:)
-
invoked with | @staticmethod  | @classmethod| no decorator
--
class| args unchanged | class as 1st arg | args unchanged
instance | args unchanged | class as 1st arg | inst as 1st arg
---
It suggests that use of the @staticmethod serves to protect one should
the 'method' be called via an instance rather than the class.  Has it
any other effect?


Yes, to confuse people into thinking they should be using staticmethod
when what they really should use is classmethod :-)


Now consider what @staticmethod achieves: it causes a normal method to be 
called as though it were a global function i.e. without the normally implied 
"self" parameter. So we could write our own:


 def staticmethod(func):
   def method(self, *a, **kw):
 return func(*a, **kw)
 return method

As described above, this effectively installs the "method" function as the 
class's actual method, and that function's whole purpose is simply to _discard_ 
the self parameter and call the original function without "self".


Once tha

Re: [Tutor] method, type?

2016-01-07 Thread Cameron Simpson

On 08Jan2016 00:18, ALAN GAULD  wrote:

My only point of difference here, I think, is the definition
of a constructor. I consider a constructor to be the creator
of object instances, which makes the only default Python
constructor the __new__() since the __init__() is only an
initializer.


Me too. I was deliberately avoiding the term "constructor", then let myself get 
sucked into using it just now because you get a new instance of your target 
class out of the factory function/method. But they are better thought of as 
wrappers for the class' real constructor.


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


Re: [Tutor] Syntax error

2016-01-07 Thread Cameron Simpson

On 07Jan2016 13:15, Sarah Rasco  wrote:

Alan - I realized I did that right after I sent this email. However, I
can't run it in the windows or python prompts.

Here is my document:
[image: Inline image 1]
When I try to run it in the windows prompt I get:
[image: Inline image 2]

[...]

Hi Sarah,

The tutor list and the main python-list strips attachments, so we cannot see 
your images.  Please cut/paste the text as text instead of using screenshots.



I also tried to run it in my windows command prompt. I put in cd C:\python
and it gave me the python prompt.


I think you're misreading the Windows command prompt which recites the current 
folder. This:


 C:\python>

is still the Window command prompt. It is also probably not where you should do 
your python work unless you personally made this folder specially. Where did 
you save your "hello.py" file? That is probably where you should cd.



Then, when I tried to open the file by
typing python hello.py, I was given a syntax error again. Does anyone have
any suggestions as to what the problem could be?


Please cut/paste the text of your hello.py file and a complete transcript of 
the syntax error (all the lines).


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


Re: [Tutor] Organizing files

2016-01-11 Thread Cameron Simpson

On 11Jan2016 13:51, Rene Werner  wrote:

right now I am working on a couple of programming-related challenges. The
challenges are sorted into problem sets, where each set contains a number
of problems.

Because a lot of these problems rely on code that is often the same, I have
put these parts into a seperate file, util.py, and I simply do

from util import *


Remark: you are better off importing only specific names:

 from util import this, that, the_other

otherwise you pollute your namespace to lots of junk. While you've only got one 
module your version works, but it stops being useful pretty soon after you 
start importing more things.



in each solution. I have my solutions organized in different folders, one
for each problem set:

set1/prob1.py
set1/prob2.py
set2/prob3.py

and so on. So far, I keep symlinking util.py in each set folder, so e.g.
set1/util.py is a symlink to ../util.py. The same goes for set2, set3 and
so on. This works, but I get the feeling that it is clumsy and could be
done better.

What is the usual way in python do realize this in a way so that I don't
have to symlink util.py for every problem set, but still have it available?


The normal way is to have your own module library and modify $PYTHONPATH to 
consult it. You might have a $HOME/python_modules directory with util.py inside 
it (or whatever other modules). Put:


 PYTHONPATH=$HOME/python_modules
 export PYTHONPATH

in your environment. Then Python will know to look in your python_modules 
directory for modules ahead of other places and you will not need the symlinks 
(which are fragile anyway).


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


Re: [Tutor] s.insert(i, x) explanation in docs for Python 3.4 confusing to me

2016-01-15 Thread Cameron Simpson

On 15Jan2016 22:20, boB Stepp  wrote:

At 
https://docs.python.org/3.4/library/stdtypes.html#sequence-types-list-tuple-range
it states:

"s.insert(i, x) inserts x into s at the index given by i (same as s[i:i] = [x])"

I find this confusing.  First, at the interpreter, whenever I type in:


things

[0, 'Hmm...', 3, 'WhackABunny', 6, '?']

things[-1:-1]

[]

things[0:0]

[]

I always get an empty list, which is actually what I was expecting, so
I do not see how s[i:i] can ever equal [x].


It isn't an equality test (==), it is an assignent. It is saying "set the zero 
length sequence at index i to the one element sequence [x]".



The second thing I find puzzling is the docs say x is inserted at
position i, while in the interpreter:


help(list.insert)

Help on method_descriptor:

insert(...)
   L.insert(index, object) -- insert object before index

The "...insert object before index" makes sense to me, but "...inserts
x into s at the index given by i..." does not because:


Personally I'd rather it said "insert object at index". For "before" I'd need 
something longer, like "insert object before the elements from index onward".



things.insert(-1, 'What the heck?!?')
things

[0, 'Hmm...', 3, 'WhackABunny', 6, 'What the heck?!?', '?']

"...at the index..." to me would mean that 'What the heck?!?' should
become the last item in the list.  Again, the interpreter help gave
what I was expecting.


To me it means "insert 'x' so that its index is 'i'".


Am I just being dense or are the docs in this instance confusing?


They may be a bit confusing, though I do think you're misreading the "=" bit at 
the top.


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


Re: [Tutor] s.insert(i, x) explanation in docs for Python 3.4 confusing to me

2016-01-15 Thread Cameron Simpson

On 15Jan2016 23:05, boB Stepp  wrote:

On Fri, Jan 15, 2016 at 10:53 PM, Cameron Simpson  wrote:

things.insert(-1, 'What the heck?!?')
things


[0, 'Hmm...', 3, 'WhackABunny', 6, 'What the heck?!?', '?']

"...at the index..." to me would mean that 'What the heck?!?' should
become the last item in the list.  Again, the interpreter help gave
what I was expecting.



To me it means "insert 'x' so that its index is 'i'".


But that's my point!  In my example x (here 'What the heck?!?') is
*not* at index i (here, -1).  Instead it winds up at index -2.  But
this fits in perfectly with the interpreter help, since it winds up
*before* index i (-1).


Ah, but -1 isn't the "real" index. It is a convenient value for computing the 
real index if you want to figure things out from the end of the list instead of 
the start.  In your example above, the real index is 5.  As you would get from 
things.index('?') before the insert. So your insert really means:


 things.insert(5, 'What the heck?!?')

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


Re: [Tutor] s.insert(i, x) explanation in docs for Python 3.4 confusing to me

2016-01-16 Thread Cameron Simpson

On 16Jan2016 18:43, boB Stepp  wrote:

This led me to try:


mylist[:None]

[100, 200, 300, 400, 500]

So, in effect, None is acting as a place holder for that final
position in slices.  Also, I would never have thought to be able to
use a logical "or" inside an index in Peter's "[:-i or None]".


Yah, like the default value for many missing parameters. When you don't need an 
expression after the ":" you can of course write:


 mylist[:]

much like writing a function "def f(x, y=None)"; None is a sentinel value - 
specially recognised as nor in the normal domain for that value.


Cheers,
Cameron Simpson 

Q: How does a hacker fix a function which doesn't work for all of the elements 
in its domain?

A: He changes the domain.
- Rich Wareham 

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


Re: [Tutor] s.insert(i, x) explanation in docs for Python 3.4 confusing to me

2016-01-17 Thread Cameron Simpson

On 16Jan2016 22:42, Alex Kleider  wrote:

On 2016-01-16 18:02, Cameron Simpson wrote:

much like writing a function "def f(x, y=None)"; None is a sentinel
value - specially recognised as nor in the normal domain for that
value.


Can you please clarify the last bit:
"specially recognised as nor in the normal domain for that value."


s/nor/not/

The domain of a function (or value) is the set of valid values it may take. The 
range is the set of values it may produce.


A sentinel value is a special value you may encounter in a data set (or as a 
value) which is _not_ part of the normal domain; often it indicates the end of 
a sequence (hence the name, like a border guard).  In Python the special value 
None is often used as a sentinel value.  Since all names have _some_ value, if 
you need to indicate that this name "isn't set" or "doesn't specify a valid 
value", you need a sentinal value, often "None".


So the common idiom for default values in Python function definitions:

 def func(a, b, c=None):
   if c is None:
 c = default-value-for-c
   ...

indicates that the parameters "a" and "b must be supplied, and "c" is optional.  
If not supplied it will have the value "None". This is a sentinel value so that 
"func" can distinguish a valid value from a value not supplied.


You can also use them to indicate the end of data in some sense. If you're 
looking at a text file as lines of printable characters, the newline character 
at the end of the line could be considered a sentinel. Also consider a Queue: 
there's no notion of "closed" in the stdlib version, so one might put a None on 
the queue to indicate to the consumer that there will be no more items.


It isn't always None. Sometimes you may want to pass None as normal data, or 
you have no control over what is passed around. In that case you might need to 
make a unique sentinel value entirely for your object. The normal way to do 
this is simply to make a new object:


 sentinel = object()

This is a minimal Python object which nobody else is using. Its value is 
nothing special (or even meaningful), so you merely want to check whether what 
you've got is that particular object, using "is". Untested example sketch:


 class SomethingLikeAQueue:

   def __init__(self,..):
 self.things = []
 # private value to use as a sentinel, unique per instance
 self._sentinel = object()
 ... whatever else ...

   def put(self, value):
 # public method to put a new value
 if value is self._sentinel:
   raise ValueError("you may not put the sentinel value")
 self._put(value)

   def _put(self, value):
 # private method accepting any value including the sentinel
 # we will use receipt of the sentinel to process the things and stop 
 # further acceptance of more things

 if value is self._sentinel:
   things = self.things
   self.things = None  # will make the .append blow up
   ... process things here maybe ...
 else:
   things.append(value)

   def close(self):
 # send the sentinel to indicate no more things
 self._put(self._sentinel)

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


Re: [Tutor] s.insert(i, x) explanation in docs for Python 3.4 confusing to me

2016-01-17 Thread Cameron Simpson

On 17Jan2016 10:49, Alex Kleider  wrote:

Can you please clarify the last bit:
"specially recognised as nor in the normal domain for that value."


s/nor/not/


May I trouble you further by specifically asking about 's/nor/not/'- I don't 
get what that's about.


Ah. Ed, sed, vi, vim speak. Substitute: replace "nor" with "not". The "nor" is 
a typo. I meant "not in the normal domain".



Has it to do with this 'nor': http://www.merriam-webster.com/dictionary/nor?


"Nor" is indeed a useful word, but it wasn't the word I intended.

[...]

It isn't always None. [...]
you might need to make a unique sentinel value entirely for your
object. The normal way to do this is simply to make a new object:

sentinel = object()

This is a minimal Python object which nobody else is using. Its value
is nothing special (or even meaningful), so you merely want to check
whether what you've got is that particular object, using "is".
Untested example sketch:

class SomethingLikeAQueue:

  def __init__(self,..):
self.things = []
# private value to use as a sentinel, unique per instance
self._sentinel = object()
... whatever else ...

  def put(self, value):
# public method to put a new value
if value is self._sentinel:
  raise ValueError("you may not put the sentinel value")
self._put(value)

  def _put(self, value):
# private method accepting any value including the sentinel
# we will use receipt of the sentinel to process the things and
stop  # further acceptance of more things
if value is self._sentinel:
  things = self.things
  self.things = None  # will make the .append blow up
  ... process things here maybe ...
else:
  things.append(value)  ??? self.things.append(value)

  def close(self):
# send the sentinel to indicate no more things
self._put(self._sentinel)

[...]

ps Am I correct that towards the end of your code it should have been
   self.things.append(value)


Yes. I probably let myself be lazy because of the earlier "things = 
self.things" in the "true" branch of the "if", where I did it to keep the 
former value of "things" for processing before scrubbing self.things. Of 
course, that way lies buggy code.


I do occasionally pull various object attributes into local variables for 
performance and readability; when I do that it really should be right at the 
top of the function just after any parameter processing, thus:


 class Foo:
   def method(self, foo, bar):
 things = self.things
 for item in foo:
   things.append(item) # or whatever

There are usually two reasons I would do that ("things = self.things" at the 
top): (a) for readability if I'm going to be saying "things" a lot - 
"self.things" may be cumbersome/wordy, making the code very verbose or (b) for 
performance.


To the latter: saying "self.things" requires Python to look up the things 
attribute in "self" every time you use it; if you put it into a local variable 
then Python has direct access to it from the function scope - in CPython his is 
very efficient, and likely so in other Python implementations.


Don't forget that because both "self.things" and "things" refer to the same 
list object (in the example earlier) there's no need to have any final 
"self.things = things" because both are acting on the same list.


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


Re: [Tutor] s.insert(i, x) explanation in docs for Python 3.4 confusing to me

2016-01-17 Thread Cameron Simpson

On 17Jan2016 14:50, Alex Kleider  wrote:

Again, a personal thank you.


No worries.


More often than not, when answering one thing, you teach me about
other things.  The 'thing' thing is only the latest.  Of course
I knew that using a name bound to a collection would effect the
contents of the collection but it would never have occurred to me
to use it to advantage as you describe.


Note that it shouldn't be overdone. Pointless optimisation is also a source of 
bugs and obfuscation.


As I remarked, I'll do this for readability if needed or for performance where 
"things" (or whatever) is going to be heavily accessed (eg in a busy loop), 
such that getting-it-from-the-instance might significantly affect the 
throughput. For many things you may as well not waste your time with it - the 
direct expression of the problem is worth it for maintainability.


It is largely if I'm doing something low level (where interpreted or high level 
languages like Python lose because their data abstraction or cost-of-operation 
may exceed the teensy teensy task being performed.


As an example, I'm rewriting some code right now that scans bytes objects for 
boundaries in the data. It is inherently a sequential "get a byte, update some 
numbers and consult some tables, get the next byte ...". It is also heavily 
used in the storage phase of this application: all new data is scanned this 
way.


In C one might be going:

 for (char *cp=buffer; buf_len > 0; cp++, buflen--) {
   b = *cp;
   ... do stuff with "b" ...
 }

That will be efficiently compiled to machine code and run flat out at your 
CPU's native speed. The Python equivalent, which would look a bit like this:


 for offset in range(len(buffer)):
   b = bs[offset]
   ... do stuff with "b" ...

or possibly:

 for offset, b in enumerate(buffer):
   ... do stuff with "b" ...

will inherently be slower because in Python "bs", "b" and "offset" may be any 
type, so Python must do all this through object methods, and CPython (for 
example) compiles to opcodes for a logial machine, which are themselves 
interpreted by C code to decide what to do. You can see that the ratio of 
"implement the Python operations" to the core "do something with a byte" stuff 
can potentially be very large.


At some point I may be writing a C extension for these very busy parts of the 
code but for now I am putting some effort into making the pure Python 
implementation as efficient as I can while keeping it correct. This is an 
occasion when it is worth expending significant effort on minimising 
indirection (using "things" instead of "self.things", etc), because that 
indirection has a cost that _in this case_ will be large compared to the core 
operations.


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


Re: [Tutor] if request.method == 'GET': NameError: global name 'request' is not defined

2016-01-18 Thread Cameron Simpson

On 17Jan2016 20:13, sudipto manna  wrote:

Here is the code snippet:

File#FlaskTest2.py

from flask import Flask


You need to import "request" from flask as well:

 from flask import Flask, request

For others on this list: the Flask framework presents the current web request 
as a thread local global called "request"; simplifies writing handlers as the 
request information is readily available without having to pass it through 
function calls.


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


Re: [Tutor] Simultaneous read and write on file

2016-01-18 Thread Cameron Simpson

On 18Jan2016 16:29, ALAN GAULD  wrote:

On 18/01/16 16:01, Anshu Kumar wrote:

I try below code in python 2.7.10 to first create and write into a file and
then read and write that file but what i get is just a  file with new
content.



with open('test.txt', 'wb+') as f:

... f.write('this is test file.')
... f.write('ok!!!')
...

with open('test.txt', 'wb+') as f:

... a_str = f.read() + 'read the file'
... f.seek(0)
... f.write(a_str)
...


You called f.seek(0) which puts the cursor right back to the start
of the file. Try writing without using the f.seek().


Agreed.


But since you only want to append, it would be better and safer to use
append mode instead.

The + modes are deceptively appealing but they are full of dangers
for precisely the reasons you have discovered(*). You very rarely
need them and you are better opening/closing the file and
using explicit modes to read/write.


But if he wants to mix the modes, he certainly should be experimenting. Having 
a file open for read and write is sometimes useful; I do it myself in certain 
circumstances.


Tip for new players: if you do any .write()s, remember to do a .flush() before 
doing a seek or a read - unlike the C stdio library where the flush is 
automatic in Python the io classes require you to flush written data if you 
read or seek. (You don't have to flush before close, close does that for you.)



(*)Another problem, apart from the risks of overwriting your
data,  is that the + modes will lock the file even while you
are just reading it, which might cause a problem with shared
files)


Only on Windows. On UNIX everything is fine unless you go out of your way to 
make things harder with locking.



I have read in documentation that wb+ mode is for writing and reading. Am i
using wrong mode, should i use rb+ ?


No, you should probably be separately using 'r' to read and 'a'
to append.


Disagree. As far as his question goes, "wb+" is a correct mode for what he is 
trying. Whether it is a sensible approach depends very much on what he is doing 
with his files.


He _may_ be safer opening the file twice - once for "rb" and once for "ab" - 
because he does not have to juggle the modes, but it isn't necessarily what he 
wants.


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


Re: [Tutor] Simultaneous read and write on file

2016-01-18 Thread Cameron Simpson

On 18Jan2016 21:07, ALAN GAULD  wrote:

On 18/01/16 20:43, Cameron Simpson wrote:

The + modes are deceptively appealing but they are full of dangers
for precisely the reasons you have discovered(*). You very rarely
need them and you are better opening/closing the file and
using explicit modes to read/write.


But if he wants to mix the modes, he certainly should be experimenting. Having
a file open for read and write is sometimes useful; I do it myself in certain
circumstances.


Yes and so have I. Maybe twice in 30 years of programming.
It's sometimes necessary but it's much, much harder to get
right and very easy to get wrong, usually with data corruption
as a result.


I may have done it a little more than that; I agree it is very rare. I may be 
biased because I was debugging exactly this last week. (Which itself is an 
argument against mixed rerad/write with one file - it was all my own code and I 
spent over a day chasing this because I was looking in the wrong spot).



So for a beginner I would never encourage it. For an
experienced programmer sure' if there is no other option
(and especially if you have fixed size records where
things get easier).


Tip for new players: if you do any .write()s, remember to do a .flush() before
doing a seek or a read


That's exactly my point. There are so many things you have
to do extra when working in mixed mode. Too easy to treat
things like normal mode files and get it wrong. Experts
can do it and make it work, but mostly it's just not needed.


Yes. You're write - for simplicity and reliability two distinct open file 
instances are much easier.



Disagree. As far as his question goes, "wb+" is a correct mode for what he is
trying. Whether it is a sensible approach depends very much on what he is doing
with his files.


I'm not sure we know what he(?) is trying.
We only know he successfully overwrote his data and
that apparently was not his intention. There are use
cases where it makes sense but in most cases you can
get by just fine without.


Yeah. I think I was more narked by your not answering his "is wb+ correct" 
literally; it may be only rarely the reasonable course, but for what he was 
actually _asking_ wb+ is correct. He may not be doing the best design but as 
you say we don't know his actual use case.


For the narkiness I apologise.

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


Re: [Tutor] Simultaneous read and write on file

2016-01-18 Thread Cameron Simpson

On 18Jan2016 22:29, Peter Otten <__pete...@web.de> wrote:

Anshu Kumar wrote:

I have read in documentation that wb+ mode is for writing and reading. Am
i using wrong mode, should i use rb+ ?


Quoting https://docs.python.org/2.7/library/functions.html#open
"""
note that 'w+' truncates the file.
"""
That's why you lose the file's current content, and, yes, "r+b" would avoid
that.


And I stand corrected; I should have paid more attention. Thanks!

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


Re: [Tutor] Simultaneous read and write on file

2016-01-18 Thread Cameron Simpson

On 18Jan2016 20:41, Martin A. Brown  wrote:

Yes and so have I. Maybe twice in 30 years of programming. [...]


I may have done it a little more than that; I agree it is very
rare. I may be biased because I was debugging exactly this last
week. (Which itself is an argument against mixed rerad/write with
one file - it was all my own code and I spent over a day chasing
this because I was looking in the wrong spot).


Oh yes.  Ooof.  Today's decisions are tomorrow's albatross.


Actually I have good reason to mix these in this instance, and now that it is 
debugged it is reliable and more efficient to boot.


[...]

Tip for new players: if you do any .write()s, remember to do a
.flush() before doing a seek or a read


That's exactly my point. There are so many things you have to do
extra when working in mixed mode. Too easy to treat things like
normal mode files and get it wrong. Experts can do it and make it
work, but mostly it's just not needed.


Yes. You're write - for simplicity and reliability two distinct
open file instances are much easier.


Yes, he's write [sic].  He writes a bunch!  ;)


Alas, I have a tendency to substitute homophones, or near homophones, when 
typing in a hurry. You'll see this in a bunch of my messages. More annoyingly, 
some are only visible when I reread a posted message instead of when I was 
proofreading prior to send.



[Homonyms mess me up when I'm typing, all sew.]


Homonyms too.

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


Re: [Tutor] Why do I not get an error when I mistakenly type "humdrum.sigh_strenght" instead of the correct "humdrum.sigh_strength"?

2016-01-20 Thread Cameron Simpson

On 20Jan2016 22:34, boB Stepp  wrote:

My intent was to deliberately introduce an error into my class definition:


class Hmm(object):

   def __init__(self, sigh_type, sigh_strength):
   self.sigh_type = sigh_type
   self.sigh_strength = sigh_strength
   def snort(self):
   if self.sigh_strength == 'low':
   print("snort")
   elif self.sigh_strength == 'med':
   print("Snort!")
   elif self.sigh_strenght == 'high':
   print("SNORT!!!")
   else:
   print("Hmm...")
   def sigh():
   if self.sigh_type == 'quiet':
   print("pss")
   elif self.sigh_type == 'annoying':
   print("Whoosh!")
   elif self.sigh_type == 'loud':
   print("HEAVY SIGH!!!")
   else:
   print("HMM!!!")

I omitted "self" from the sigh() method to see what would happen plus
some other things.


Well... You've bound a function accepting no arguments to the "sigh" attribute 
of the class. Legal. Nonsensical perhaps, but legal.



humdrum = Hmm('quiet', 'low')
humdrum.snort()

snort

humdrum.sigh_strength = 'med'
humdrum.snort()

Snort!

humdrum.sigh_strenght = 'high'
humdrum.snort()

Snort!

At this point I wondered why my output was not "SNORT!!!".  Then I
noticed my typo.  But now I wonder why I did not get an error from
this typo?


Because your "if" statement matched the "med". So it never tried to look up 
"self.sigh_strenght".



humdrum.sigh_strength = 'high'
humdrum.snort()

SNORT!!!


Again, as you expected, yes?


humdrum.sigh()

Traceback (most recent call last):
 File "", line 1, in 
   humdrum.sigh()
TypeError: sigh() takes 0 positional arguments but 1 was given

This was my original point in doing all of this, to see what would
result if I omitted "self".  I am pretty sure the error is because the
object instance gets automatically passed to the sigh() method, but by
leaving the "self" parameter out in the method definition, I have a
mismatch between what was defined (0 parameters) and what was passed
to the method (1 argument).


Correct.


humdrum.sigh_strenght

'high'

But what about this?  It seems like I can use the humdrum arguments
outside of the Hmm class and merrily define new variables.  Why is
this?  Is this potentially useful behavior?


"humdrum" is just an object. You can assign attibutes to it at any time.

The code executing inside the class is no different to the code outside the 
class; Python is a dynamic language and you can do this stuff at any time.


It isn't _specificly_ useful to assign an attribute long after its normal 
initialisation, but it can be quite useful. But consider your initialiser:



   def __init__(self, sigh_type, sigh_strength):
   self.sigh_type = sigh_type
   self.sigh_strength = sigh_strength


By the time __init__ is called, the object already exists with a type/class and 
everything. All __init__ is doing is what you find unexpected later; defining 
new attribute values not there before. The only thing special about __init__ is 
that it is called automatically after an object is created. But that is all.


This is not a static language, and __init__ is not defining what 
fields/attributes the object possesses. It is merely setting some of them. It 
is executable code, not a static type definition.


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


Re: [Tutor] Why is the name "self" optional instead of mandatory?

2016-01-20 Thread Cameron Simpson

On 20Jan2016 21:42, boB Stepp  wrote:

I'm whizzing along in "Python Crash Course" and am in the chapter on
classes.  Just to satisfy my suspicion that "self" is just a
placeholder for creating an object instance,


No, it is a placeholder for a _preexiting_ object instance.

[...]

So I really only have one question:  Why not make Python's
*traditional* name, "self", mandatory?  Why give the programmer this
kind of choice?  [OK, that was two questions.]


Why make it mandatory? What benefit would it bring? Remember, one can write 
nonsense or impossible to read gibberish in any language; most people don't try 
to. So to repeat my question: why make it mandatory?


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


Re: [Tutor] Why do I not get an error when I mistakenly type "humdrum.sigh_strenght" instead of the correct "humdrum.sigh_strength"?

2016-01-22 Thread Cameron Simpson

On 22Jan2016 22:14, boB Stepp  wrote:

On Thu, Jan 21, 2016 at 4:57 AM, Steven D'Aprano  wrote:

Danny is correct. And it is a useful feature too. For instance, we can
add attributes to functions:

def spam(x, y):
...

spam.extra_info = "whatever"


A new thing that I did not suspect I could do.  This bothers me for two reasons:

   1)  It does not seem right adding attributes to functions outside
of its definition.


Have you tried to do it from inside? Anyway, a function is just another object. 
What do you think it should be particularly special?



   2)  spam.extra_info appears to be global:


spam.extra_info = "whatever"
z = 'WOW!'
def print_global_stuff():

   print('z =', z)
   print('spam.extra_info =', spam.extra_info)


No, "spam" is global. So you can name it anywhere in that module; therefore you 
can name anything inside it. Again, like any other object.



print_global_stuff()

z = WOW!
spam.extra_info = whatever

And I imagine I am being dense about something that is quite obvious
to you:  How is this a useful feature to have?  What does it give me
that is more useful than just saying something like:

just_another_global variable = "whatever"


spam.extra_info = "blah"
snot = spam
print(snot.extra_info)

Consider if you passed "snot" (or "spam") to a function:

 def print_extra_info(obj):
   print(obj.extra_info)

This is not something you could do with just_another_global_variable.

Consider: this is information you want assicated with a specific object.  
Therefore it really _is_ an arribute of the object so that it can follow it 
around.



And what bothered me about my original example that started this
thread is that when my typo

humdrum.sigh_strenght = 'high'

was accepted and did not generate an error, it seemed to mean to me
that I was violating my object's data encapsulation.  It just seems to
me that I should not be able to arbitrarily add new attributes from
outside the class definition that created my object.  That seems
similar to having a class Dog, to which from outside the class'
definition, I decide to add a new Dog attribute that all dogs in this
class can now have a tail sticking out of their noses.  I have no
qualms about subclassing Dog with a MutantDog subclass, but adding new
attributes from outside the class definition?  That just does not seem
right to at this point of my understanding.  As in your function
example, I am sure that I am missing something quite obvious, but I am
just not seeing it now.


All you're missing is realising that setting an attribute is not a special 
operation.


To take an anecdote from elsewhere:

 UNIX was not designed to stop you from doing stupid things, because that 
 would also stop you from doing clever things.   - Doug Gwyn


There's no need to prevent you setting "sigh_strenght". There probably is 
benefit in linting tools reporting to you about attributes which are set but 
apparently never used.


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


Re: [Tutor] Why do I not get an error when I mistakenly type "humdrum.sigh_strenght" instead of the correct "humdrum.sigh_strength"?

2016-01-23 Thread Cameron Simpson

On 23Jan2016 01:52, boB Stepp  wrote:

On Fri, Jan 22, 2016 at 11:04 PM, Cameron Simpson  wrote:

On 22Jan2016 22:14, boB Stepp  wrote:
All you're missing is realising that setting an attribute is not a special
operation.


I guess no matter how new one is to OOP, one nevertheless brings one's
preconceptions, however malformed, into the learning process.  In my
case, one of mine was that once a class is coded, any given instance
of a class is forevermore responsible for managing its *internals*, so
that any change in these would be managed by the object when one of
its (meant to be) publicly available methods is called.


That is the pure OO way; and you can do things that way in Python, though you 
can't _prevent_ direct access.  However, it isn't the common way with Python; 
generally with a Python class there are public attributes with ordinary names; 
outsiders can consult them but generally should not change them unless the doco 
says that is ok. "Internal" attributes which outsiders should not touch are 
general givens names starting with an underscore so that outsiders can know.



In the case
of attributes, I was thinking/expecting something like the following
would have to be done:


class Dog(object):

   def __init__(self, name, breed):
   self.name = name
   self.breed = breed
   self.number_legs = 4
   self.number_tails = 1
   self.number_eyes = 2
   self.attributes = {
   'name': self.name,
   'breed': self.breed,
   'number of legs': self.number_legs,
   'number of tails': self.number_tails,
   'number of eyes': self.number_eyes}

   def add_attribute(self, new_attribute_name, new_attribute_value):
   self.new_attribute_name = new_attribute_name
   self.new_attribute_value = new_attribute_value
   self.attributes[self.new_attribute_name] = self.new_attribute_value

   def show_attributes(self):
   print("The object,", self.name, "has the following attributes:")
   for attribute_name, attribute_value in self.attributes.items():
   print(attribute_name, "=", attribute_value)


our_dog = Dog('Copper', 'beagle')
our_dog.show_attributes()

The object, Copper has the following attributes:
number of tails = 1
number of legs = 4
breed = beagle
name = Copper
number of eyes = 2

our_dog.add_attribute('unique marking', 'blue right eye')
our_dog.show_attributes()

The object, Copper has the following attributes:
number of legs = 4
breed = beagle
unique marking = blue right eye
number of tails = 1
name = Copper
number of eyes = 2

I suspect there are probably better ways to do what I am trying to
demonstrate [I am trying to use a dict to simulate adding new instance
variables after the fact.],


You're aware that most objects have a .__dict__ attribute containing the 
attributes? It is a dict, btw. So:


 class O(object):
   pass

 >>> o=O()
 >>> o.x=1
 >>> o.__dict__
 {'x': 1}


perhaps with built-in functions that I
have not read about yet.  But I hope my code illustrates my previous
expectations.  I guess I was expecting that access to an object's
internals would be more strictly regulated.  But, thinking about it, I
already knew that even if name mangling is done for a method's name,
it can still be directly accessed from outside of that object's class
definition.


Yeah. If you mean .__blah methods and attributes, I used to use them but 
generally don't these days. They're more an aid to avoiding collisions when 
subclassing to my mind, but they're not bulletproff and the implicit mangling 
makes for confusion in my mind.



But if I am understanding everyone's comments correctly, Python allows
me write my classes in such a way, that public access to my object's
internals is controlled, in the sense that Python has coding
conventions that tell all of the quite intelligent, respectful,
consenting adults that might use my code how I intend that code to be
used.  And that I, despite my intentions, must respect that users of
my code may have very valid reasons for deviating from my intentions.
Have I captured the Pythonic spirit of what everyone has been trying
to tell me?


Pretty much.

Alan will take you up on doing purer OO practices in Python.

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


Re: [Tutor] Why do I not get an error when I mistakenly type "humdrum.sigh_strenght" instead of the correct "humdrum.sigh_strength"?

2016-01-23 Thread Cameron Simpson

On 23Jan2016 12:55, boB Stepp  wrote:

On Sat, Jan 23, 2016 at 3:30 AM, Cameron Simpson  wrote:

On 23Jan2016 01:52, boB Stepp  wrote:

I guess no matter how new one is to OOP, one nevertheless brings one's
preconceptions, however malformed, into the learning process.  In my
case, one of mine was that once a class is coded, any given instance
of a class is forevermore responsible for managing its *internals*, so
that any change in these would be managed by the object when one of
its (meant to be) publicly available methods is called.


That is the pure OO way; and you can do things that way in Python, though
you can't _prevent_ direct access.  However, it isn't the common way with
Python; generally with a Python class there are public attributes with
ordinary names; outsiders can consult them but generally should not change
them unless the doco says that is ok...


I'd like to focus on this last sentence.  Are you suggesting that it
is "better" programming practice to code the class so that it has its
own publicly available methods to process its public attributes?


No, I'm suggesting that in a pure OO system, your only access to the internal 
state of an object is via .get_thing() methods and the only way to set them is 
via .set_thing(value) methods. In a system where outsiders cannot access 
internal attributes, that provides a completely opaque layer where the object 
mediates these actions to ensure correctness and where the internals are 
invisible, allowing a complete change of implementation without breaking the 
interface outsiders use.



And
that it is both good practice and Pythonic to allow outsiders to
freely read public attributes as needed?


Generally yes. As the author of the class, you need to decide what should be 
visible (meaning "not have a leading underscore"). Of course it is _all_ 
visible, but when you give something a "public" name you are quietly implying 
to outsiders that this is stable, and future implementations will continue to 
preserve it.


You can be totally conservative of course and give all the internal state ._* 
names. But an object with no attributes is generally not as useful. Note that 
there's a grey area here: plenty of objects have methods which return values:


 class O(object):
   def __init__(self, name):
 self._name = name
   def name(self):
 return self._name

 o = O("foo")
 print(o.name())

so you can keep the state "private" while presenting useful information via 
methods. By having .name be a function, you are free to reimplement the class 
using anther mechanism and outsiders will not have to change how they use 
things:


 class O(object):
   def __init__(self, name):
 # make a row in a database associating our id with this name
 db.set_name(id(self), name)
   def name(self):
 # fetch the name back out of the database
 n = db.get_name_by_id(id(self))
 return n


I suspect there are probably better ways to do what I am trying to
demonstrate [I am trying to use a dict to simulate adding new instance
variables after the fact.],


You're aware that most objects have a .__dict__ attribute containing the
attributes? It is a dict, btw. So:

 class O(object):
   pass

 >>> o=O()
 >>> o.x=1
 >>> o.__dict__
 {'x': 1}


The book I am currently working through, "Python Crash Course",
despite its title, is oriented towards beginners to programming.  It
does not cover dunder methods and attributes, other than __init__().
I am aware from following this list and reading portions of other
books, that they exist, but I have not gotten into the details of any
of them.  So rewriting my class to use .__dict__, I have gotten:


class Dog(object):

   def __init__(self, name, breed):
   self.name = name
   self.breed = breed
   self.number_legs = 4
   self.number_tails = 1
   self.number_eyes = 2
   def show_attributes(self):
   print("The object,", self.name, "has the following attributes:")
   for attribute_name, attribute_value in self.__dict__.items():
   print(attribute_name, "=", attribute_value)


our_dog = Dog('Copper', 'beagle')
our_dog.show_attributes()

The object, Copper has the following attributes:
number_tails = 1
number_eyes = 2
breed = beagle
number_legs = 4
name = Copper

our_dog.unique_marking = 'blue right eye'   # Adding a new attribute from 
outside the class definition.
our_dog.show_attributes()

The object, Copper has the following attributes:
number_eyes = 2
breed = beagle
unique_marking = blue right eye
number_tails = 1
number_legs = 4
name = Copper

I have to say that this seems very simple and direct despite my
initial reluctance to assign new attributes to an object from outside
the class definition of that object.


Yes. No magic here, just expos

Re: [Tutor] Why do I not get an error when I mistakenly type "humdrum.sigh_strenght" instead of the correct "humdrum.sigh_strength"?

2016-01-23 Thread Cameron Simpson

On 23Jan2016 16:25, boB Stepp  wrote:

On Sat, Jan 23, 2016 at 12:55 PM, boB Stepp  wrote:

I still would like to do this via a method, but I am currently stuck
on how to replace ??? with the attribute name I would like to insert:

class Dog(object):
...

def add_attribute(self, attribute_name, attribute_value):
self.??? = attribute_value

If I write something like:

unique_marking = 'blue right eye'
our_dog.add_attribute(unique_marking, 'blue right eye)

I cannot get ??? to be unique_marking.  Instead, show_attributes()
will give from .__dict__, 'attribute_name', instead of what I would
like to replace it with, unique_marking.  But I have not given up yet!


I think I now have this nuked out.  I am only just now realizing how
powerful .__dict__ is:

[... working code ...]


Wow!  So much power for so little code!


Sure. But also note that in the real world you will hardly ever work on 
.__dict__ directly. If I were collecting a lot of _arbitrary_ features like 
.unique_marking I would put them all in some internal attribute:


 class Dog(object):
   def __init__(self, name):
 self.name = name
 self.features = {}
   def add_feature(self, feature_name, feature_value):
 self.features[feature_name] = feature_value

(Note, deliberately avoiding the term "attribute" here.)

Also, Python provideds the functions setattr and getattr to _avoid_ directly 
accessing .__dict__:


 setattr(self, attribute_name, attribute_value)

because not all objects use .__dict__ to store this stuff. Generally the dunder 
names are to be avoided: not that they should never be used, but they tend to 
be mechanism which has "public" exposure elsewhere, eg __dict__ vs 
getattr/setattr. For exactly the same reason as other OO stuff: because the 
internal implementation is not always __dict__.


So you might access __dict__ internally for introspection, but you would more 
commonly use getattr (and outsiders should _always_ use getattr!) Or, of 
course, if the attribute name is known at coding time, with the better .name 
syntax:


 v = dog.__dict__['unique_feature']
 v = getattr(dog, 'unique_feature')
 v = dog.unique_feature

from least desired to most desired. BTW, when the attribute exists these all 
return the same thing, but when the attribute does no exist they all raise 
different kinds of exception.


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


Re: [Tutor] 2016-02-01 Filter STRINGS in Log File and Pass as VARAIBLE within PYTHON script

2016-02-01 Thread Cameron Simpson

On 01Feb2016 15:53, knnleow GOOGLE  wrote:

trying out on how to port my unix shell script to python.
get more complicated than i expected.: (
i am not familiar with the modules available in python.
anyone care to share how to better the clumsy approach below.
regards,
kuenn

   timestamp02 = time.strftime("%Y-%m-%d-%H%M%S")
   banIPaddressesFile = os.popen("cat 
/var/log/fail2ban.log| egrep ssh| egrep Ban| egrep " + myDate + "| awk 
\'{print $7}\'| sort -n| uniq >/tmp/banIPaddressesFile." + 
timestamp02).read()


First up, this is still essentially a shell script. You're constructing a shell 
pipeline like this (paraphrased):


 cat >/var/log/fail2ban.log
 | egrep ssh
 | egrep Ban
 | egrep myDate
 | awk '{print $7}'
 | sort -n
 | uniq 
 >/tmp/banIPaddressesFile-timestamp


So really, you're doing almost nothing in Python. You're also writing 
intermediate results to a temporary filename, then reading from it. Unless you 
really need to keep that file around, you won't need that either.


Before I get into the Python side of things, there are a few small (small) 
criticisms of your shell script:


- it has a "useless cat"; this is a very common shell inefficiency there people 
 put "cat filename | filter1 | filter2 ..." when they could more cleanly just 
 go "filter1 

- you are searching for fixed strings; why are you using egrep? Just say "grep" 
 (or even "fgrep" if you're old school - you're new to this so I presume not)


- you're using "sort -n | uniq", presumably because uniq requires sorted input; 
 you are better off using "sort -un" here and skipping uniq. I'd also point 
 out that since these are IP addresses, "sort -n" doesn't really do what you 
 want here.


So, to the Python:

You seem to want to read the file /var/log/fail2ban.log and for certain 
specific lines, record column 7 which I gather from the rest of the code 
(below) is an IP address. I gather you just want one copy of each unique IP 
address.


So, to read lines of the file the standard idom goes:

 with open('/var/log/fail2ban.log') as fail_log:
   for line in fail_log:
 ... process lines here ...

You seem to be checking for two keywords and a date in the interesting lines.  
You can do this with a simple test:


 if 'ssh' in line and 'Ban' in line and myDate in line:

If you want the seventh column from the line (per your awk command) you can get 
it like this:


 words = line.split()
 word7 = words[6]

because Python arrays count form 0, therefore index 6 is the seventh word.

You want the unique IP addresses, so I suggest storing them all in a set and 
not bothering with a sort until some other time. So make an empty set before 
you read the file:


 ip_addrs = set()

and add each address to it for the lines you select:

 ip_addrs.add(word7)

After you have read the whole file you will have the desired addresses in the 
ip_addrs set.


Try to put all that together and come back with working code, or come back with 
completed but not working code and specific questions.


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


  1   2   3   4   >