Re: [Tutor] Need help with code
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"
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"
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
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
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
> 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
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
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?
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?
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
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?
#!/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
>> >> 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?
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
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
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"
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"
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?
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?
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
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
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