Re: [Tutor] Unit testing: Just the API or internal use only methods, too?

2019-07-16 Thread Mats Wichmann
On 7/16/19 4:41 PM, boB Stepp wrote:
> Peter Otten, while responding to one of my questions in the past,
> mentioned something in passing that apparently has been mulling around
> in the back of my head.  I don't recall his exact words, but he
> essentially said that I should be testing the public interface to my
> classes, but not the methods only used internally by the class and not
> meant to be publicly accessible.  Is this generally how I should be
> viewing testing?  Would someone be willing to expand at some length on
> this topic?

Test everything (within reason).

If you practice TDD, say, where your tests are the contract for how an
interface shall behave, that makes a lot more sense for public APIs,
which shall not change or be flagged immediately by your unit tests,
than for internal functions which should be able to change within reason
to suit implementation needs.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] raising exceptions in constructor code?

2019-07-16 Thread Cameron Simpson

On 16Jul2019 23:49, Alan Gauld  wrote:

On 16/07/2019 22:56, Mats Wichmann wrote:
thrown.  This gets watered down to the mantra "Don't throw 
exceptions from

within constructors."  Does this carry over to Python?


If you mean __init__, that's not a constructor, so you should set your
mind at rest :)   It's more properly an "initializer", the instance has
already been constructed when it's called.


FWIW The true constructor is __new__() and its quite rarely overridden
by application programmers. But if you do, it's not common that you'd do
anything that would merit an exception. __new__ pretty much just sets
up the structure of the object ready for initialisation by __init__.

Incidentally, this two stage construction/initialisation is also found
in other OOP languages like Smalltalk and Objective C (and Lisp?).


And to return to the OP's question:

The __init__ method (and arguably __new__ if you touch it - very rare) 
is like other Python code: resource allocation should normally get 
unwound as objects become unreferenced. So raising an exception should 
be a pretty safe thing to do.


That is a simplification. Of course if you implement an object with side 
effects _outside_ the Python object space (maybe it opened a scratch 
file to support something), it is your responsibility to ensure release 
in the object's __del__ method. But an object that just allocates a 
bunch of lists or dicts or the like? Python will clean that up for you.


That said, I try to do cheap initialisation before exspensive 
initialisation. So allocating locks, opening files, starting worker 
threads: these come at the bottom of the __init__ method.


Also, it is _ROUTINE_ to raise exceptions from __init__: like any other 
method we _expect_ you to raise ValueError if the initialiser parameters 
are insane (negatively sized arrays, etc etc).


So in Python, raising exceptions in __init__ is normal: it shouldn't 
happen when you programme is running correctly of course, but it is the 
_preferred_ action when your initialiser cannot complete correctly.


Consider:

 x = Foo()

After this assignment we expect "x" to be a usable instance of Foo. We 
don't put special checks; what would such checks look like? (There are 
some answers for that, but they're all poor.)


So raising an exception is what happens if __init__ fails.

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


Re: [Tutor] raising exceptions in constructor code?

2019-07-16 Thread Steven D'Aprano
On Tue, Jul 16, 2019 at 04:29:15PM -0500, James Hartley wrote:
> I ask this having more C++ knowledge than sense.
> 
> There is an adage in the halls of everything Stroustrup that one needs to
> think about how resource allocation will be unwound if an exception is
> thrown.  This gets watered down to the mantra "Don't throw exceptions from
> within constructors."  Does this carry over to Python?  I'm trying to
> develop a Pythonistic mindset as opposed to carrying over old baggage...

No, it is perfectly safe to raise exceptions from within the Python 
constructors, whether you are using __new__ (the true constructor) or 
__init__ (the initialiser).

The only tricky part is if you allocate resources external to the 
object, like this:


class Weird(object):
openfiles = []
def __new__(cls, fname):
f = open(fname)
cls.openfiles.append(f)
# New instance:
instance = super().__new__(cls)
if condition:
raise ValueError
return instance


Even if the __new__ constructor fails, I've kept a reference to an open 
file in the class. (I could have used a global variable instead.) That 
would be bad. But notice I had to work hard to make this failure mode, 
and write the code in a weird way. The more natural way to write that^1 
would be:

class Natural(object):
def __init__(self, fname):
self.openfile = open(fname)
if condition:
raise ValueError

Now if there is an exception, the garbage collector will collect the 
instance and close the open file as part of the collection process. 
That might not be immediately, for example Jython might not close the 
file until interpreter shutdown. But the earlier example will definitely 
leak an open file, regardless of which Python interpreter you use, while 
the second will only leak if the garbage collector fails to close open 
files.


Here's a better example that doesn't depend on the quirks of the garbage 
collector:

class Leaky(object):
instances = []
def __init__(self):
self.instance.append(self)
if random.random() < 0.1:
raise ValueError

This will hold onto a reference to the instance even if the initialiser 
(constructor) fails. But you normally wouldn't do that.

class NotLeaky(object):
def __init__(self):
if random.random() < 0.1:
raise ValueError


try:
x = NotLeaky()
except ValueError:
pass


Now either the call to NotLeaky succeeds, and x is bound to the 
instance, or it fails, and x is *not* bound to the instance. With no 
references to the newly-created instance, it will be garbage collected.




^1 Actually that's not too natural either. It is not usually a good idea 
to hold onto an open file when you aren't actively using it, as the 
number of open files is severely constrained on most systems. 



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


Re: [Tutor] Unit testing: Just the API or internal use only methods, too?

2019-07-16 Thread Alan Gauld via Tutor
On 16/07/2019 23:41, boB Stepp wrote:

> essentially said that I should be testing the public interface to my
> classes, but not the methods only used internally by the class and not
> meant to be publicly accessible.  

I suspect he meant that you should publish the tests for the API
but not necessarily for the internal/private methods.

You should definitely test all code you write, but how formally
you test the private stuff is up to you. But publishing the
public API tests allows clients to run them too.


-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


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


Re: [Tutor] raising exceptions in constructor code?

2019-07-16 Thread Alan Gauld via Tutor
On 16/07/2019 22:56, Mats Wichmann wrote:

>> thrown.  This gets watered down to the mantra "Don't throw exceptions from
>> within constructors."  Does this carry over to Python?  

> 
> If you mean __init__, that's not a constructor, so you should set your
> mind at rest :)   It's more properly an "initializer", the instance has
> already been constructed when it's called.

FWIW The true constructor is __new__() and its quite rarely overridden
by application programmers. But if you do, it's not common that you'd do
anything that would merit an exception. __new__ pretty much just sets
up the structure of the object ready for initialisation by __init__.

Incidentally, this two stage construction/initialisation is also found
in other OOP languages like Smalltalk and Objective C (and Lisp?).

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


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


[Tutor] Unit testing: Just the API or internal use only methods, too?

2019-07-16 Thread boB Stepp
Peter Otten, while responding to one of my questions in the past,
mentioned something in passing that apparently has been mulling around
in the back of my head.  I don't recall his exact words, but he
essentially said that I should be testing the public interface to my
classes, but not the methods only used internally by the class and not
meant to be publicly accessible.  Is this generally how I should be
viewing testing?  Would someone be willing to expand at some length on
this topic?

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


[Tutor] How would I replace the data of a Pandas Series with the values of a dictionary?

2019-07-16 Thread Daniel Bosah
Hi all,

I have a problem trying to match items in a dict and pandas series in
Python.

I have a dict ( called city_dict )of cities and city_id's ; for each city (
which is a key in the dict ), a unique city_id is a value in that dict.

So for example, city_dict = { New York : 1001, LA : 1002, Chicago : 1003 }.
New York is a key, 1001 is a value.

Now I have a panda Series called dfCities. In this series is a bunch of
cities, including the cities in city_dict.

My goal is to replace the cities in dfCities with the city_id's in a brand
new csv file. So if dfCities has New York in it, I want to replace it with
it's value in the dictionary, so 1001.


Approaches I've tried - checking to see if the keys  match the cities in
dfCities in a  'if in' statement ( such as "if city_dict.keys() in
dfSeries"), and then doing a straight replace ( can't do that since series
are ambiguous in truth values).  Therefore I tried using .any() for Pandas
series (since .all() would strictly want all values in dfCities to match,
and all values don't match )

Afterwards, tried to directly match the series with keys and the clarified
truth value series, but dict_keys are unhashable, so I had to convert the
keys to str and see if I could compare strings ( with a stringified
dfCities )

Then I realized that even if I can get a if statement to start checking
(if dfCities.str.contains(keyss).any(): ) (keyss being the stringified
version of the keys for city_dict ), I don't know how to build a approach
to cross check the values of city_dict with the cities in dfCities ( I have
a vague notion that I should check if the keys of city_dict match with
dfCities, and then replace the cities in dfCities with the values of
city_dict in a new csv file output. However, I don't know how to replace
data in a Series with vaues of a dict ).

So I would like to ask the community what approach I can take to build to
that piece of the puzzle. I feel I have most of the solution, but I'm
missing something.

Thanks for reading and I appreciate the help.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] raising exceptions in constructor code?

2019-07-16 Thread Mats Wichmann
On 7/16/19 3:29 PM, James Hartley wrote:
> I ask this having more C++ knowledge than sense.
> 
> There is an adage in the halls of everything Stroustrup that one needs to
> think about how resource allocation will be unwound if an exception is
> thrown.  This gets watered down to the mantra "Don't throw exceptions from
> within constructors."  Does this carry over to Python?  I'm trying to
> develop a Pythonistic mindset as opposed to carrying over old baggage...

If you mean __init__, that's not a constructor, so you should set your
mind at rest :)   It's more properly an "initializer", the instance has
already been constructed when it's called.


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


[Tutor] raising exceptions in constructor code?

2019-07-16 Thread James Hartley
I ask this having more C++ knowledge than sense.

There is an adage in the halls of everything Stroustrup that one needs to
think about how resource allocation will be unwound if an exception is
thrown.  This gets watered down to the mantra "Don't throw exceptions from
within constructors."  Does this carry over to Python?  I'm trying to
develop a Pythonistic mindset as opposed to carrying over old baggage...

Thanks!

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


Re: [Tutor] Reading .csv data vs. reading an array

2019-07-16 Thread Peter Otten
Chip Wachob wrote:

> I tried it anyhow, with this being an example of my source data:
> 
> "Record Length",202,"Points",-0.005640001706,1.6363
> "Sample Interval",5e-09,s,-0.005639996706,1.65291
> "Trigger Point",1128000,"Samples",-0.005639991706,1.65291
> "Trigger Time",0.341197,s,-0.005639986706,1.60309
> ,,,-0.005639981706,1.60309
> "Horizontal Offset",-0.00564,s,-0.005639976706,1.6363
> ,,,-0.005639971706,1.65291
> ,,,-0.005639966706,1.65291
> ,,,-0.005639961706,1.6363
> .
> .
> .
> 
> Note that I want the items in the third and fourth column of the csv file
> for my time and voltage.
> 
> When I tried to use the unpack, they all came over as strings.  I can't
> seem to convert them selectively..

Try wrapping the reader like this:

 $ cat custom_reader.py
import csv
import io

data = """\
"Record Length",202,"Points",-0.005640001706,1.6363
"Sample Interval",5e-09,s,-0.005639996706,1.65291
"Trigger Point",1128000,"Samples",-0.005639991706,1.65291
"Trigger Time",0.341197,s,-0.005639986706,1.60309
,,,-0.005639981706,1.60309
"Horizontal Offset",-0.00564,s,-0.005639976706,1.6363
,,,-0.005639971706,1.65291
,,,-0.005639966706,1.65291
,,,-0.005639961706,1.6363
"""

def maybe_float(s):
try:
return float(s)
except ValueError:
return s

def myreader(*args, **kw):
reader = csv.reader(*args, **kw)
for row in reader:
yield [maybe_float(field) for field in row]

for row in myreader(io.StringIO(data)):
print(row)

$ python3 custom_reader.py 
['Record Length', 202.0, 'Points', -0.005640001706, 1.6363]
['Sample Interval', 5e-09, 's', -0.005639996706, 1.65291]
['Trigger Point', 1128000.0, 'Samples', -0.005639991706, 1.65291]
['Trigger Time', 0.341197, 's', -0.005639986706, 1.60309]
['', '', '', -0.005639981706, 1.60309]
['Horizontal Offset', -0.00564, 's', -0.005639976706, 1.6363]
['', '', '', -0.005639971706, 1.65291]
['', '', '', -0.005639966706, 1.65291]
['', '', '', -0.005639961706, 1.6363]

If you find that performance suffers more than you are willing to accept 
here's an alternative implementation of maybe_float() that may be faster for 
some inputs:

def maybe_float(s):
if s and s[:1] in " 0123456789+-":
try:
return float(s)
except ValueError:
return s
return s


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


Re: [Tutor] Object references in Python

2019-07-16 Thread Mats Wichmann
On 7/16/19 2:33 PM, Steven D'Aprano wrote:

> x = Parrot()
> 
> Now x is a reference to a Parrot instance. y remains a reference to the 
> list.
> 
> x.colour is a reference to the string "blue" (by default).
> 
> x.speak is a reference to the "speak" method of Parrot objects.
> 
> 
> 
> Does this help?
> 
> 
> 

Let's add one more little cute one for good measure:

>>> def foo():
... print("This function does Foo")
...
>>> foo()
This function does Foo
>>> # we created a function object, and foo is a reference to it
...
>>> x = foo
>>> # x should be a reference to the same object
...
>>> x()
This function does Foo
>>> x is foo
True
>>> def foo():
... print("This function no longer Foos")
...
>>> # we created a new function object, and foo is now a reference to it
...
>>> foo()
This function no longer Foos
>>> x()
This function does Foo
>>> # x is still a reference to the original function object
...
>>> x is foo
False
>>>
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Object references in Python

2019-07-16 Thread Steven D'Aprano
On Tue, Jul 16, 2019 at 12:08:10PM +, AHIA Samuel wrote:

> Please what are references in Python development?

x = 19
y = x

The name "x" is a reference to the int 19; the name y is a reference to 
the same int.

x = "Hello world"

Now the name "x" is a reference to the string "Hello world". y remains a 
reference to the int 19.

x = None

Now the name "x" is a reference to the None object.

x = [100, 200, 300]

Now the name "x" is a reference to a list with three items:

- The first item of x, x[0], is a reference to the int 100.
- The second item of x, x[1], is a reference to the int 200.
- The third item of x, x[2], is a reference to the int 300.

y = x

Now y is no longer a reference to the int 19 as before, but is a 
reference to the same list that x is a reference to. There are now two 
references to the list object: x and y.

(If you are a C programmer, you can think of x and y both being pointers 
to the same list. This is not completely correct, but it isn't far 
wrong.)

Since x and y are references to the same list, we can equally say:

- The first item of y, y[0], is a reference to the int 100.
- The second item of y, y[1], is a reference to the int 200.
- The third item of y, y[2], is a reference to the int 300.

x.append(None)

Now the name x is still a reference to the same list as before, except 
that we have added a new item to the end of the list:

- The fourth item of x, x[3], is a reference to the None object.
- The fourth item of y, y[3], is a reference to the None object.

Since both x and y are references to the same list, any change to the x 
list is a change to the y list (since they are the same).


class Parrot:
def __init__(self, colour="blue"):
self.colour = colour
def speak(self):
 print("Polly wants a cracker!")


Now the name "Parrot" is a reference to the class "Parrot".

x = Parrot()

Now x is a reference to a Parrot instance. y remains a reference to the 
list.

x.colour is a reference to the string "blue" (by default).

x.speak is a reference to the "speak" method of Parrot objects.



Does this help?



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


Re: [Tutor] Impersonation

2019-07-16 Thread Jim

On 7/15/19 9:36 PM, Jim wrote:

Mats,

Hopefully you recognize my email address as someone you have given 
advice concerning Python.


Over the last month or so I have received at least 3 emails supposedly 
coming from you that I am sure you did not send.


The from line is:  Mats Wichmann 

The body is: On Monday, July 15, 2019 10:36 AM, Mats Wichmann wrote:
Hope you are well. Just wanted to share something with you 
http://www.bt6q.lnhaxf.info/


I just wanted you to know that it seems someone is trying to impersonate 
you.


Regards,  Jim



My apologies. I intended that this message go only to Mats.

Regards, Jim


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


Re: [Tutor] Reading .csv data vs. reading an array

2019-07-16 Thread David Rock

> On Jul 16, 2019, at 04:31, Alan Gauld via Tutor  wrote:
> 
> On 16/07/2019 09:59, Oscar Benjamin wrote:
> 
>>> All true, but sed - once you get used to it! - is easier IMHO
>>> and usually faster than Python - it's written in C...
>> 
>> I always think I'll like sed but whenever I actually try to use it I
>> just can't get the syntax together. 
> 
> 
> Id been using awk and sed for 15 years before I discovered
> Python (and perl) so they are kind of second nature.
> 
> If you can't settle with sed try awk, it's much simpler to
> use and almost as powerful but not as fast. I think awk is
> one of the most neglected of the *nix tools now that
> scripting languages like perl/python/ruby exist. But for
> line by line file processing it is superb.

The first O’Reilly book I ever purchased was “Sed & Awk”, and has been one of 
the most invaluable over the last 20 years.  While they are not the simplest 
tools to master, they are worth the effort; especially when you are trying to 
do inline “one-liners” to massage data or process large files.  That doesn’t 
mean it’s a requirement to know them, but it does get easier with practice.  
That said, if making a little python one-off filter to do what you need is 
faster (to write) and works (well enough), it comes down to what your time is 
worth.

— 
David Rock
da...@graniteweb.com




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


[Tutor] Object references in Python

2019-07-16 Thread AHIA Samuel
Please what are references in Python development?
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Reading .csv data vs. reading an array

2019-07-16 Thread Alan Gauld via Tutor
On 16/07/2019 09:59, Oscar Benjamin wrote:

>> All true, but sed - once you get used to it! - is easier IMHO
>> and usually faster than Python - it's written in C...
> 
> I always think I'll like sed but whenever I actually try to use it I
> just can't get the syntax together. 


Id been using awk and sed for 15 years before I discovered
Python (and perl) so they are kind of second nature.

If you can't settle with sed try awk, it's much simpler to
use and almost as powerful but not as fast. I think awk is
one of the most neglected of the *nix tools now that
scripting languages like perl/python/ruby exist. But for
line by line file processing it is superb.

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


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


Re: [Tutor] Reading .csv data vs. reading an array

2019-07-16 Thread Oscar Benjamin
On Tue, 16 Jul 2019 at 01:44, Alan Gauld via Tutor  wrote:
>
> On 15/07/2019 21:28, Mats Wichmann wrote:
>
> > course Python can do that too, by working line-at-a-time, explicitly by
> > calling readlines() or implicitly by looping over the file handle. The
> > latter looks something like this;
> >
> > with open("/path/to/datafile", "r") as f:
> > for line in f:
> > if REDFLAGTEXT in line:  # skip these
> > continue
> > do-something-with line
>
> All true, but sed - once you get used to it! - is easier IMHO
> and usually faster than Python - it's written in C...

I always think I'll like sed but whenever I actually try to use it I
just can't get the syntax together. I do use vim and can do
find/replace there. It seems like every different utility grep, egrep,
sed, vim etc has subtly different escaping rules or maybe I just
haven't got my head around it.

When writing this pull request:
https://github.com/sympy/sympy_doc/pull/32
I spent something like 15 minutes trying to get sed to work before
giving up. It took me 2 minutes to write and run the Python script
that I ended up using.

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