Re: [Tutor] Python Help with Program
On 16/02/15 01:26, Tina Figz wrote: I'm having a problem with my program and I'm not sure how to correct it (I'm in an intro programming class). My program is supposed two numbers and count the number of carry operations. This is what I have: n1 = int(raw_input('Number #1: ')) n2 = int(raw_input('Number #2: ')) add = n1 + n2 > print ' ' > print n1, '+', n2, '=', add Down to here everything is ok and you get the sum of the two numbers sn1 = str(n1) sn2 = str(n2) num1 = 1 num2 = 1 num1 == num2 This line doesn't do anything. last_n1 = sn1[-num1] last_n2 = sn2[-num2] int_lastn1 = int(last_n1) int_lastn2 = int(last_n2) eq = int_lastn1 + int_lastn2 carry = 0 Before entering the loop you have (for your example) sn1 = '239', sn2 = '123' num1 = 1, num2 = 1 last_n1 = '9',last_n2 = '3', int_lastn1 = 9, int_lastn2 = 3 eq = 12 carry = 0 while eq >= 10 and carry < len(sn1) and carry < len(sn2): num1 += 1 num2 += 1 carry += 1 Your loop only changes num1, num2 and carry. But only carry is tested in the loop condition. So in effect you just keep adding 1 to carry until it is > then len(sn1 or len(sn2), ie 3. You are not changing anything else, so you are effectively just counting the number of characters in your shortest number. When I input 239 & 123 as my two numbers it equals 362, which is correct. But it says I have 3 carries, when the answer should be 1 carry operation. You need to completely redesign your algorithm. Try writing it out using pen and paper to figure out how you would do it manually. -- 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] Python Help with Program
On 16/02/2015 08:24, Alan Gauld wrote: On 16/02/15 01:26, Tina Figz wrote: I'm having a problem with my program and I'm not sure how to correct it (I'm in an intro programming class). My program is supposed two numbers and count the number of carry operations. This is what I have: n1 = int(raw_input('Number #1: ')) n2 = int(raw_input('Number #2: ')) add = n1 + n2 > print ' ' > print n1, '+', n2, '=', add Down to here everything is ok and you get the sum of the two numbers sn1 = str(n1) sn2 = str(n2) num1 = 1 num2 = 1 num1 == num2 This line doesn't do anything. last_n1 = sn1[-num1] last_n2 = sn2[-num2] int_lastn1 = int(last_n1) int_lastn2 = int(last_n2) eq = int_lastn1 + int_lastn2 carry = 0 Before entering the loop you have (for your example) sn1 = '239', sn2 = '123' num1 = 1, num2 = 1 last_n1 = '9',last_n2 = '3', int_lastn1 = 9, int_lastn2 = 3 eq = 12 carry = 0 while eq >= 10 and carry < len(sn1) and carry < len(sn2): num1 += 1 num2 += 1 carry += 1 Your loop only changes num1, num2 and carry. But only carry is tested in the loop condition. So in effect you just keep adding 1 to carry until it is > then len(sn1 or len(sn2), ie 3. You are not changing anything else, so you are effectively just counting the number of characters in your shortest number. When I input 239 & 123 as my two numbers it equals 362, which is correct. But it says I have 3 carries, when the answer should be 1 carry operation. You need to completely redesign your algorithm. Try writing it out using pen and paper to figure out how you would do it manually. I'd start this exercise at line 1 and work right the way through the code, e.g. why bother doing all the work to get sn1 and sn2? -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python Help with Program
Hi Tina, or Taylor, welcome! Sorry but your email "From" header says your name is Tina and your signature says Taylor so I'm not sure which name you prefer. On Sun, Feb 15, 2015 at 07:26:35PM -0600, Tina Figz wrote: > I'm having a problem with my program and I'm not sure how to correct it > (I'm in an intro programming class). > > My program is supposed two numbers and count the number of carry > operations. Let's start by working it out using pencil and paper. Write down two numbers, lined up on the right: 472837 29152 for example. Let's go through and check for carries: Number of carries so far: 0 7 and 2 = 9, no carry. 3 and 5 = 8, no carry. 8 and 1 = 9, no carry 2 and 9 = 11, carry the 1. Add one to the number of carries. 7 and 2, plus the 1 we carried, = 10, carry the 1. So add one to number of carries. 4, plus the 1 we carried, = 5, no carry. So the number of carries is two. The process is to take the digits of each number, starting from the right-hand end, in pairs. If you run out of digits for one number before the other, use 0. Add the two digits together, plus any carry digit from before, and if the result is larger than 9, there's a carry. We start with the number of carries equal to 0, and add 1 to that *only* if adding the pair of digits is larger than 9. Let's see what you have: [snip part of the code] > eq = int_lastn1 + int_lastn2 > carry = 0 > while eq >= 10 and carry < len(sn1) and carry < len(sn2): > num1 += 1 > num2 += 1 > carry += 1 You start on the right track: you check whether the last two digits add to more than 9. But, you never check the next two digits, or the two after that. You calculate "eq" (which is not a good name, by the way) once, outside the loop, but never calculate it again with any additional digits. Instead, you add 1 to carry *every single time*, regardless of the digits (apart from the first). Fun fact: (well, not that fun) you have to repeat the calculation each time through the loop, otherwise you're just using the same result over and over again. Example: py> my_string = "12345" py> position = -1 py> total = int(my_string[position]) + 1000 py> while position > -len(my_string): ... print(total) ... position = position - 1 ... 1005 1005 1005 1005 The total never changes, because we never re-calculate it. Instead: py> my_string = "12345" py> position = -1 py> while position > -len(my_string): ... total = int(my_string[position]) + 1000 ... print(total) ... position = position - 1 ... 1005 1004 1003 1002 Does that help you see why your code counts the wrong number of carries, and help you fix it? -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Help with program
Hello, I am trying to build a program that approximates the value of cosine - this is my program so far. It is not returning the right values. Could you tell me what I am doing wrong? def main(): import math print("This program approximates the cosine of x by summing") print("the terms of this series: x^0 / 0!, -x^2 / 2!,") print("x^4 / 4!, -x^6 / 6!...") n = eval(input("How many terms should be used? ")) x = eval(input("What value should be used for x? ")) s = 1 d = 1 e = 1 value = 0 for i in range(n - 1): value = value + s + (x**e / math.factorial(d)) s = s * 1 e = e + 2 d + d + 2 print("Approximation for cos(x) calculated by this program: ") print(value) print() difference = math.cos(x) - value print("Difference between this value and math.cos(x): ") print(difference) main() Thank you! C.Skinner ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Help with program
On 16/02/2015 16:27, Courtney Skinner wrote: Hello, I am trying to build a program that approximates the value of cosine - this is my program so far. It is not returning the right values. Could you tell me what I am doing wrong? def main(): import math Not that it matters but imports are usually done at the top of the module. print("This program approximates the cosine of x by summing") print("the terms of this series: x^0 / 0!, -x^2 / 2!,") print("x^4 / 4!, -x^6 / 6!...") n = eval(input("How many terms should be used? ")) x = eval(input("What value should be used for x? ")) *DON'T* use eval, it's potentially dangerous. n = int(input("How many terms should be used? ")) x = float(input("What value should be used for x? ")) s = 1 d = 1 e = 1 value = 0 for i in range(n - 1): Are you aware that this will count from zero to n - 2? value = value + s + (x**e / math.factorial(d)) s = s * 1 e = e + 2 d + d + 2 Whoops :) print("Approximation for cos(x) calculated by this program: ") print(value) print() difference = math.cos(x) - value print("Difference between this value and math.cos(x): ") print(difference) main() We'd usually write:- if __name__ == "__main__": main() Thank you! C.Skinner -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Help with program
On 16/02/15 16:27, Courtney Skinner wrote: Hello, I am trying to build a program that approximates the value of cosine def main(): import math Its usual to do the imports outside the function at the tyop of the file. Python doesn't actually care much but its 'standard practice'. print("This program approximates the cosine of x by summing") print("the terms of this series: x^0 / 0!, -x^2 / 2!,") print("x^4 / 4!, -x^6 / 6!...") n = eval(input("How many terms should be used? ")) x = eval(input("What value should be used for x? ")) Don't use eval(). Use int() for the first one and float() for the second. eval() is a security hazard and potentially dangerous. s = 1 d = 1 e = 1 value = 0 for i in range(n - 1): value = value + s + (x**e / math.factorial(d)) Your description says you subtract every second value (eg -x**2/2!) You are adding them all. Also you are adding 1(s) every time, surely you just want to add it the first time. In other words you want value to start at 1 and the loop to iterate from 2-(n-1)? You also want a sign multiplier which toggles between +/-1 Also you can get Python to do most the work for you by specifying a third step-size argument to range: ... for e in range(2, (n*2)+1, 2): #step by 2 value += (x**e)/math.factorial(e) * sign ... You no longer need any of the other increments or variables. s = s * 1 e = e + 2 d + d + 2 print("Approximation for cos(x) calculated by this program: ") print(value) print() You probably want all of these outside the loop. You might like to add a print(value) though while you are debugging. difference = math.cos(x) - value print("Difference between this value and math.cos(x): ") print(difference) HTH -- 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] Help with program
Courtney Skinner wrote: > Hello, > > I am trying to build a program that approximates the value of cosine - > this is my program so far. It is not returning the right values. Could you > tell me what I am doing wrong? > > > def main(): > > import math > > print("This program approximates the cosine of x by summing") > print("the terms of this series: x^0 / 0!, -x^2 / 2!,") > print("x^4 / 4!, -x^6 / 6!...") > > n = eval(input("How many terms should be used? ")) > x = eval(input("What value should be used for x? ")) Consider the more restrictive int() and float() instead of eval(). > s = 1 A nice suggestive name like "sign" instead of "s" might help you with your debugging efforts. Of course the same goes for your other names. > d = 1 > e = 1 > > value = 0 > > for i in range(n - 1): > value = value + s + (x**e / math.factorial(d)) With the name suggested above the error value = value + sign + (x**e / math.factorial(d)) should almost be obvious. sign plus? wait what... Add print("current exponent", e) to see another problem. > > s = s * 1 That shows signs of a missing sign ;) > e = e + 2 > d + d + 2 > > > > print("Approximation for cos(x) calculated by this program: ") > print(value) > print() > > difference = math.cos(x) - value > > print("Difference between this value and math.cos(x): ") > print(difference) > > main() > > Thank you! > > C.Skinner ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] What are *appropriate* uses for exec() and eval() ?
I have heard periodically about the potential evils of using exec() and eval(), including today, on this list. I gather that the first requirement for safely using these functions is that the passed argument MUST be from a trusted source. So what would be examples where the use of these functions IS appropriate? -- boB ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Popen was deprecated since Python 2.6, now what?
Wow, just found out this morning that the following terms of: import os pr = os.popen("lpr", "w") pr.write(month), pr.write(" "), pr.write("\t\tLine ") was deprecated. In place there of, there is a subprocess to use. I have not been able to figure out on how to use a subprocess in place of my former popen. I have been reading the new materials on the subprocess all day and it is still not quite understandable. Is there an easy tutorial of how to replace popen with the subprocess? I am using Python 2.7.6 on an Ubuntu 14.04.1 system. In advance, thanking you all for your assistance. Ken ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Popen was deprecated since Python 2.6, now what?
On Mon, Feb 16, 2015 at 1:26 PM, Ken G. wrote: > Wow, just found out this morning that the following > terms of: > > import os > pr = os.popen("lpr", "w") > pr.write(month), pr.write(" "), > pr.write("\t\tLine ") > > was deprecated. In place there of, there is > a subprocess to use. Hi Ken, Yes: subprocess.Popen(), along with Popen.communicate(), are what you want to look at. For your example above, the change is relatively direct: ## import subprocess pr = subprocess.Popen(['lpr', 'w']) pr.communicate(month + ' ' + '\t\tLine ') ## The main difference between this and what you had earlier is that you send all the input at once using Popen.communicate(). There's a quick-and-dirty section in the documentation for converting from the os.popen call to the subprocess equivalents. See: https://docs.python.org/2/library/subprocess.html#replacing-os-popen-os-popen2-os-popen3 ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] What are *appropriate* uses for exec() and eval() ?
On Mon, Feb 16, 2015 at 11:52 AM, boB Stepp wrote: > I have heard periodically about the potential evils of using exec() > and eval(), including today, on this list. I gather that the first > requirement for safely using these functions is that the passed > argument MUST be from a trusted source. So what would be examples > where the use of these functions IS appropriate? Given that there are language environments that do perfectly ok without those functions, the flippant answer would be: those functions aren't necessary. But to be more serious: they'd probably be most useful when you're defining your own interactive programming environment. For example, consider a debugger or an IDE (such as IDLE. Or if you come from the Java world, imagine Eclipse). In a debugger, you're running another program, and allowing the user to do something programmatic in the context of that program. Setting breakpoints, or looking at the value of certain expressions. In this scenario, we want to be able to access the same runtime data structures that drive the running program... within the program itself! It's this introspection that drives the need for an eval or exec. Enormously powerful. Enormously dangerous in the wrong hands. That being said, almost all programs are neither debuggers nor IDEs at their heart. (Despite the joke that every program strives to become Emacs at a certain point.) ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Popen was deprecated since Python 2.6, now what?
On 16/02/15 21:26, Ken G. wrote: I have not been able to figure out on how to use a subprocess in place of my former popen. I have been reading the new materials on the subprocess all day and it is still not quite understandable. Here is what the docs say: ### 17.5.5.5. Replacing os.popen(), os.popen2(), os.popen3() (child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize) ==> p = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, close_fds=True) (child_stdin, child_stdout) = (p.stdin, p.stdout) (child_stdin, child_stdout, child_stderr) = os.popen3(cmd, mode, bufsize) ==> p = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) (child_stdin, child_stdout, child_stderr) = (p.stdin, p.stdout, p.stderr) (child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize) ==> p = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True) (child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout) Return code handling translates as follows: pipe = os.popen(cmd, 'w') ... rc = pipe.close() if rc is not None and rc >> 8: print("There were some errors") ==> process = Popen(cmd, 'w', stdin=PIPE) ... process.stdin.close() if process.wait() != 0: print("There were some errors") 17.5.5.6. Replacing functions from the popen2 module Note If the cmd argument to popen2 functions is a string, the command is executed through /bin/sh. If it is a list, the command is directly executed. (child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode) ==> p = Popen("somestring", shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, close_fds=True) (child_stdout, child_stdin) = (p.stdout, p.stdin) (child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode) ==> p = Popen(["mycmd", "myarg"], bufsize=bufsize, stdin=PIPE, stdout=PIPE, close_fds=True) (child_stdout, child_stdin) = (p.stdout, p.stdin) popen2.Popen3 and popen2.Popen4 basically work as subprocess.Popen, except that: Popen raises an exception if the execution fails. the capturestderr argument is replaced with the stderr argument. stdin=PIPE and stdout=PIPE must be specified. popen2 closes all file descriptors by default, but you have to specify close_fds=True with Popen to guarantee this behavior on all platforms or past Python versions. # Which bits of that don't you understand? That way we have something concrete to work with. For example, Your popen program: import os pr = os.popen("lpr", "w") pr.write(month), pr.write(" "), pr.write("\t\tLine ") Translates according to the above as import subprocess as sub pr = sub.Popen(["lpr"], stdin = sub.PIPE) pr.stdin.write(month) pr.stdin.write(" ") pr.stdin.close() if pr.wait() != 0: print 'Errors!' Now, how can we help further clarify things? -- 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] Popen was deprecated since Python 2.6, now what?
On 02/16/2015 05:11 PM, Danny Yoo wrote: On Mon, Feb 16, 2015 at 1:26 PM, Ken G. wrote: Wow, just found out this morning that the following terms of: import os pr = os.popen("lpr", "w") pr.write(month), pr.write(" "), pr.write("\t\tLine ") was deprecated. In place there of, there is a subprocess to use. Hi Ken, Yes: subprocess.Popen(), along with Popen.communicate(), are what you want to look at. For your example above, the change is relatively direct: ## import subprocess pr = subprocess.Popen(['lpr', 'w']) pr.communicate(month + ' ' + '\t\tLine ') ## The main difference between this and what you had earlier is that you send all the input at once using Popen.communicate(). There's a quick-and-dirty section in the documentation for converting from the os.popen call to the subprocess equivalents. See: https://docs.python.org/2/library/subprocess.html#replacing-os-popen-os-popen2-os-popen3 . Thank you for helping me get on the road here. I printed out your response and I'll be playing with it. Ken ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Popen was deprecated since Python 2.6, now what?
On 02/16/2015 06:26 PM, Alan Gauld wrote: On 16/02/15 21:26, Ken G. wrote: I have not been able to figure out on how to use a subprocess in place of my former popen. I have been reading the new materials on the subprocess all day and it is still not quite understandable. Here is what the docs say: ### 17.5.5.5. Replacing os.popen(), os.popen2(), os.popen3() (child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize) ==> p = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, close_fds=True) (child_stdin, child_stdout) = (p.stdin, p.stdout) (child_stdin, child_stdout, child_stderr) = os.popen3(cmd, mode, bufsize) ==> p = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) (child_stdin, child_stdout, child_stderr) = (p.stdin, p.stdout, p.stderr) (child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize) ==> p = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True) (child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout) Return code handling translates as follows: pipe = os.popen(cmd, 'w') ... rc = pipe.close() if rc is not None and rc >> 8: print("There were some errors") ==> process = Popen(cmd, 'w', stdin=PIPE) ... process.stdin.close() if process.wait() != 0: print("There were some errors") 17.5.5.6. Replacing functions from the popen2 module Note If the cmd argument to popen2 functions is a string, the command is executed through /bin/sh. If it is a list, the command is directly executed. (child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode) ==> p = Popen("somestring", shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, close_fds=True) (child_stdout, child_stdin) = (p.stdout, p.stdin) (child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode) ==> p = Popen(["mycmd", "myarg"], bufsize=bufsize, stdin=PIPE, stdout=PIPE, close_fds=True) (child_stdout, child_stdin) = (p.stdout, p.stdin) popen2.Popen3 and popen2.Popen4 basically work as subprocess.Popen, except that: Popen raises an exception if the execution fails. the capturestderr argument is replaced with the stderr argument. stdin=PIPE and stdout=PIPE must be specified. popen2 closes all file descriptors by default, but you have to specify close_fds=True with Popen to guarantee this behavior on all platforms or past Python versions. # Which bits of that don't you understand? That way we have something concrete to work with. For example, Your popen program: import os pr = os.popen("lpr", "w") pr.write(month), pr.write(" "), pr.write("\t\tLine ") Translates according to the above as import subprocess as sub pr = sub.Popen(["lpr"], stdin = sub.PIPE) pr.stdin.write(month) pr.stdin.write(" ") pr.stdin.close() if pr.wait() != 0: print 'Errors!' Now, how can we help further clarify things? Thank for the translation of the hard-to-read docs. Reading the docs threw me for a loop. I printed out your response and will be studying to try best understand it. Ken ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Popen was deprecated since Python 2.6, now what?
> Thank for the translation of the hard-to-read docs. Reading the docs threw > me for a loop. I printed out your response and will be studying to try best > understand it. No problem; feel free to ask questions on anything that doesn't make sense, and we'll try to help as best as we can. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] What are *appropriate* uses for exec() and eval() ?
On Mon, Feb 16, 2015 at 01:52:16PM -0600, boB Stepp wrote: > I have heard periodically about the potential evils of using exec() > and eval(), including today, on this list. I gather that the first > requirement for safely using these functions is that the passed > argument MUST be from a trusted source. So what would be examples > where the use of these functions IS appropriate? The flippant reply would be "there aren't any". But that is not true. In the broader context of programming in general, not just Python, the use of eval/exec is incredibly powerful because it allows you to write dynamic code that uses information available at runtime to solve problems which cannot even be expressed at compile time. Think about it like this: A programming language is like a toolbox filled with tools for solving problems. You combine those tools like Lego blocks, combining them in different ways to make new tools. One of those Lego blocks is a robot, called eval or exec, which you can instruct to make new tools, instead of making them yourself. There are various downsides: the extra complexity of telling the robot which Lego blocks to use, instead of just directly using the blocks yourself, means that using the robot is slower, more complex, harder to read, error messages are less useful, and if your instructions contain data coming from strangers, they may be able to subvert your intention, sneak instructions into your code, and take control of the robot. But it means you can put off the decision for which Lego block to use until runtime when more information is available. exec is literally a Python interpreter embedded inside Python, so if you have a particularly hard problem to solve, one of the ways you can solve it is to write a program to *write a program to solve it*, then use exec to run that second program. All this discussion has been very abstract. Here are some concrete examples of good use of eval/exec. In the standard library, we have the timeit module which takes a code snippet from the user, executes it as Python code, and measures how long it takes. There's no way to take *code* from the user except as a string, if you type it directly Python will interpret it immediately. To delay execution, you have to put the code inside a string, and then later interpret the string as Python code. In other words, exec. Likewise, we have the doctest module. Inside your function docstrings, you can write samples of interactive output: def spam(n): """Return n lots of spam. >>> spam(3) 'spam spam spam' """ ... The doctest module scans the docstring, extracts anything which looks like interactive output (starting with >>> prompt), execs that text as Python code, and checks that the output matches what you gave it. Your sample code is *executable documentation*, so long as you remember to run dotest over it, you can always be sure that the sample code is correct. In the collections module, there is a factory function called namedtuple for creating record-like tuples with named fields. How it works is you provide the name of the fields, they get plugged into a class definition template, and the template executed as Python code, which creates a new class. That class is returned for you to use: py> from collections import namedtuple py> Record = namedtuple("Record", "x y z") py> point = Record(23, 42, 19) py> print(point) Record(x=23, y=42, z=19) py> point.x 23 Here is the original version which eventually became part of the collections module: http://code.activestate.com/recipes/500261-named-tuples/ Here is a fork of that recipe. It uses an inner class for the new namedtuple class. The only thing which needs exec is the __new__ method. http://code.activestate.com/recipes/578918-yet-another-namedtuple/ This demonstrates a powerful truth about Python: *most of the time* you don't need to use exec or eval because the standard language features are powerful enough to solve the problem for you. Using a dynamically created inner class is *almost* enough to solve this problem, only the __new__ method defeats it. If our requirements where just a little less demanding, we could avoid exec completely. In some languages, if you want to define functions are runtime, the only way to do it is to write a function template, fill in the blanks at runtime, then exec it: template = """ def add(x): return x + %s """ namespace = {} exec(template % 10, namespace) addTen = namespace['add'] print(addTen(23)) With Python, going to all that trouble is unnecessary: def factory(n): """Return a new function which adds n to its argument.""" def add(x): return x + n return add addTen = factory(10) print(addTen(23)) The result is easier to read, faster, and more secure. -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.or
Re: [Tutor] Help with program
On 02/16/2015 11:27 AM, Courtney Skinner wrote: Hello, I am trying to build a program that approximates the value of cosine - this is my program so far. It is not returning the right values. Could you tell me what I am doing wrong? You've got several answers that point out several problems in your code. But I think you're missing a key concept. If you're faced with a problem that's beyond your present abilities, or that's got you stumped, always consider factoring the problem into simpler ones. To me the first thing you should factor out is a factorial function. Write one, that takes a positive int and returns the factorial, and test it against the one in the math library. Once it's correct, then use it in the cosine problem. Now you've got a simpler loop to write. And you know part of the code works. Next, see if you can avoid most of those three variables you're using. For example, What do you get when you calculate (-1) ** (i) Can you use that to simplify things? -- DaveA ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] What are *appropriate* uses for exec() and eval() ?
On Mon, Feb 16, 2015 at 6:15 PM, Steven D'Aprano wrote: > Here is a fork of that recipe. It uses an inner class for the new > namedtuple class. The only thing which needs exec is the __new__ method. > > http://code.activestate.com/recipes/578918-yet-another-namedtuple/ > > This demonstrates a powerful truth about Python: *most of the time* you > don't need to use exec or eval because the standard language features > are powerful enough to solve the problem for you. Using a dynamically > created inner class is *almost* enough to solve this problem, only the > __new__ method defeats it. If our requirements where just a little less > demanding, we could avoid exec completely. No, exec is not necessary at all. If they had to the author could have reimplemented the argument assignment logic by hand. They chose not to because it is "too hard". (And it is.) Fortunately, they don't have to go that far: signature = inspect.Signature([ inspect.Parameter(field_name, inspect.Parameter.POSITIONAL_OR_KEYWORD) for field_name in field_names]) def __new__(cls, *args, **kwargs): return tuple.__new__(cls, signature.bind(*args, **kwargs).arguments.values()) -- Devin ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] What are *appropriate* uses for exec() and eval() ?
On 16Feb2015 19:10, Devin Jeanpierre wrote: On Mon, Feb 16, 2015 at 6:15 PM, Steven D'Aprano wrote: Here is a fork of that recipe. It uses an inner class for the new namedtuple class. The only thing which needs exec is the __new__ method. http://code.activestate.com/recipes/578918-yet-another-namedtuple/ This demonstrates a powerful truth about Python: *most of the time* you don't need to use exec or eval because the standard language features are powerful enough to solve the problem for you. Using a dynamically created inner class is *almost* enough to solve this problem, only the __new__ method defeats it. If our requirements where just a little less demanding, we could avoid exec completely. No, exec is not necessary at all. If they had to the author could have reimplemented the argument assignment logic by hand. [... example...] I see your counter counter example and raise you another counter. One might use exec() to use code that is valid in one python version but not another, when you need your program to run in both i.e. to get code that is syntacticly invalid in one version, but to use it (conditionally) in another version. I only have one use case for this presently: I have a use of exec() in my cs.py3 python2/3 compatability module: def raise3(exc_type, exc_value, exc_traceback): if sys.hexversion >= 0x0300: raise exc_type(exc_value).with_traceback(exc_traceback) else: # subterfuge to let this pass a python3 parser; ugly exec('raise exc_type, exc_value, exc_traceback') I'm using exec() here because a Python 3 interpreter will reject the 3 argument form of raise. Elsewhere in my code I just call cs.py3.raise3() with the requisite arguments. Note that the string passed to exec() is hardwired, not obtained from elsewhere in any form. Like all sane people, I consider using exec() a code smell: if you're using it you should consider heavily alternatives to it. Cheers, Cameron Simpson I think... Therefore I ride. I ride... Therefore I am. - Mark Pope ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] What are *appropriate* uses for exec() and eval() ?
On Mon, Feb 16, 2015 at 7:20 PM, Cameron Simpson wrote: > One might use exec() to use code that is valid in one python version but not > another, when you need your program to run in both i.e. to get code that is > syntacticly invalid in one version, but to use it (conditionally) in another > version. > > I only have one use case for this presently: I have a use of exec() in my > cs.py3 python2/3 compatability module: > > def raise3(exc_type, exc_value, exc_traceback): >if sys.hexversion >= 0x0300: > raise exc_type(exc_value).with_traceback(exc_traceback) >else: > # subterfuge to let this pass a python3 parser; ugly > exec('raise exc_type, exc_value, exc_traceback') > > I'm using exec() here because a Python 3 interpreter will reject the 3 > argument form of raise. Elsewhere in my code I just call cs.py3.raise3() > with the requisite arguments. Note that the string passed to exec() is > hardwired, not obtained from elsewhere in any form. I'd try conditional imports, first: if sys.hexversion >= ...: from .compat_py3 import raise3 else: from .compat_py2 import raise3 But maybe this breaks with the setuptools pre-compilation shenanigans? At any rate, I didn't mean to make a general statement. Obviously, sometimes exec/eval is necessary. If for no other reason than because sometimes the requirement is to use exec (e.g. if you are implementing something equivalent to python -i, etc.). -- Devin ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor