Re: [Tutor] Need help with code

2017-04-17 Thread Alan Gauld via Tutor
On 16/04/17 18:26, Tyler Seacrist wrote:

> I need to draw a stack diagram for print_n 
> called with s = 'Hello' and n=2 and am unsure of how to do so.

Me too.

What is print_n?

Which stack?
One in your program or the interpreters internal stack?

We need a lot more detail.

-- 
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] Do not understand code snippet from "26.8. test — Regression tests package for Python"

2017-04-17 Thread Peter Otten
boB Stepp wrote:

> It is here that I am struggling.  If the mixin class does not inherit
> from unittest.TestCase, then how is test_func ever seen?

Perhaps it becomes clearer if we build our own class discovery / method 
runner system. Given T as the baseclass for classes that provide foo_...() 
methods that we want to run, and M as the mix-in that provides such methods 
but isn't itself a subclass of T...

class T:
pass

class M:
def foo_one(self):
print(self.__class__.__name__, "one")
def foo_two(self):
print(self.__class__.__name__, "one")

class X(T):
def foo_x(self):
print(self.__class__.__name__, "x")

class Y(M, T):
pass

we want our discovery function to find the classes X and Y.
First attempt:

def discover_Ts():
for C in globals().values():
if issubclass(C, T):
print("found", C)


discover_Ts()

globals().values() gives all toplevel objects in the script and issubclass 
checks if we got a subclass of T. Let's try:

$ python3 discovery.py 
Traceback (most recent call last):
  File "discovery.py", line 23, in 
discover_Ts()
  File "discovery.py", line 19, in discover_Ts
if issubclass(C, T):
TypeError: issubclass() arg 1 must be a class

It turns out that issubclass() raises a TypeError if the object we want to 
check is not a class:

>>> issubclass(int, float)
False
>>> issubclass(42, float)
Traceback (most recent call last):
  File "", line 1, in 
TypeError: issubclass() arg 1 must be a class

For our purposes False is the better answer, so let's write our own 
issubclass:

def safe_issubclass(S, B):
try:
return issubclass(S, B)
except TypeError:
return False

def discover_Ts():
for C in globals().values():
if safe_issubclass(C, T):
print("found", C)

$ python3 discovery2.py 
found 
found 
found 

That's close, we only need to reject T:

def discover_Ts():
for C in globals().values():
if safe_issubclass(C, T) and C is not T:
print("found", C)

Easy. Now we have the classes we can look for the methods:

def discover_Ts():
for C in globals().values():
if safe_issubclass(C, T) and C is not T:
print("found", C, "with foo_... methods")
for name in dir(C):
if name.startswith("foo_"):
print("   ", name)

$ python3 discovery4.py 
found  with foo_... methods
foo_x
found  with foo_... methods
foo_one
foo_two

As you can see, to the discovery algorithm it doesn't matter where the 
method is defined, it suffices that it's part of the class and can be found 
by dir() or vars().

As a bonus, now that we have the class and the method let's invoke them:

def discover_Ts():
for C in globals().values():
if safe_issubclass(C, T) and C is not T:
print("found", C, "with foo_... methods")
for name in dir(C):
if name.startswith("foo_"):
yield C, name

def run_method(cls, methodname):
inst = cls()
method = getattr(inst, methodname)
method()

for cls, methodname in discover_Ts():
run_method(cls, methodname)

While you could invoke run_method() inside discover_Ts() I turned 
discover_Ts() into a generator that produces class/methodname pairs which 
looks a bit more pythonic to me. Let's run it:

$ python3 discovery5.py 
found  with foo_... methods
X x
Traceback (most recent call last):
  File "discovery5.py", line 36, in 
for cls, methodname in discover_Ts():
  File "discovery5.py", line 24, in discover_Ts
for C in globals().values():
RuntimeError: dictionary changed size during iteration

Oops, as the global names cls, and methodname spring into existence they 
torpedize our test discovery. We could (and should when we need a moderate 
amount of robustness) take a snapshot of the global variables with 
list(globals().values()), but for demonstration purposes we'll just move the 
toplevel loop into a function:

$ cat discovery6.py 
class T:
pass

class M:
def foo_one(self):
print(self.__class__.__name__, "one")
def foo_two(self):
print(self.__class__.__name__, "two")

class X(T):
def foo_x(self):
print(self.__class__.__name__, "x")

class Y(M, T):
pass

def safe_issubclass(S, B):
try:
return issubclass(S, B)
except TypeError:
return False

def discover_Ts():
for C in globals().values():
if safe_issubclass(C, T) and C is not T:
print("found", C, "with foo_... methods")
for name in dir(C):
if name.startswith("foo_"):
yield C, name

def run_method(cls, methodname):
inst = cls()
method = getattr(inst, methodname)
method()

def main():
for cls, methodname in discover_Ts():
run_method(cls, methodname)

if __name__ == "__main__":
main()
$ python3 discovery6.py 
found  with foo_... methods
Y one
Y two
found  with foo_.

Re: [Tutor] Do not understand code snippet from "26.8. test — Regression tests package for Python"

2017-04-17 Thread Peter Otten
Peter Otten wrote:

> class M:
> def foo_one(self):
> print(self.__class__.__name__, "one")
> def foo_two(self):
> print(self.__class__.__name__, "one")
 
Oops, foo_two() should of course print "two", not "one".

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


Re: [Tutor] Python 3.6 Multiply the elements of a 2D Array by the elements of a 1D Aeeay

2017-04-17 Thread Stephen P. Molnar

On 04/16/2017 04:57 PM, Sergio Rojas wrote:


On 04/14/2017 04:21 AM, Peter Otten wrote:

Stephen P. Molnar wrote:


However, what I want to do is multiply each element ob D by each element
of s and sum all of the products.


If you *really* want this:

sum_of_all_products = s.sum() * D.sum()

example:

s = [a b c]

D = [[a1 a2]
[a3 a4]]

a*a1 + a*a2 + a*a3 + a*a4 = a * D.sum()

d := D.sum()
a*d + b*d + c*d = s.sum() * d

Even if that's what you want you should heed Steven's advice.



Nice example on "analyze before computing". Nevertheless,
A lazy man's approach to life might  go  using numpy ufunc.outer
  [ https://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.outer.html 
]


In [1]: import numpy as np

In [2]: from sympy import symbols

In [3]: x1, y1, z1, x2, y2, z2, x3, y3, z3 = symbols('x1 y1 z1 x2 y2 z2 x3 y3 z3
...: ')

In [4]: x=np.array([[x1,y1,z1], [x2,y2,z2], [x3,y3,z3]])

In [5]: z=np.array([z1,z2,z3])

In [6]: print(np.multiply.outer(z,x))
[[[x1*z1 y1*z1 z1**2]
   [x2*z1 y2*z1 z1*z2]
   [x3*z1 y3*z1 z1*z3]]

  [[x1*z2 y1*z2 z1*z2]
   [x2*z2 y2*z2 z2**2]
   [x3*z2 y3*z2 z2*z3]]

  [[x1*z3 y1*z3 z1*z3]
   [x2*z3 y2*z3 z2*z3]
   [x3*z3 y3*z3 z3**2]]]

In [7]: np.multiply.outer(z,x).sum()
Out[7]: x1*z1 + x1*z2 + x1*z3 + x2*z1 + x2*z2 + x2*z3 + x3*z1 + x3*z2 + x3*z3 + 
y1*z1 + y1*z2 + y1*z3 + y2*z1 + y2*z2 + y2*z3 + y3*z1 + y3*z2 + y3*z3 + z1**2 + 
2*z1*z2 + 2*z1*z3 + z2**2 + 2*z2*z3 + z3**2

In [8]:

Sergio
https://www.packtpub.com/big-data-and-business-intelligence/numerical-and-scientific-computing-scipy-video
https://github.com/rojassergio/Learning-Scipy
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor



Thanks for the reply.

--
Stephen P. Molnar, Ph.D.Life is a fuzzy set
www.molecular-modeling.net  Stochastic and multivariate
(614)312-7528 (c)
Skype: smolnar1
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Need help with code

2017-04-17 Thread Danny Yoo
On Mon, Apr 17, 2017 at 12:00 AM, Alan Gauld via Tutor  wrote:
> On 16/04/17 18:26, Tyler Seacrist wrote:
>
>> I need to draw a stack diagram for print_n
>> called with s = 'Hello' and n=2 and am unsure of how to do so.


Are you referring to this?

http://www.greenteapress.com/thinkpython/html/thinkpython004.html#toc33
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] bracket issue

2017-04-17 Thread Danny Yoo
> coming to recursion well i currently use eval() so everything ok i don't
> have to worry about brackets but i want to write my own parser. a top down
> parser for expressions.


Do *not* use eval to parse expressions.  It is an extremely bad idea to do this.


Instead, you can use ast.parse, which will give you the parse tree
directly.  It uses the grammatical structure described in:

https://docs.python.org/2/library/ast.html#abstract-grammar


Example:

##
>>> tree = ast.parse("2*3+3(8-4(5+6+9))+2+3+3(4/4)", mode='eval')
>>> tree
<_ast.Expression object at 0x7f86c447e490>
>>> tree.body
<_ast.BinOp object at 0x7f86c447e450>
>>> tree.body.op
<_ast.Add object at 0x7f86c4487cd0>
>>> tree.body.left
<_ast.BinOp object at 0x7f86c447e390>
>>>
>>> tree.body.left.left.left.left.left
<_ast.Num object at 0x7f86c440ed90>
>>> tree.body.left.left.left.left.left.n
2
>>> tree.body.left.left.left.left.right.n
3
>>> tree.body.left.left.left.left.op
<_ast.Mult object at 0x7f86c4487dd0>
##

The example shows that we can navigate the structure of the expression
to get at individual nodes.  Because the structure is recursive,
you'll likely be writing recursive functions that do case-analysis on
the 'expr' type described in the abstract grammar.


To get at the "3(8-4(5+6+9))" part of the example expression, we take
a right instead of a left.  We get back a "Call" object,


###
>>> tree.body.left.left.left.right
<_ast.Call object at 0x7f86c440ee10>
###


which according to the grammar, has a "func" and "args", themselves
being expressions.


###
>>> tree.body.left.left.left.right.func
<_ast.Num object at 0x7f86c440ee50>
>>> tree.body.left.left.left.right.func.n
3
>>> tree.body.left.left.left.right.args
[<_ast.BinOp object at 0x7f86c440ee90>]
###


I hope this helps to give you a brief overview on navigating the
abstract syntax tree.  Good luck!
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] reg. list update

2017-04-17 Thread Rasika Sapate via Tutor
Dear Python group,
I had written following code.

super = []
sub = [""]*3
other = ["a","b","c","d"]
sub[0] = "hi"
sub[1] = "hello"
for item in other:
sub[2] = item
super.append(sub)
for item in super:
print item


Output :
['hi', 'hello', 'd']
['hi', 'hello', 'd']
['hi', 'hello', 'd']
['hi', 'hello', 'd']


Expected output:
['hi', 'hello', 'a]
['hi', 'hello', 'b']
['hi', 'hello', 'c']
['hi', 'hello', 'd']


Is there anything wrong in this code or any feature of python?

Thanks and regards,
Rasika Sapate.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] reg. list update

2017-04-17 Thread Peter Otten
Rasika Sapate via Tutor wrote:

> Dear Python group,
> I had written following code.
> 
> super = []
> sub = [""]*3
> other = ["a","b","c","d"]
> sub[0] = "hi"
> sub[1] = "hello"
> for item in other:
> sub[2] = item
> super.append(sub)
> for item in super:
> print item
> 
> 
> Output :
> ['hi', 'hello', 'd']
> ['hi', 'hello', 'd']
> ['hi', 'hello', 'd']
> ['hi', 'hello', 'd']
> 
> 
> Expected output:
> ['hi', 'hello', 'a]
> ['hi', 'hello', 'b']
> ['hi', 'hello', 'c']
> ['hi', 'hello', 'd']
> 
> 
> Is there anything wrong in this code or any feature of python?

When you replace an item in a list you don't magically copy that list, so in 
a for loop

>>> outer = []
>>> inner = [1, 2, 3]
>>> for item in "abc":
...inner[2] = item
...outer.append(inner)
... 
>>>

You append the same list three time to outer

>>> outer[0] is inner
True
>>> outer[2] is inner
True

and inner[2] holds the last value you assigned to it. What you want is a new 
list on each iteration, and one way to get that when the inner list is long 
is list concatenation with the + operator:

>>> outer = []
>>> inner_start = [1, 2]
>>> for item in "abc":
... outer.append(inner_start + [item])
... 
>>> outer[0] is outer[2]
False
>>> outer
[[1, 2, 'a'], [1, 2, 'b'], [1, 2, 'c']]

In your case with only three items I recommend that you use a list literal:

>>> outer = []
>>> for item in "abc":
... outer.append([1, 2, item])
... 
>>> outer
[[1, 2, 'a'], [1, 2, 'b'], [1, 2, 'c']]

Python has a concise way to spell those append-only loops which is called 
list comprehension and looks like this:

>>> [[1, 2, item] for item in "abc"]
[[1, 2, 'a'], [1, 2, 'b'], [1, 2, 'c']]


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


Re: [Tutor] Can a virtual environment be renamed?

2017-04-17 Thread Jim

On 04/16/2017 02:18 PM, Mats Wichmann wrote:

On 04/16/2017 10:16 AM, Jim wrote:

On 04/16/2017 10:10 AM, Chris Warrick wrote:

On 16 April 2017 at 16:45, Jim  wrote:

My system python is 2.7.12 so I created a virtual environment using
venu to
run 3.5.2. I put it in /home/jfb/EVs/env. Now I would like to try 3.6
and
put it in env36. Is it possible to change env to env35 for 3.5.2 without
breaking things?


No. You need to delete your existing virtualenv and create a new one.
You can just use `pip freeze > requirements.txt` in the old one and
run `pip install -r requirements.txt` in the new one to ”move” all the
packages you had.




Thanks Chris. I thought that would be the answer but wanted to check
before I spent a lot of time trying to do something that was not possible.

Virtual environments tend to confuse me. My system is Mint 18.1 with
2.7.12 & 3.5.2 installed. So I would have to download a tar file of 3.6,
then build it and then use it's version of venv to create a virtual
environment to try 3.6. Is that correct?

Thanks,  Jim


It doesn't need to be terribly complicated, something called pyenv can
manage the install for you (yes, it will build it if needed).

pyenv install --list

to show what's available to install

pyenv install 3.6.0

to install a copy

If you set up the shell helpers, pyenv will let you create the
virtualenv and launch it:

pyenv virtualenv 3.6.0 test-3.6.0
pyenv activate test-3.6.0



Thanks Mats,

When I get a chance to try 3.6 this looks like the best way for me to 
install it.


Regards, Jim



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


Re: [Tutor] Can a virtual environment be renamed?

2017-04-17 Thread Jim

On 04/16/2017 11:24 AM, Chris Warrick wrote:

On 16 April 2017 at 18:16, Jim  wrote:

On 04/16/2017 10:10 AM, Chris Warrick wrote:


On 16 April 2017 at 16:45, Jim  wrote:


My system python is 2.7.12 so I created a virtual environment using venu
to
run 3.5.2. I put it in /home/jfb/EVs/env. Now I would like to try 3.6 and
put it in env36. Is it possible to change env to env35 for 3.5.2 without
breaking things?



No. You need to delete your existing virtualenv and create a new one.
You can just use `pip freeze > requirements.txt` in the old one and
run `pip install -r requirements.txt` in the new one to ”move” all the
packages you had.




Thanks Chris. I thought that would be the answer but wanted to check before
I spent a lot of time trying to do something that was not possible.

Virtual environments tend to confuse me. My system is Mint 18.1 with 2.7.12
& 3.5.2 installed. So I would have to download a tar file of 3.6, then build
it and then use it's version of venv to create a virtual environment to try
3.6. Is that correct?


Yes, you need to install the appropriate interpreter first, and
likewise a virtualenv won’t work if you uninstall an
interpreter/upgrade it to a new minor version*. You might not need to
use the source tarball if
https://launchpad.net/~fkrull/+archive/ubuntu/deadsnakes works on Mint
(and if you do use tarballs, make sure to install somewhere in /opt or
whatever not to make a mess — it’s easy to break your OS if you’re not
careful)

* eg. 3.5 → 3.6. Won’t ever happen on Mint or other “friendly”
distros, unless you do a dist-upgrade. Happens pretty often on
rolling-release distros or macOS with homebrew.



Chris, thanks for the confirmation and the link.

Regards, Jim

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


Re: [Tutor] reg. list update

2017-04-17 Thread Mats Wichmann
On 04/17/2017 12:41 PM, Rasika Sapate via Tutor wrote:
> Dear Python group,
> I had written following code.
> 
> super = []
> sub = [""]*3
> other = ["a","b","c","d"]
> sub[0] = "hi"
> sub[1] = "hello"
> for item in other:
> sub[2] = item
> super.append(sub)
> for item in super:
> print item
> 
> 
> Output :
> ['hi', 'hello', 'd']
> ['hi', 'hello', 'd']
> ['hi', 'hello', 'd']
> ['hi', 'hello', 'd']
> 
> 
> Expected output:
> ['hi', 'hello', 'a]
> ['hi', 'hello', 'b']
> ['hi', 'hello', 'c']
> ['hi', 'hello', 'd']
> 
> 
> Is there anything wrong in this code or any feature of python?

yeah, feature of Python.  you could google for "deep copy".

in short, sub[2] ends up with a reference to, not a copy of, the object
referenced by "item" in the first for loop. all four lists hold this
reference. by the time you go to print, that's a reference to the value
"item" held when the first loop exited, or 'd'.  item itself no longer
refers to that, you assign new things to it.

You can see this by adding a couple of debug print lines

super = []
sub = [""]*3
other = ["a","b","c","d"]
sub[0] = "hi"
sub[1] = "hello"
for item in other:
sub[2] = item
print "item id:", id(item)
super.append(sub)
for item in super:
print item
print "item[2] id:", id(item[2])
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] sqlite3 making a spurious duplicate?

2017-04-17 Thread Marilyn Davis
#!/usr/bin/env python3
"""
Hello Tutors,

I can't figure out why the FillWithStars() function puts Canopus in the db
twice.

What am I missing?

Thank you for any help.

Marilyn Davis

p.s. That Reset(db_name) is in there so that you can run it over and over
if you want.

---
"""
import os, sqlite3, subprocess

def Reset(db_name):
os.system("rm " + db_name)
db_process = subprocess.Popen(("sqlite3", db_name),
   stdin=subprocess.PIPE,
   stdout=subprocess.PIPE,
   stderr=subprocess.PIPE)
for send in (b'.tables', ):
returned = db_process.communicate(send)
assert returned == (b'', b'')

def FillWithStars():

with sqlite3.connect("stars.db") as connection:

connection.executescript("""
CREATE TABLE brightest(
name,
constellation,
apparent_magnitude,
absolute_magnitude,
distance);
INSERT INTO brightest VALUES("Canopus", "Carina", -0.72, -2.5,
74);
""")

connection.executemany("INSERT INTO brightest VALUES(?, ?, ?, ?, ?)",
[("Arcturus", "Bootes", -0.04, 0.2, 34),])

stored_stars = connection.execute("SELECT * FROM BRIGHTEST")

for star in stored_stars:
print(star)

def main():
Reset("stars.db")
FillWithStars()

if __name__ == '__main__':
main()

"""Output:

bash-3.2$ ./why3.py
('Canopus', 'Carina', -0.72, -2.5, 74)
('Canopus', 'Carina', -0.72, -2.5, 74)
('Arcturus', 'Bootes', -0.04, 0.2, 34)
bash-3.2$
"""

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


Re: [Tutor] reg. list update

2017-04-17 Thread Mats Wichmann

>>
>> Is there anything wrong in this code or any feature of python?
> 
> yeah, feature of Python.  you could google for "deep copy".
> 


the reference issue is involved here, but my explanation was off, I
confused myself, listen to Peter instead :)   It's just the same list
four times.




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


Re: [Tutor] sqlite3 making a spurious duplicate?

2017-04-17 Thread Alan Gauld via Tutor
On 18/04/17 00:36, Marilyn Davis wrote:
> #!/usr/bin/env python3
> """
> Hello Tutors,
> 
> I can't figure out why the FillWithStars() function puts Canopus in the db
> twice.
> 
> What am I missing?

I don;t know but I converted your script into the more
conventional form and it worked. it was the fetchall()
line that made the difference... I don't understand
why your code seems to behave oddly, but its too late
to figure out right now, hopefully someone else can
answer... Here is my version:

import os, sqlite3, subprocess

def FillWithStars():

with sqlite3.connect("stars.db") as connection:

cursor = connection.cursor()
cursor.execute("DROP TABLE IF EXISTS brightest")

cursor.execute("""
CREATE TABLE brightest(
name,
constellation,
apparent_magnitude,
absolute_magnitude,
distance)""")
cursor.execute("""INSERT INTO brightest
  VALUES("Canopus", "Carina", -0.72, -2.5, 74)""")

stored_stars = cursor.execute("SELECT * FROM BRIGHTEST")

for star in stored_stars:
print('---> ', star)

cursor.execute("INSERT INTO brightest VALUES(?, ?, ?, ?, ?)",
   ("Arcturus", "Bootes", -0.04, 0.2, 34))

stored_stars = cursor.execute("SELECT * FROM BRIGHTEST")

for star in stored_stars.fetchall():
print(star)

def main():
FillWithStars()

if __name__ == '__main__':
main()


-- 
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] reg. list update

2017-04-17 Thread D . V . N . Sarma డి . వి . ఎన్ . శర్మ
This is an aliasing problem. Change the code to

super = []
sub = [""]*3
other = ["a","b","c","d"]
sub[0] = "hi"
sub[1] = "hello"
for item in other:
l = sub[:]
l[2] = item
super.append(l)
for item in super:
print item

regards,
Sarma.

On Tue, Apr 18, 2017 at 2:16 AM, Mats Wichmann  wrote:

> On 04/17/2017 12:41 PM, Rasika Sapate via Tutor wrote:
> > Dear Python group,
> > I had written following code.
> >
> > super = []
> > sub = [""]*3
> > other = ["a","b","c","d"]
> > sub[0] = "hi"
> > sub[1] = "hello"
> > for item in other:
> > sub[2] = item
> > super.append(sub)
> > for item in super:
> > print item
> >
> >
> > Output :
> > ['hi', 'hello', 'd']
> > ['hi', 'hello', 'd']
> > ['hi', 'hello', 'd']
> > ['hi', 'hello', 'd']
> >
> >
> > Expected output:
> > ['hi', 'hello', 'a]
> > ['hi', 'hello', 'b']
> > ['hi', 'hello', 'c']
> > ['hi', 'hello', 'd']
> >
> >
> > Is there anything wrong in this code or any feature of python?
>
> yeah, feature of Python.  you could google for "deep copy".
>
> in short, sub[2] ends up with a reference to, not a copy of, the object
> referenced by "item" in the first for loop. all four lists hold this
> reference. by the time you go to print, that's a reference to the value
> "item" held when the first loop exited, or 'd'.  item itself no longer
> refers to that, you assign new things to it.
>
> You can see this by adding a couple of debug print lines
>
> super = []
> sub = [""]*3
> other = ["a","b","c","d"]
> sub[0] = "hi"
> sub[1] = "hello"
> for item in other:
> sub[2] = item
> print "item id:", id(item)
> super.append(sub)
> for item in super:
> print item
> print "item[2] id:", id(item[2])
> ___
> Tutor maillist  -  Tutor@python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor
>
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] Tkinter and canvas question

2017-04-17 Thread Phil
Thank you for reading this.

How do I reference the_canvas from my solve() method? Despite hours of 
searching I haven't been able to solve this or find a similar example. All that 
I've gained is a headache.

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.4/tkinter/__init__.py", line 1536, in __call__
return self.func(*args)
  File "/home/pi/sudoku.py", line 64, in solve
self.the_canvas.create_text(20,20,text="5")
AttributeError: 'Sudoku' object has no attribute 'the_canvas'

from tkinter import *

class Sudoku(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent

parent.title("Sudoku solver")

#create canvas
the_canvas = Canvas(width = 300, height = 300)  
   
the_canvas.pack(side = TOP, anchor = NW, padx = 10, pady = 10)

#create grid

#create solve button
solve_button = Button(the_canvas, text = "Solve", command = self.solve,
anchor = W)
solve_button.configure(width = 5, activebackground = "#33B5E5",
relief = FLAT)
solve_button.pack(side = TOP)
solve_button_window = the_canvas.create_window(250, 250, anchor=NW, 
window=solve_button)

def solve(self):
print("solve called")
self.the_canvas.create_text(20,20,text="5")


def main():
root = Tk()
app = Sudoku(root)
app.mainloop()

if __name__ == '__main__':
main()


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


Re: [Tutor] Do not understand code snippet from "26.8. test — Regression tests package for Python"

2017-04-17 Thread boB Stepp
On Sun, Apr 16, 2017 at 11:50 PM, Mats Wichmann  wrote:

>
> You got me thinking as well, as I don't much care for unittest, at least
> partly because it forces you to use classes even when it doesn't feel
> all that natural.

I have looked into pytest multiple times, but have decided to stick
with unittest until I feel I have mastered its use.  While it forces
the use of classes, this is an advantage for me as I am still in the
beginning stages of learning OOP.  But if I ever make it through these
learning journeys, I will probably switch to using pytest.  Everything
I have read on it to this point has favorably impressed me.

[snip]

> === reverser.py ==
> def slicerev(collection):
> return collection[::-1]
>
> if __name__ == "__main__":
> print slicerev([1,2,3,4])
> print slicerev((1,2,3,4))
> print slicerev('abcd')
> ===

[snip]

> The actual test function should be pretty straightforward.
>
> === test_slicerev.py ===
> import pytest
>
> from reverser import slicerev
>
> @pytest.fixture(params=[
> ([1,2,3,4], [4,3,2,1]),
> ((1,2,3,4), (4,3,2,1)),
> ('abcd','edcba')
> ])
> def slicedata(request):
> return request.param
>
> def test_slicerev(slicedata):
> input, expected = slicedata
> output = slicerev(input)
> assert output == expected
> ===

It's funny you picked this type of example.  Last year I was
struggling with getting unittest to feed in data to my test of a
function (or was it a method?), and almost took the plunge and went
all in on pytest because of the apparent ease of handling these types
of situations while respecting DRY.  I did find a way to do something
similar in unittest, so put off pytest for another day.  I cannot
remember now what I did.  I need to go back and find that code (If I
still have it.) and compare it with this Mixin approach that I started
this whole thread with.  Nonetheless pytest is definitely on my radar
and I will get to it at some point.

Thanks!


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


Re: [Tutor] Do not understand code snippet from "26.8. test — Regression tests package for Python"

2017-04-17 Thread boB Stepp
Ah, Peter, if only I could achieve your understanding and mastery!

On Mon, Apr 17, 2017 at 3:37 AM, Peter Otten <__pete...@web.de> wrote:

> Perhaps it becomes clearer if we build our own class discovery / method
> runner system. Given T as the baseclass for classes that provide foo_...()
> methods that we want to run, and M as the mix-in that provides such methods
> but isn't itself a subclass of T...
>

[snip]

> As you can see, to the discovery algorithm it doesn't matter where the
> method is defined, it suffices that it's part of the class and can be found
> by dir() or vars().
>

[snip]

>
> $ cat discovery6.py
> class T:
> pass
>
> class M:
> def foo_one(self):
> print(self.__class__.__name__, "one")
> def foo_two(self):
> print(self.__class__.__name__, "two")
>
> class X(T):
> def foo_x(self):
> print(self.__class__.__name__, "x")
>
> class Y(M, T):
> pass
>
> def safe_issubclass(S, B):
> try:
> return issubclass(S, B)
> except TypeError:
> return False
>
> def discover_Ts():
> for C in globals().values():
> if safe_issubclass(C, T) and C is not T:
> print("found", C, "with foo_... methods")
> for name in dir(C):
> if name.startswith("foo_"):
> yield C, name

So your discover function does not need to instantiate any objects; it
just searches the module's global namespace for class names.  Cool!
And dir(C) gives all attributes of C including _inherited_ attributes!
 This clarifies so much.  Many thanks, Peter!

> def run_method(cls, methodname):
> inst = cls()
> method = getattr(inst, methodname)
> method()
>
> def main():
> for cls, methodname in discover_Ts():
> run_method(cls, methodname)
>
> if __name__ == "__main__":
> main()
> $ python3 discovery6.py
> found  with foo_... methods
> Y one
> Y two
> found  with foo_... methods
> X x
>
> That was easy. We have replicated something similar to the unit test
> framework with very little code.
>
> Now you can go and find the equivalent parts in the unittest source code :)

But not tonight ~(:>))


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


Re: [Tutor] sqlite3 making a spurious duplicate?

2017-04-17 Thread Steven D'Aprano
On Mon, Apr 17, 2017 at 04:36:50PM -0700, Marilyn Davis wrote:
> #!/usr/bin/env python3
> """
> Hello Tutors,
> 
> I can't figure out why the FillWithStars() function puts Canopus in the db
> twice.


Good question. And thank you for providing a really well-written, 
simple, clear script that we can run unchanged to demonstrate the 
problem.

I get the same results as you, and like you, I'm not too sure why. But 
I'm leading to suspect the blame lies with sqlite, not your code.

If I take your script and add the following lines between the call to 
connection.executescript(...) and connection.executemany(...):

stored_stars = connection.execute("SELECT * FROM BRIGHTEST")
for star in stored_stars:
print(star)
del stored_stars
print('-'*30)

I get this output:

[steve@ando ~]$ python3 why4.py
('Canopus', 'Carina', -0.72, -2.5, 74)

('Canopus', 'Carina', -0.72, -2.5, 74)
('Canopus', 'Carina', -0.72, -2.5, 74)
('Arcturus', 'Bootes', -0.04, 0.2, 34)


so it looks to me like the initial call to executescript() correctly 
adds Canopus once, and then the call to executemany() mysteriously 
duplicates it.

I tried one more iteration: swap the two stars, so that Acturus 
is added first, then Canopus:


[steve@ando ~]$ python3 why5.py
('Arcturus', 'Bootes', -0.04, 0.2, 34)

('Arcturus', 'Bootes', -0.04, 0.2, 34)
('Arcturus', 'Bootes', -0.04, 0.2, 34)
('Canopus', 'Carina', -0.72, -2.5, 74)


At this point, I'm not sure whether this is a bug in sqlite, or a 
misunderstanding that we're doing something wrong. I think this now 
needs an sqlite expert.



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


Re: [Tutor] sqlite3 making a spurious duplicate?

2017-04-17 Thread Steven D'Aprano
I made one more diagnostic change to your script, changing the 
FillWithStars function to this:


def FillWithStars():
with sqlite3.connect("stars.db") as connection:
connection.executescript("""
CREATE TABLE brightest(
name,
constellation,
apparent_magnitude,
absolute_magnitude,
distance);
INSERT INTO brightest VALUES("Arcturus", "Bootes", -0.04, 0.2, 
34);""")

stored_stars = connection.execute("SELECT * FROM BRIGHTEST")
for star in stored_stars:
print(star)
del stored_stars
print('-'*40)

connection.executemany("INSERT INTO brightest VALUES(?, ?, ?, ?, ?)",
[("Canopus", "Carina", -0.72, -2.5, 74),])

stored_stars = connection.execute("SELECT * FROM BRIGHTEST")
print("stars as reported inside the with block")
for star in stored_stars:
print(star)
stored_stars = connection.execute("SELECT * FROM BRIGHTEST")

print("stars as reported outside the with block")
for star in stored_stars:
print(star)




As you can see, this now prints the stars from inside the with 
block, while the database connection is still open, and then a second 
time, when the database connection is closed.

The first prints the expected information, the second does not:

[steve@ando ~]$ python3 why5.py
('Arcturus', 'Bootes', -0.04, 0.2, 34)

stars as reported inside the with block
('Arcturus', 'Bootes', -0.04, 0.2, 34)
('Canopus', 'Carina', -0.72, -2.5, 74)
stars as reported outside the with block
('Arcturus', 'Bootes', -0.04, 0.2, 34)
('Arcturus', 'Bootes', -0.04, 0.2, 34)
('Canopus', 'Carina', -0.72, -2.5, 74)



So I now expect that this is a misuse of the stored_stars cursor object. 
(Or, possibly, a bug in the cursor object.) If you want to use the 
cursor object, it appears that the connection to the database must be 
open. If you want to use it after closing the database, I think you need 
to extract the data into a list first:

# untested
stored_stars = list(connection.execute("SELECT * FROM BRIGHTEST")



Last but not least, I tried looking at the sqlite database directly:

[steve@ando ~]$ sqlite3 stars.db
SQLite version 3.3.6
Enter ".help" for instructions
sqlite> .databases
seq  name file
---  ---  --
0main /home/steve/stars.db
sqlite> .dump
BEGIN TRANSACTION;
CREATE TABLE brightest(
name,
constellation,
apparent_magnitude,
absolute_magnitude,
distance);
INSERT INTO "brightest" VALUES('Arcturus', 'Bootes', -0.04, 0.2, 34);
INSERT INTO "brightest" VALUES('Canopus', 'Carina', -0.72, -2.5, 74);
COMMIT;




So it looks to me that the right data is stored in the database itself, 
it is just a problem with (mis)using a cursor object after the 
connection is closed.

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


Re: [Tutor] Tkinter and canvas question

2017-04-17 Thread boB Stepp
On Mon, Apr 17, 2017 at 6:13 PM, Phil  wrote:
> Thank you for reading this.
>
> How do I reference the_canvas from my solve() method? Despite hours of 
> searching I haven't been able to solve this or find a similar example. All 
> that I've gained is a headache.
>
> Exception in Tkinter callback
> Traceback (most recent call last):
>   File "/usr/lib/python3.4/tkinter/__init__.py", line 1536, in __call__
> return self.func(*args)
>   File "/home/pi/sudoku.py", line 64, in solve
> self.the_canvas.create_text(20,20,text="5")
> AttributeError: 'Sudoku' object has no attribute 'the_canvas'
>
> from tkinter import *
>
> class Sudoku(Frame):
> def __init__(self, parent):
> Frame.__init__(self, parent)
> self.parent = parent
>
> parent.title("Sudoku solver")
>
> #create canvas
> the_canvas = Canvas(width = 300, height = 300)
> the_canvas.pack(side = TOP, anchor = NW, padx = 10, pady = 10)
>
> #create grid
>
> #create solve button
> solve_button = Button(the_canvas, text = "Solve", command = 
> self.solve,
> anchor = W)
> solve_button.configure(width = 5, activebackground = "#33B5E5",
> relief = FLAT)
> solve_button.pack(side = TOP)
> solve_button_window = the_canvas.create_window(250, 250, anchor=NW, 
> window=solve_button)
>
> def solve(self):
> print("solve called")
> self.the_canvas.create_text(20,20,text="5")
>
>
> def main():
> root = Tk()
> app = Sudoku(root)
> app.mainloop()
>
> if __name__ == '__main__':
> main()
>
>
> --
> Regards,
> Phil
> ___
> Tutor maillist  -  Tutor@python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor



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


Re: [Tutor] Tkinter and canvas question

2017-04-17 Thread boB Stepp
Sorry for the unnecessary post with no response -- inadvertent click
on "Send" button which was too near Gmail's "..." button to expand
content.

On Mon, Apr 17, 2017 at 6:13 PM, Phil  wrote:
> Thank you for reading this.
>
> How do I reference the_canvas from my solve() method? Despite hours of 
> searching I haven't been able to solve this or find a similar example. All 
> that I've gained is a headache.
>

I have yet to do much class writing with tkinter, but if I am
understanding things correctly, in your Sudoku class where you
instantiate a Canvas instance, you assign it to the name "the_canvas".
This will be local to the __init__ method's namespace.  I think you
need to precede each of those "the_canvas" with "self." to get
"self.the_canvas".  This way your solve method will be able to access
it.

> Exception in Tkinter callback
> Traceback (most recent call last):
>   File "/usr/lib/python3.4/tkinter/__init__.py", line 1536, in __call__
> return self.func(*args)
>   File "/home/pi/sudoku.py", line 64, in solve
> self.the_canvas.create_text(20,20,text="5")
> AttributeError: 'Sudoku' object has no attribute 'the_canvas'
>
> from tkinter import *
>
> class Sudoku(Frame):
> def __init__(self, parent):
> Frame.__init__(self, parent)
> self.parent = parent
>
> parent.title("Sudoku solver")
>
> #create canvas
> the_canvas = Canvas(width = 300, height = 300)
> the_canvas.pack(side = TOP, anchor = NW, padx = 10, pady = 10)
>
> #create grid
>
> #create solve button
> solve_button = Button(the_canvas, text = "Solve", command = 
> self.solve,
> anchor = W)
> solve_button.configure(width = 5, activebackground = "#33B5E5",
> relief = FLAT)
> solve_button.pack(side = TOP)
> solve_button_window = the_canvas.create_window(250, 250, anchor=NW, 
> window=solve_button)
>
> def solve(self):
> print("solve called")
> self.the_canvas.create_text(20,20,text="5")
>
>
> def main():
> root = Tk()
> app = Sudoku(root)
> app.mainloop()
>
> if __name__ == '__main__':
> main()
>
>
> --
> Regards,
> Phil
> ___
> Tutor maillist  -  Tutor@python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor



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