Re: [Tutor] Figuring out selective actions in Python

2018-05-06 Thread Steven D'Aprano
On Fri, May 04, 2018 at 03:53:41PM -0400, Daniel Bosah wrote:
> Hello,
> 
> I'm trying to figure out how to do blank in blank things. For example, if I
> want to delete 5 MB ( or anything ) for every 20 MB, how would the could
> look like? I'm essentially trying to do an action in one order of the
> sequence out of an entire sequence.

Huh? Does your question have anything to do with Python? What do you 
mean, "do blank in blank things"?

Sounds like the old "Blankety-Blanks" game show...

https://en.wikipedia.org/wiki/Blankety_Blanks_%28Australian_game_show%29#Gameplay



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


[Tutor] Need help with a virtual environment mess

2018-05-06 Thread Jim
In a prior thread you guys helped me fix a problem with pip after I 
upgraded an installed version of python 3.6 on my Mint 18 system. Pip 
would not run in my python 3.6 virtual environment. The fix was to use 
synaptic to install python3-distutils. I thought everything was ok until 
I tried to run a old script from a different VE using python 3.5 which 
could not import tkinter.


I have 4 versions of python on this system:
system Python2 = 2.7.12 (default)
system Python3 = 3.5.2 (default)
a VE called env = 3.5.2
a Ve called env36 = 3.6.5

This is the error I get trying to import tkinter in env, I also get the 
same error if I try to import it in system python3.


jfb@jims-mint18 ~ $ source /home/jfb/EVs/env/bin/activate
(env) jfb@jims-mint18 ~ $ python
Python 3.5.2 (default, Nov 23 2017, 16:37:01)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tkinter as tk
Traceback (most recent call last):
  File "/usr/lib/python3.5/tkinter/__init__.py", line 36, in 
import _tkinter
ImportError: No module named '_tkinter'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "", line 1, in 
  File "/usr/lib/python3.5/tkinter/__init__.py", line 38, in 
raise ImportError(str(msg) + ', please install the python3-tk package')
ImportError: No module named '_tkinter', please install the python3-tk 
package

>>>

If I go to synaptic and install the python3-tk it installs version 3.6.5 
of the package and I can still not import tkinter in env with python 
3.5.2, but I can in env36 with python 3.6.5.


I don't know if it makes a difference but I installed python3.6 from
LP-PPA-jonathonf-python-3.6/now.

Thanks,  Jim


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


Re: [Tutor] Extract main text from HTML document

2018-05-06 Thread Mark Lawrence

On 05/05/18 18:59, Simon Connah wrote:

Hi,

I'm writing a very simple web scraper. It'll download a page from a
website and then store the result in a database of some sort. The
problem is that this will obviously include a whole heap of HTML,
JavaScript and maybe even some CSS. None of which is useful to me.

I was wondering if there was a way in which I could download a web
page and then just extract the main body of text without all of the
HTML.

The title is obviously easy but the main body of text could contain
all sorts of HTML and I'm interested to know how I might go about
removing the bits that are not needed but still keep the meaning of
the document intact.

Does anyone have any suggestions on this front at all?

Thanks for any help.

Simon.


A combination of requests http://docs.python-requests.org/en/master/ and 
beautiful soup https://www.crummy.com/software/BeautifulSoup/bs4/doc/ 
should fit the bill.  Both are installable with pip and are regarded as 
best of breed.


--
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] Extract main text from HTML document

2018-05-06 Thread Simon Connah
Thanks for the replies, everyone. Beautiful Soup looks like a good option.

My primary goal is to extract the main body text, the title and the
meta description from a web page and run it through one of the cloud
Natural Language processing services to find out some information that
I'd like to know and I'd like to do it to quite a few websites.

This is all for a little project I have in mind. I'm not even sure if
it'll work but it'll be fun to try. I might have to do some custom
work on top of what Beautiful Soup offers though as I need to get very
specific data in a certain format.

On 5 May 2018 at 22:43, boB Stepp  wrote:
> On Sat, May 5, 2018 at 12:59 PM, Simon Connah  wrote:
>
>> I was wondering if there was a way in which I could download a web
>> page and then just extract the main body of text without all of the
>> HTML.
>
> I do not have any experience with this, but I like to collect books.
> One of them [1] says on page 245:
>
> "Beautiful Soup is a module for extracting information from an HTML
> page (and is much better for this purpose than regular expressions)."
>
> I believe this topic has come up before on this list as well as the
> main Python list.  You may want to check it out.  It can be installed
> with pip.
>
> [1] "Automate the Boring Stuff with Python -- Practical Programming
> for Total Beginners" by Al Sweigart.
>
> HTH!
> --
> boB
> ___
> 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


Re: [Tutor] Python C extension - which method?

2018-05-06 Thread Brad M
If I may ask, what's the difference between these two?

1)
import ctypes
hello = ctypes.WinDLL('hello', use_last_error=True)

2)
from ctypes import cdll
hello = cdll.LoadLibrary('hello.dll')



Both of them can return "1980" from  this:

hello.c

#include 

__declspec(dllexport) int say_something()
{
return 1980;
}


On Sun, May 6, 2018 at 8:39 AM, Brad M  wrote:

> Does this have any downside? I have noticed that printf("HI") in my .DLL;
> doesn't really print anything.
> I am on windows.
>
> cdll.LoadLibrary('helloworld.dll')
>
>
>
> My next question is that I need to return an array or a list of address or
> int or some type of data, but
> if I returned a pointer to the array of some data type, how does the
> python cope with it?
>
> For instance, my plan is to have 3 functions:
>
> 1) a function that return all addresses that have a given value to python,
> say, 9001
> 2) then I do something with python so that values change, the target value
> is now 1009.
> 3) a second function that takes all the addresses as input and then return
> adddress that have values of 1009.
>
> 4) repeat 2 and 3 until there is only 1 or so of address which correct
> values.
> 5) A 3rd function that takes only 1 address and simply return the values
> at that address.
>
> So the whole point of having 1-4 is to find the one address that contain
> that values I want, and then
> all I do is to call the 3rd function to find the values at that address.
>
>
>
> So basically what I need to know is if the method I am using,
> cdll.LoadLibrary('helloworld.dll')
> is proper or I need some other method, and then I would like to find out
> how to handle the data returned.
> (address)
>
> Thanks!!!
>
>
>
> On Sun, May 6, 2018 at 5:44 AM, Stefan Behnel  wrote:
>
>> Hi,
>>
>> Brad M schrieb am 04.05.2018 um 11:30:
>> > I want to create a C-based memory scanner for Python, and so far this is
>> > how I do it:
>> >
>> > Python:
>> >
>> > from ctypes import cdll
>> > mydll = cdll.LoadLibrary('hello.dll')
>> > print(mydll.say_something())
>> >
>> > and hello.dll:
>> >
>> > #include 
>> > __declspec(dllexport) int say_something()
>> > {
>> > return 1980;
>> > }
>> >
>> > so the printout is "1980"
>> >
>> > Is this alright?
>>
>>
>> Depends on your needs and your C/C++ knowledge.
>>
>> If you have a shared library that provides the ready-made functionality,
>> and accessing that native code at all is more important than calling it
>> very quickly (e.g. you only do a few longish-running calls into it), then
>> wrapping a shared library with ctypes (or preferably cffi) is a good way
>> to
>> do it.
>>
>> Otherwise, try either a native wrapper generator like pybind11, or write
>> your wrapper in Cython.
>>
>> Specifically, if you are not just calling into an external library 1:1,
>> but
>> need to do (or can benefit from doing) non-trivial operations in native
>> code, definitely use Cython.
>>
>> http://cython.org
>>
>>
>> > I am aware that there is another much more complicated
>> > method such as this:
>> >
>> > https://tutorialedge.net/python/python-c-extensions-tutorial
>> /#building-and-installing-our-module
>>
>> Well, yes, it exists, but I advise against wrapping C code manually that
>> way. It's just too cumbersome and error prone. Leave it to the experts who
>> have already written their tools for you.
>>
>> Stefan
>>
>>
>> Disclosure: I'm a Cython core dev, so I'm biased and I absolutely know
>> what
>> I'm talking about.
>>
>> ___
>> 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] ValueError: Procedure probably called with too many arguments (8 bytes in excess)

2018-05-06 Thread Brad M
Hi all:

I am experimenting with python calling some .DLL and this is my setup:

scan.py
memscan = ctypes.WinDLL('mahdll', use_last_error=True)
print(memscan.say_something(1,2))

# So I pass to int to the DLL function.


DLL:

#include 

__declspec(dllexport) int say_something(int a, int b)
{
printf("Hello World");
return math(a, b);
}

int math(int a, int b)
{
return a + b;
}




# So I found it wont print "hello world"
and it give this error:

ValueError: Procedure probably called with too many arguments (8 bytes in
excess)

# Also, if I pass no argument to the function, it won't printf("Hello
world")
on the python interpreter or opens a console window to print it.


So what's the right thing to do to pass arguments to a DLL function?

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


Re: [Tutor] Extract main text from HTML document

2018-05-06 Thread Brian Lockwood
Two things. The first thing is that you can download the page as a string
and delete a everything between tags. Secondly It might be worth looking at
Udacity cs101 as this course is all about a search engine.
On Sat, 5 May 2018 at 22:27, Simon Connah  wrote:

> Hi,
>
> I'm writing a very simple web scraper. It'll download a page from a
> website and then store the result in a database of some sort. The
> problem is that this will obviously include a whole heap of HTML,
> JavaScript and maybe even some CSS. None of which is useful to me.
>
> I was wondering if there was a way in which I could download a web
> page and then just extract the main body of text without all of the
> HTML.
>
> The title is obviously easy but the main body of text could contain
> all sorts of HTML and I'm interested to know how I might go about
> removing the bits that are not needed but still keep the meaning of
> the document intact.
>
> Does anyone have any suggestions on this front at all?
>
> Thanks for any help.
>
> Simon.
> ___
> 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


Re: [Tutor] Python C extension - which method?

2018-05-06 Thread Brad M
Does this have any downside? I have noticed that printf("HI") in my .DLL;
doesn't really print anything.
I am on windows.

cdll.LoadLibrary('helloworld.dll')



My next question is that I need to return an array or a list of address or
int or some type of data, but
if I returned a pointer to the array of some data type, how does the python
cope with it?

For instance, my plan is to have 3 functions:

1) a function that return all addresses that have a given value to python,
say, 9001
2) then I do something with python so that values change, the target value
is now 1009.
3) a second function that takes all the addresses as input and then return
adddress that have values of 1009.

4) repeat 2 and 3 until there is only 1 or so of address which correct
values.
5) A 3rd function that takes only 1 address and simply return the values at
that address.

So the whole point of having 1-4 is to find the one address that contain
that values I want, and then
all I do is to call the 3rd function to find the values at that address.



So basically what I need to know is if the method I am using,
cdll.LoadLibrary('helloworld.dll')
is proper or I need some other method, and then I would like to find out
how to handle the data returned.
(address)

Thanks!!!



On Sun, May 6, 2018 at 5:44 AM, Stefan Behnel  wrote:

> Hi,
>
> Brad M schrieb am 04.05.2018 um 11:30:
> > I want to create a C-based memory scanner for Python, and so far this is
> > how I do it:
> >
> > Python:
> >
> > from ctypes import cdll
> > mydll = cdll.LoadLibrary('hello.dll')
> > print(mydll.say_something())
> >
> > and hello.dll:
> >
> > #include 
> > __declspec(dllexport) int say_something()
> > {
> > return 1980;
> > }
> >
> > so the printout is "1980"
> >
> > Is this alright?
>
>
> Depends on your needs and your C/C++ knowledge.
>
> If you have a shared library that provides the ready-made functionality,
> and accessing that native code at all is more important than calling it
> very quickly (e.g. you only do a few longish-running calls into it), then
> wrapping a shared library with ctypes (or preferably cffi) is a good way to
> do it.
>
> Otherwise, try either a native wrapper generator like pybind11, or write
> your wrapper in Cython.
>
> Specifically, if you are not just calling into an external library 1:1, but
> need to do (or can benefit from doing) non-trivial operations in native
> code, definitely use Cython.
>
> http://cython.org
>
>
> > I am aware that there is another much more complicated
> > method such as this:
> >
> > https://tutorialedge.net/python/python-c-extensions-
> tutorial/#building-and-installing-our-module
>
> Well, yes, it exists, but I advise against wrapping C code manually that
> way. It's just too cumbersome and error prone. Leave it to the experts who
> have already written their tools for you.
>
> Stefan
>
>
> Disclosure: I'm a Cython core dev, so I'm biased and I absolutely know what
> I'm talking about.
>
> ___
> 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] passing values and C pointers

2018-05-06 Thread Brad M
Hi all:

Although I have college C++ 101 and Python 101 down my belt, I wan't
taught how to read a reference manual to figure this out :(

Say I have an array of values, say addresses or int produced by a c module/
c function that's in a DLL , how do I pass that array back to
the python code?

from ctypes import cdll
mydll = cdll.LoadLibrary('mydll')
a = mydll.c_get_data()


or, as I have learned in C, I can use malloc to create a linked list(new
beast for me) and then return the head pointer to the previous C function.

But eventually I am going to pass that C pointer back to python, right?
1) how do i do that,
2) how do do work on that data on that pointer? let's say the pointer
points to a linked list.

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


Re: [Tutor] Python C extension - which method?

2018-05-06 Thread eryk sun
On Sun, May 6, 2018 at 12:49 AM, Brad M  wrote:
> If I may ask, what's the difference between these two?
>
> 1)
> import ctypes
> hello = ctypes.WinDLL('hello', use_last_error=True)
>
> 2)
> from ctypes import cdll
> hello = cdll.LoadLibrary('hello.dll')

Use ctypes.CDLL and ctypes.WinDLL instead of cdll.LoadLibrary and
windll.LoadLibrary. The latter is more typing for no benefit and
prevents using the constructor arguments: handle, mode (POSIX),
use_errno, and use_last_error (Windows). You need the latter two
options if the library requires C errno or Windows GetLastError(), in
which case you should use ctypes.get_errno() or
ctypes.get_last_error() to get the error values after a C function
call.

> Both of them can return "1980" from  this:
>
> hello.c
>
> #include 
>
> __declspec(dllexport) int say_something()
> {
> return 1980;
> }

CDLL is the cdecl calling convention, and WinDLL is stdcall. There is
no difference in 64-bit Windows (x64 ABI). In 32-bit Windows (x86
ABI), cdecl has the caller clean the stack (i.e. pop arguments), and
stdcall has the callee (the called function) clean the stack. cdecl
allows functions with a variable number of arguments, such as the CRT
printf function. In MSVC, cdecl is the default convention if you don't
declare a function as __stdcall. A library can export functions with
varying calling conventions, so in general you may need to mix CDLL
and WinDLL.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] passing values and C pointers

2018-05-06 Thread eryk sun
On Sun, May 6, 2018 at 2:17 AM, Brad M  wrote:
>
> Say I have an array of values, say addresses or int produced by a c module/
> c function that's in a DLL , how do I pass that array back to
> the python code?

C arrays are passed and returned automatically as pointers to the
first element. The array length has to be passed separately, unless
there's a known sentinel value.

A simple pattern is to let the caller allocate the array and pass a
pointer and the length. This gives the caller explicit control over
the lifetime of the array, which is especially simple for ctypes since
it uses reference-counted objects.

Say you have a function in C such as the following:

int
DLLAPI
get_data(int *data, size_t length)
{
size_t i;
for (i=0, i < length; i++) {
if (do_something(i, &data[i]) == -1) {
return -1; /* failure */
}
}
return 0; /* success */
}

In Python, set up and call this function as follows:

import ctypes

mydll = ctypes.CDLL('mydll')

# setup
mydll.get_data.argtypes = (
ctypes.POINTER(ctypes.c_int), # data
ctypes.c_size_t)  # length

# call
data = (ctypes.c_int * 10)()
status = mydll.get_data(data, len(data))
if status == -1:
raise MyDllException('get_data: ...')

for i, value in enumerate(data):
result = do_something_else(i, value)
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] How to separate UI code from program logic?

2018-05-06 Thread boB Stepp
I was solving a programming problem in one of my books concerning the
generation of a Collatz sequence
(https://en.wikipedia.org/wiki/Collatz_conjecture), and started to
wonder how I should separate my program's output from its logic.  It
seems like this should be obvious to me, but, unfortunately, it isn't.
The core functions from my program are:

#
def collatz(integer):
"""Returns the Collatz sequence number corresponding to integer.  integer
must be > 0, or the sequence will not converge to 1."""

if integer % 2 == 0:
return integer // 2
else:
return 3 * integer + 1

def generate_collatz_sequence(seed):
"""Generates a Collatz sequence starting from seed.
seed must be a positive integer, or the sequence will not
coverge to 1."""

counter = 0
collatz_number = seed
print("Collatz seed number: ", collatz_number)
while True:
counter += 1
collatz_number = collatz(collatz_number)
print("Collatz number", counter, ": ", collatz_number)
if collatz_number == 1:
print("The Collatz sequence has once again converged to 1!")
break
#

My understanding of best practice here is that I should not have any
print() calls inside my generate_collatz_sequence() function.  I
_could_ store the generated sequence in a list and return it, but that
does not seem like good use of RAM if some user-supplied seed value
led to kazillions of Collatz sequence numbers being generated.  As it
stands there will be no theoretical RAM issues as the numbers are
being generated and then outputted one at a time.  OTOH, if I created
some kind of display messages function, I don't see how I have gained
anything as these calls to a display message function would just be
taking the place of the print() calls.  The end result would be the
same -- display code interleaved with program logic code.  What am I
being dense about here?

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


Re: [Tutor] Need help with a virtual environment mess

2018-05-06 Thread boB Stepp
On Sun, May 6, 2018 at 11:05 AM, Jim  wrote:
> In a prior thread you guys helped me fix a problem with pip after I upgraded
> an installed version of python 3.6 on my Mint 18 system. Pip would not run
> in my python 3.6 virtual environment. The fix was to use synaptic to install
> python3-distutils. I thought everything was ok until I tried to run a old
> script from a different VE using python 3.5 which could not import tkinter.
>
> I have 4 versions of python on this system:
> system Python2 = 2.7.12 (default)
> system Python3 = 3.5.2 (default)
> a VE called env = 3.5.2
> a Ve called env36 = 3.6.5
>
> This is the error I get trying to import tkinter in env, I also get the same
> error if I try to import it in system python3.
>
> jfb@jims-mint18 ~ $ source /home/jfb/EVs/env/bin/activate
> (env) jfb@jims-mint18 ~ $ python
> Python 3.5.2 (default, Nov 23 2017, 16:37:01)
> [GCC 5.4.0 20160609] on linux
> Type "help", "copyright", "credits" or "license" for more information.
 import tkinter as tk
> Traceback (most recent call last):
>   File "/usr/lib/python3.5/tkinter/__init__.py", line 36, in 
> import _tkinter
> ImportError: No module named '_tkinter'
>
> During handling of the above exception, another exception occurred:
>
> Traceback (most recent call last):
>   File "", line 1, in 
>   File "/usr/lib/python3.5/tkinter/__init__.py", line 38, in 
> raise ImportError(str(msg) + ', please install the python3-tk package')
> ImportError: No module named '_tkinter', please install the python3-tk
> package

>
> If I go to synaptic and install the python3-tk it installs version 3.6.5 of
> the package and I can still not import tkinter in env with python 3.5.2, but
> I can in env36 with python 3.6.5.
>

As I have not yet tried to play around with virtual environments, I
may be about to do more harm than help, but I will plow ahead anyway!
~(:>))

My primitive understanding of installing Python versions that are
different from the system Python version into a virtual environment,
is that you have to install all dependencies you need from within that
virtual environment you created.  If I am correct about this then your
error messages suggest you need to install the tkinter stuff from
within that virtual environment using that virtual environment's pip.
Hopefully I am too far off from the truth here, but in any event, I
hope this helps you in your problem!

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


Re: [Tutor] How to separate UI code from program logic?

2018-05-06 Thread Alan Gauld via Tutor


On 6 May 2018, at 23:00, boB Stepp  wrote:

>I was solving a programming problem in one of my books concerning the
>generation of a Collatz sequence
>(https://en.wikipedia.org/wiki/Collatz_conjecture), and started to
>wonder how I should separate my program's output from its logic.  It
>seems like this should be obvious to me, but, unfortunately, it isn't.
>The core functions from my program are:
>#
>def collatz(integer):
>    """Returns the Collatz sequence number corresponding to integer.  integer
>    must be > 0, or the sequence will not converge to 1."""
>    if integer % 2 == 0:
>    return integer // 2
>    else:
>    return 3 * integer + 1
>def generate_collatz_sequence(seed):
>    """Generates a Collatz sequence starting from seed.
>    seed must be a positive integer, or the sequence will not
>    coverge to 1."""
>    counter = 0
>    collatz_number = seed
>    print("Collatz seed number: ", collatz_number)
>    while True:
>    counter += 1
>    collatz_number = collatz(collatz_number)
>    print("Collatz number", counter, ": ", collatz_number)
>    if collatz_number == 1:
>    print("The Collatz sequence has once again converged to 1!")
>    break
>#
>My understanding of best practice here is that I should not have any
>print() calls inside my generate_collatz_sequence() function.  I
>_could_ store the generated sequence in a list and return it, but that
>does not seem like good use of RAM if some user-supplied seed value
>led to kazillions of Collatz sequence numbers being generated.  


The clue is in that last word.
Write a generator function that yields the intermediate results.

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


Re: [Tutor] How to separate UI code from program logic?

2018-05-06 Thread boB Stepp
On Sun, May 6, 2018 at 5:05 PM, Alan Gauld  wrote:
> On 6 May 2018, at 23:00, boB Stepp  wrote:

>>My understanding of best practice here is that I should not have any
>>print() calls inside my generate_collatz_sequence() function.  I
>>_could_ store the generated sequence in a list and return it, but that
>>does not seem like good use of RAM if some user-supplied seed value
>>led to kazillions of Collatz sequence numbers being generated.
>
> The clue is in that last word.
> Write a generator function that yields the intermediate results.

Aha!  Of course the book I am poking around in does not even cover
generator functions ...  But I will plow ahead as usual and implement
your suggestion.  Thanks, Alan!



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


Re: [Tutor] How to separate UI code from program logic?

2018-05-06 Thread Mark Lawrence

On 06/05/18 22:59, boB Stepp wrote:

I was solving a programming problem in one of my books concerning the
generation of a Collatz sequence
(https://en.wikipedia.org/wiki/Collatz_conjecture), and started to
wonder how I should separate my program's output from its logic.  It
seems like this should be obvious to me, but, unfortunately, it isn't.
The core functions from my program are:

#
def collatz(integer):
 """Returns the Collatz sequence number corresponding to integer.  integer
 must be > 0, or the sequence will not converge to 1."""

 if integer % 2 == 0:
 return integer // 2
 else:
 return 3 * integer + 1

def generate_collatz_sequence(seed):
 """Generates a Collatz sequence starting from seed.
 seed must be a positive integer, or the sequence will not
 coverge to 1."""

 counter = 0
 collatz_number = seed
 print("Collatz seed number: ", collatz_number)
 while True:
 counter += 1
 collatz_number = collatz(collatz_number)
 print("Collatz number", counter, ": ", collatz_number)
 if collatz_number == 1:
 print("The Collatz sequence has once again converged to 1!")
 break
#

My understanding of best practice here is that I should not have any
print() calls inside my generate_collatz_sequence() function.  I
_could_ store the generated sequence in a list and return it, but that
does not seem like good use of RAM if some user-supplied seed value
led to kazillions of Collatz sequence numbers being generated.  As it
stands there will be no theoretical RAM issues as the numbers are
being generated and then outputted one at a time.  OTOH, if I created
some kind of display messages function, I don't see how I have gained
anything as these calls to a display message function would just be
taking the place of the print() calls.  The end result would be the
same -- display code interleaved with program logic code.  What am I
being dense about here?



You're not being dense, you're just trying to wrap your head around a 
difficult concept.  I suggest you read up on the model view controller 
pattern.  First hit on google 
https://www.tomdalling.com/blog/software-design/model-view-controller-explained/ 
seems as good as any.


--
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] How to separate UI code from program logic?

2018-05-06 Thread boB Stepp
On Sun, May 6, 2018 at 5:05 PM, Alan Gauld  wrote:
> On 6 May 2018, at 23:00, boB Stepp  wrote:

>>My understanding of best practice here is that I should not have any
>>print() calls inside my generate_collatz_sequence() function.  I
>>_could_ store the generated sequence in a list and return it, but that
>>does not seem like good use of RAM if some user-supplied seed value
>>led to kazillions of Collatz sequence numbers being generated.
>
> The clue is in that last word.
> Write a generator function that yields the intermediate results.

Ok.  I've been reading up on generators and playing around with them
today.  And then, per Alan's hint, tried to separate all display code
from my program logic code.  What was originally meant to be a
throw-away effort, has somehow mushroomed into something I hope
resembles a finished product.  The results I came up with are as
follows:

#

#!/usr/bin/env python3

"""This program will generate a Collatz sequence from a user-supplied positive
integer.  According to Wikipedia
(https://en.wikipedia.org/wiki/Collatz_conjecture):

"The Collatz conjecture is a conjecture in mathematics that concerns a
sequence defined as follows: start with any positive integer n. Then each
term is obtained from the previous term as follows: if the previous term is
even, the next term is one half the previous term. Otherwise, the next term
is 3 times the previous term plus 1. The conjecture is that no matter what
value of n, the sequence will always reach 1."
"""

def get_positive_integer():
"""Get a positive integer from the user."""

while True:
try:
integer = int(input("Please enter a positive integer:  "))
if integer > 0:
return integer
else:
print("That was not a positive integer!")
continue
except ValueError:
print("That was not an integer!")
continue

def display_collatz_numbers(seed, collatz_generator):
"""Display a Collatz sequence, one value per line, given the seed (Which
will be the first number in the sequence.) and a generator which will
yield the Collatz sequence."""

print("\nThe seed number: ", seed)
for sequence_index, number in enumerate(collatz_generator):
print("Sequence number", sequence_index + 1, ": ", number)

def ask_to_continue():
choice = input("Do you wish to generate another Collatz sequence?").lower()
return choice.startswith('y')

def get_collatz_number(integer):
"""Returns the Collatz sequence number corresponding to integer.  integer
must be > 0, or the sequence will not converge to 1."""

if integer % 2 == 0:
return integer // 2
else:
return 3 * integer + 1

def generate_collatz_sequence(seed):
"""Creates a generator, which will yield a Collatz sequence starting from
seed.  seed must be a positive integer, or the sequence will not converge to
1."""

collatz_number = seed
while True:
collatz_number = get_collatz_number(collatz_number)
yield collatz_number
if collatz_number == 1:
return

def main():
"""Run program."""

while True:
seed = get_positive_integer()
display_collatz_numbers(seed, generate_collatz_sequence(seed))
if ask_to_continue():
continue
else:
break

if __name__ == '__main__':
main()

#

Questions and comments:

1)  I am open to a general critique on making this code better.

2)  I spent a lot of effort trying to come up with a way to combine
the two functions, get_collatz_number() and
generate_collatz_sequence(), into something both more compact and more
readable, but I was unsuccessful.  I suspect there is a better way.
Is there?  And how would I do it?

3)  Is this the correct way to separate display code from program
logic code?  Is there a better way to do this?

4)  I think this is the first time I've actually tried to implement a
generator function.  Did I do a good Pythonic implementation of this?

As always, thanks!

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