Re: [Tutor] using the loop function while another

2012-10-10 Thread Alan Gauld

On 10/10/12 02:14, eryksun wrote:


another=input('Do you have another book to order for this student?',
   '\nEnter y for yes: ')


Remove the comma, and this will parse correctly.


Oops, yes good catch, don't know where that came from.


another=input('''
   Do you have another book to order for this student?
   Enter y for yes: ''')


This retains the leading spaces. You can use textwrap.dedent() to remove them:


I intended the spaces but didn't know about textwrap let alone dedent().
You learn something new every day! :-)


--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/

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


[Tutor] ctypes question

2012-10-10 Thread Albert-Jan Roskam
Hi,
 
I have a program that reads and writes files using ctypes. When I want it to 
read AND write (e.g. read a file, select some stuff and write that), the 
library returns a 'read-open' error. I think that the pointer to the file 
handle for read and write point to the same address. To test that hypothesis, I 
wrote the simplified code below. Problem is, that I can't make it work, let 
alone come up with a solution. ;-( How do I tell ctypes to use a 
particular chunck of memory, so read and write buffers do not mutually 
interfere? Maybe the 'offset' parameter of ctypes.byref?
 
import ctypes
import platform
import os
import tempfile

# load libraries
pf = platform.platform().lower()
if pf.startswith(win):
    libc = ctypes.cdll.msvcrt
    fopen = libc._fdopen
elif pf.startswith(lin):
    libc = ctypes.CDLL(libc.so.6)
    fopen = libc.fdopen
elif pf.startswith(darwin):
    libc = ctypes.CDLL(libc.dylib)
    fopen = libc.fdopen
else:
    raise NotImplementedError

# create test data
path = tempfile.gettempdir()
os.chdir(path)
fn = test.txt
lines = 100 * (100 * * + os.linesep)
with open(fn, wb) as f:
    f.write(lines)

 
# read test data (code does NOT work)
fh = fopen(ctypes.c_char_p(fn), rb)
fhPtr = ctypes.byref(ctypes.c_int(fh))
buff = ctypes.create_string_buffer(lines)
ret = libc.fread(buff, ctypes.c_int(1), ctypes.c_int(len(lines)), fhPtr)
print buff.value

 
# write test data (code does NOT work)
fn = somefile.txt
fh_out = fopen(ctypes.c_char_p(fn), wb)
fh_outPtr = ctypes.byref(ctypes.c_int(fh_out))
buff = ctypes.create_string_buffer(lines)
ret = libc.fwrite(buff, ctypes.c_int(1), ctypes.c_int(len(lines)), fh_outPtr)

 Thanks in advance!

Regards,
Albert-Jan


~~
All right, but apart from the sanitation, the medicine, education, wine, public 
order, irrigation, roads, a 
fresh water system, and public health, what have the Romans ever done for us?
~~ 
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] ctypes question

2012-10-10 Thread Peter Otten
Albert-Jan Roskam wrote:

 I have a program that reads and writes files using ctypes. When I want it
 to read AND write (e.g. read a file, select some stuff and write that),
 the library returns a 'read-open' error. I think that the pointer to the
 file handle for read and write point to the same address. 

In C fopen() returns a FILE *, open() returns an int. If your library 
expects a file handle, i. e. an int you can open the file in Python

f = open(filename, r+b)

and pass f.fileno() to the library.

 To test that
 hypothesis, I wrote the simplified code below. Problem is, that I can't
 make it work, let alone come up with a solution. ;-( How do I tell ctypes
 to use a particular chunck of memory, so read and write buffers do not
 mutually interfere? Maybe the 'offset' parameter of ctypes.byref?

I think you should turn to python-list instead of tutor with problems like 
this.

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


Re: [Tutor] ctypes question

2012-10-10 Thread Alan Gauld

On 10/10/12 11:02, Albert-Jan Roskam wrote:

I have a program that reads and writes files using ctypes.


Any particular reason why? That's not normally something I'd expect you 
to need ctypes for. Unless you just want to play with ctypes...



When I want it to read AND write (e.g. read a file, select some stuff and write 
that),

 the library returns a 'read-open' error.

Can we see the error messages please?


I think that the pointer to the file handle for read and write point to the 
same address.

 To test that hypothesis, I wrote the simplified code below.
 Problem is, that I can't make it work

Again, what exactly is going wrong. can't make it work is not too 
helpful, we need specific descriptions of what went wrong with any error 
messages.



How do I tell ctypes to use a particular chunck of memory,

 so read and write buffers do not mutually interfere?

In general you don't, you leave all that to the OS via the C libraries.
But you do need to think about what you are doing with the file. You 
shouldn't open the same file simultaneously for read and write. If you 
do need to do both use the combined 'rw' mode - but be aware that 
getting simultaneous read/write behaviour right is hard!



Maybe the 'offset' parameter of ctypes.byref?

import ctypes
import platform
import os
import tempfile

# load libraries
pf = platform.platform().lower()
if pf.startswith(win):
 libc = ctypes.cdll.msvcrt
 fopen = libc._fdopen
elif pf.startswith(lin):
 libc = ctypes.CDLL(libc.so.6)
 fopen = libc.fdopen
elif pf.startswith(darwin):
 libc = ctypes.CDLL(libc.dylib)
 fopen = libc.fdopen
else:
 raise NotImplementedError

# create test data
path = tempfile.gettempdir()
os.chdir(path)
fn = test.txt
lines = 100 * (100 * * + os.linesep)
with open(fn, wb) as f:
 f.write(lines)


# read test data (code does NOT work)
fh = fopen(ctypes.c_char_p(fn), rb)
fhPtr = ctypes.byref(ctypes.c_int(fh))
buff = ctypes.create_string_buffer(lines)
ret = libc.fread(buff, ctypes.c_int(1), ctypes.c_int(len(lines)), fhPtr)
print buff.value


# write test data (code does NOT work)
fn = somefile.txt
fh_out = fopen(ctypes.c_char_p(fn), wb)
fh_outPtr = ctypes.byref(ctypes.c_int(fh_out))
buff = ctypes.create_string_buffer(lines)
ret = libc.fwrite(buff, ctypes.c_int(1), ctypes.c_int(len(lines)), fh_outPtr)


Again, what does NOT work? Does it work if you comment out one of the 
blocks? I don't use ctypes much and certainly not for file handling so 
can't be sure if the code is correct or not - maybe ask on a ctypes 
forum for that...


--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/

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


Re: [Tutor] ctypes question

2012-10-10 Thread eryksun
On Wed, Oct 10, 2012 at 6:02 AM, Albert-Jan Roskam fo...@yahoo.com wrote:

 elif pf.startswith(lin):
 libc = ctypes.CDLL(libc.so.6)
 fopen = libc.fdopen

 fh = fopen(ctypes.c_char_p(fn), rb)
 fhPtr = ctypes.byref(ctypes.c_int(fh))
 buff = ctypes.create_string_buffer(lines)
 ret = libc.fread(buff, ctypes.c_int(1), ctypes.c_int(len(lines)), fhPtr)
 print buff.value

fdopen takes a file descriptor, not a filename. You're using it with a
filename like fopen (and you even called it fopen). Also, the byref
usage is incorrect. fopen() returns a pointer to a FILE. fread() needs
the pointer, not a reference to the pointer. You're giving it the
address of an int, but it expects to find a FILE. You can use
c_void_p(fh), or set the argtypes.

 from ctypes import *
 import ctypes.util

 libc = cdll.LoadLibrary(ctypes.util.find_library('c'))
 fopen = libc.fopen
 fread = libc.fread
 fread.argtypes = [c_void_p, c_size_t, c_size_t, c_void_p]

 fh = fopen(spam.txt, rb)
 buf = create_string_buffer(128)
 fread(buf, 1, 128, fh)
5
 buf.value
'spam\n'

To use fdopen, you can get a fileno() from an open Python file object:

 f = open(spam.txt, rb)

 fdopen = libc.fdopen
 fh = fdopen(f.fileno(), rb)
 fread(buf, 1, 128, fh)
5
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] ctypes question

2012-10-10 Thread Albert-Jan Roskam
- Original Message -
 From: eryksun eryk...@gmail.com
 To: Albert-Jan Roskam fo...@yahoo.com
 Cc: Python Mailing List tutor@python.org
 Sent: Wednesday, October 10, 2012 1:40 PM
 Subject: Re: [Tutor] ctypes question
 
 On Wed, Oct 10, 2012 at 6:02 AM, Albert-Jan Roskam fo...@yahoo.com 
 wrote:
 
 elif pf.startswith(lin):
     libc = ctypes.CDLL(libc.so.6)
     fopen = libc.fdopen
 
 fh = fopen(ctypes.c_char_p(fn), rb)
 fhPtr = ctypes.byref(ctypes.c_int(fh))
 buff = ctypes.create_string_buffer(lines)
 ret = libc.fread(buff, ctypes.c_int(1), ctypes.c_int(len(lines)), fhPtr)
 print buff.value
 
 fdopen takes a file descriptor, not a filename. You're using it with a
 filename like fopen (and you even called it fopen). Also, the byref
 usage is incorrect. fopen() returns a pointer to a FILE. fread() needs
 the pointer, not a reference to the pointer. You're giving it the
 address of an int, but it expects to find a FILE. You can use
 c_void_p(fh), or set the argtypes.

Aha, thanks. Yes, my total lack of knowledge of C speaks volumes here.
 
      from ctypes import *
      import ctypes.util
 
      libc = cdll.LoadLibrary(ctypes.util.find_library('c'))

That's a nice little trick!
 
      fopen = libc.fopen
      fread = libc.fread
      fread.argtypes = [c_void_p, c_size_t, c_size_t, c_void_p]
 
      fh = fopen(spam.txt, rb)
      buf = create_string_buffer(128)
      fread(buf, 1, 128, fh)
     5
      buf.value
     'spam\n'
 
 To use fdopen, you can get a fileno() from an open Python file object:
 
      f = open(spam.txt, rb)
 
      fdopen = libc.fdopen
      fh = fdopen(f.fileno(), rb)
      fread(buf, 1, 128, fh)
     5

Very insightful. I'll modify my code an see if it might solve my original 
problem. At least I've learnt a lot now!
 
Thanks all for replying!!
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


[Tutor] iterating over a changing list

2012-10-10 Thread Ed Owens
I'm trying to iterate over a list of elements, and make changes to the list
in front of the element I'm currently working with.  I can update the list,
but the  'for'  doesn't see the new element.  Here's the code:

import string

def add_element(items, point):
items = items[:point+1][:] + [['new']] + items[point+1:]
return items

def main():
pass

itmlst = [['a'],['b']]
itmcntr = 0

for itm in itmlst:
cmd = ''
while True:
cmd = raw_input('break, add, print:')
if cmd == 'break':
break
elif cmd == 'add':
itmlst = add_element(itmlst,itmcntr)
elif cmd == 'print':
print 'current item:', itm
else:
print 'invalid'
itmcntr += 1
print 'finished with', itm, 'in', itmlst
print len(itmlst), 'total items in list'

If I provide the inputs: [print add print break print break] at the prompt,
I get this output

current item: ['a']
current item: ['a']
finished with ['a'] in [['a'], ['new'], ['b']]
current item: ['b']
finished with ['b'] in [['a'], ['new'], ['b']]
3 total items in list

The new element got added, but it wasn't used in the iteration over the list
of items. Other than setting up a counter and calling len() each loop, is
there some way to have the changing list recognized within the for loop?

Thanks in advance for any help.

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


[Tutor] What can I do if I'm banned from a website??

2012-10-10 Thread Benjamin Fishbein
I've been scraping info from a website with a url program I wrote. But now I 
can't open their webpage, no matter which web browser I use. I think they've 
somehow blocked me. How can I get back in? Is it a temporary block? And can I 
get in with the same computer from a different wifi?

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


Re: [Tutor] What can I do if I'm banned from a website??

2012-10-10 Thread James Reynolds
On Wed, Oct 10, 2012 at 4:35 PM, Benjamin Fishbein bfishbei...@gmail.comwrote:

 I've been scraping info from a website with a url program I wrote. But now
 I can't open their webpage, no matter which web browser I use. I think
 they've somehow blocked me. How can I get back in? Is it a temporary block?
 And can I get in with the same computer from a different wifi?

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


A few thoughts:

1. Try using a proxy.
2. Ask the webadmin (nicely) to unban you
3. Use requests / urllib3 to se connection pooling
4. See if the site has an API designed for data extraction.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] What can I do if I'm banned from a website??

2012-10-10 Thread c smith
how could someone know enough to write their own web-scraping program and
NOT know that this is not about python or how to get around this problem?
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] iterating over a changing list

2012-10-10 Thread Mark Lawrence

On 10/10/2012 20:52, Ed Owens wrote:

I'm trying to iterate over a list of elements, and make changes to the list
in front of the element I'm currently working with.  I can update the list,
but the  'for'  doesn't see the new element.  Here's the code:

import string

def add_element(items, point):
 items = items[:point+1][:] + [['new']] + items[point+1:]
 return items

def main():
 pass

itmlst = [['a'],['b']]
itmcntr = 0

for itm in itmlst:
 cmd = ''
 while True:
 cmd = raw_input('break, add, print:')
 if cmd == 'break':
 break
 elif cmd == 'add':
 itmlst = add_element(itmlst,itmcntr)
 elif cmd == 'print':
 print 'current item:', itm
 else:
 print 'invalid'
 itmcntr += 1
 print 'finished with', itm, 'in', itmlst
print len(itmlst), 'total items in list'

If I provide the inputs: [print add print break print break] at the prompt,
I get this output

current item: ['a']
current item: ['a']
finished with ['a'] in [['a'], ['new'], ['b']]
current item: ['b']
finished with ['b'] in [['a'], ['new'], ['b']]
3 total items in list

The new element got added, but it wasn't used in the iteration over the list
of items. Other than setting up a counter and calling len() each loop, is
there some way to have the changing list recognized within the for loop?

Thanks in advance for any help.

Ed



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



Usually handled by iterating over a copy of the list.

for itm in itmlst[:]:

--
Cheers.

Mark Lawrence.

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


Re: [Tutor] What can I do if I'm banned from a website??

2012-10-10 Thread Mark Lawrence

On 10/10/2012 21:35, Benjamin Fishbein wrote:

I've been scraping info from a website with a url program I wrote. But now I 
can't open their webpage, no matter which web browser I use. I think they've 
somehow blocked me. How can I get back in? Is it a temporary block? And can I 
get in with the same computer from a different wifi?

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



Grovel?  Bribery?  Threaten violence?  Don't break their Ts  Cs in the 
first place? And what has this got to do with Python?


--
Cheers.

Mark Lawrence.

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


Re: [Tutor] What can I do if I'm banned from a website??

2012-10-10 Thread Walter Prins
Hi

On 10 October 2012 21:35, Benjamin Fishbein bfishbei...@gmail.com wrote:
 I've been scraping info from a website with a url program I wrote. But now I 
 can't open their webpage, no matter which web browser I use. I think they've 
 somehow blocked me. How can I get back in? Is it a temporary block? And can I 
 get in with the same computer from a different wifi?

Hard to know for certain what they've done, perhaps they've blocked
your IP. You can try connecting from another IP and see if that works.

2 points:
1) If you're going to be scraping websites, you should always play
nice with the web-server -- throttle your requests (put some random
delay between them) so they don't hammer the web-server too hard.  Not
doing this will enrage any webmaster.  He'll be very quick to figure
out why his website's being hammered, from where (the IP) and then
block you.  You'd probably do the same if you ran a website and you
noticed some particular IP hammering your site..
2) You should ideally always respect websites wishes regarding bots
and scraping.   If they don't want automated bots to be scraping them
then you should really not scrape that site.  And if you're going to
disregard their wishes and scrape it anyway (not recommended), then
all bets are off and you'll have to fly under the radar and ensure
that your scraping app looks as much like a browser as possible
(probably using modified headers that looks like what a browser will
send) and behaves as much like a human operator driving a browser as
possible, or you'll find yourself blocked as you've experienced above.

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


Re: [Tutor] iterating over a changing list

2012-10-10 Thread Dave Angel
On 10/10/2012 03:52 PM, Ed Owens wrote:
 I'm trying to iterate over a list of elements, and make changes to the list
 in front of the element I'm currently working with.  I can update the list,
 but the  'for'  doesn't see the new element.  Here's the code:

 import string

 def add_element(items, point):
 items = items[:point+1][:] + [['new']] + items[point+1:]
 return items
This function doesn't change its input object at all, it's just creates
and returns a new one.
 def main():
 pass

 itmlst = [['a'],['b']]
 itmcntr = 0

 for itm in itmlst:
 cmd = ''
 while True:
 cmd = raw_input('break, add, print:')
 if cmd == 'break':
 break
 elif cmd == 'add':
 itmlst = add_element(itmlst,itmcntr)

Now you've created a brand new list, and bound it to the itemlst
variable, but you're still iterating over the original list.

 elif cmd == 'print':
 print 'current item:', itm
 else:
 print 'invalid'
 itmcntr += 1
 print 'finished with', itm, 'in', itmlst
 print len(itmlst), 'total items in list'

 If I provide the inputs: [print add print break print break] at the prompt,
 I get this output

 current item: ['a']
 current item: ['a']
 finished with ['a'] in [['a'], ['new'], ['b']]
 current item: ['b']
 finished with ['b'] in [['a'], ['new'], ['b']]
 3 total items in list

 The new element got added, but it wasn't used in the iteration over the list
 of items. Other than setting up a counter and calling len() each loop, is
 there some way to have the changing list recognized within the for loop?



Usually, people have the reverse problem, one of seeming to stutter on
one of the items, or skipping one.  And the cure for either of those is
(as Mark tried to point out) to make a new list object to iterate over.

if you're sure you want to insert items in the original list that you're
looping on, then you need to change two places.  One is the
add_element() function needs to either use the insert() or an equivalent
set of slices.  use the insert() method, since it's easier.  And don't
bother returning the list, since you're not creating a new one. 
Convention is to either return a new object, or modify an object in
place, but not both.

The other place to change is the place where you call that function.  It
should NOT bind the variable to the return value, since it doesn't want
a new list object.

I haven't studied the rest of your code, as it didn't make much sense to
me.  But it's probably a simplified version of whatever you are trying
to do, so that should be fine.



-- 

DaveA

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


Re: [Tutor] iterating over a changing list

2012-10-10 Thread eryksun
On Wed, Oct 10, 2012 at 3:52 PM, Ed Owens eowens0...@gmx.com wrote:

 import string

Why are you importing string? Most string functions one would need
are methods of str/unicode. Sometimes string is still required,
however.

 def add_element(items, point):
 items = items[:point+1][:] + [['new']] + items[point+1:]
 return items

items[:point+1][:] creates a copy of part of the list with the slice
[:point+1], and then it copies the copy with the slice [:].

Redundant operations aside, this is returning a new list object.
That's not going to work since the loop iterator is bound to the
original list. You can't rebind a listiterator in the middle of a for
loop.

Also, generally avoid mutating a list while iterating over it.
listiterator is just incrementing an index, so modifying the size of
the list can produce nonsense (e.g. if you remove the current item,
the next item will be skipped). Instead, create an empty list and
append() to it.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] What can I do if I'm banned from a website??

2012-10-10 Thread Steven D'Aprano

On 11/10/12 07:35, Benjamin Fishbein wrote:


I've been scraping info from a website with a url program I wrote. But
now I can't open their webpage, no matter which web browser I use. I
think they've somehow blocked me. How can I get back in? Is it a
temporary block?


How the hell would we know??? Ask the people running the web site.

If you have been breaking the terms and conditions of the web site, you
could have broken the law (computer trespass). I don't say this because
I approve of or agree with the law, but when you scrape websites with
anything other than a browser, that's the chance you take.



And can I get in with the same computer from a different wifi?


*rolls eyes*

You've been blocked once. You want to get blocked again?

A lot of this depends on what the data is, why it is put on the web in
the first place, and what you intend doing with it.

Wait a week and see if the block is undone. Then:

* If the web site gives you an official API for fetching data, USE IT.

* If not, keep to their web site TC. If the TC allows scraping under
  conditions (usually something on the lines of limiting how fast you can
  scrape, or at what times), OBEY THOSE CONDITIONS and don't be selfish.

* If you think the webmaster will be reasonable, ask permission first.
  (I don't recommend that you volunteer the information that you were
  already blocked once.) If he's not a dick, he'll probably say yes,
  under conditions (again, usually to do with time and speed).

* If you insist in disregarding their TC, don't be a dick about it.
  Always be an ethical scraper. If the police come knocking, at least
  you can say that you tried to avoid any harm from your actions. It
  could make the difference between jail and a good behaviour bond.

  - Make sure you download slowly: pause for at least a few seconds
between each download, or even a minute or three.

  - Limit the rate that you download: you might be on high speed ADSL2,
but the faster you slurp files from the website, the less bandwidth
they have for others.

  - Use a cache so you aren't hitting the website again and again for
the same files.

  - Obey robots.txt.


Consider using a random pause between (say) 0 and 90 seconds between
downloads to to more accurately mimic a human using a browser. Also
consider changing your user-agent. Ethical scraping suggests putting
your contact details in the user-agent string. Defensive scraping
suggests mimicking Internet Explorer as much as possible.

More about ethical scraping:

http://stackoverflow.com/questions/4384493/how-can-i-ethically-and-legally-scrape-data-from-a-public-web-site



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


Re: [Tutor] Why difference between printing string typing its object reference at the prompt?

2012-10-10 Thread boB Stepp
On Tue, Oct 9, 2012 at 4:29 AM, eryksun eryk...@gmail.com wrote:
snip
 Python 3 lets you use any Unicode letter as an identifier, including
 letter modifiers (Lm) and number letters (Nl). For example:

  aꘌꘌb = True
  aꘌꘌb
 True

  Ⅰ, Ⅱ, Ⅲ, Ⅳ, Ⅴ = range(1, 6)
  Ⅰ, Ⅱ, Ⅲ, Ⅳ, Ⅴ
 (1, 2, 3, 4, 5)

Is doing this considered good programming practice? I recall there was
a recent discussion about using the actual characters in formulas
instead of descriptive names, where this would make more sense to
people knowledgeable in the field using the formulas; however,
descriptive names might be better for those who don't have that
specialty knowledge. Is there a Python community consensus on how and
when it is appropriate (if ever) to use Unicode characters as
identifiers?

 A potential gotcha in Unicode is the design choice to have both
 [C]omposed and [D]ecomposed forms of characters. For example:

  from unicodedata import name, normalize

  s1 = ü
  name(s1)
 'LATIN SMALL LETTER U WITH DIAERESIS'

  s2 = normalize(NFD, s1)
  list(map(name, s2))
 ['LATIN SMALL LETTER U', 'COMBINING DIAERESIS']

 These combine as one glyph when printed:

  print(s2)
 ü

 Different forms of the 'same' character won't compare as equal unless
 you first normalize them to the same form:

  s1 == s2
 False
  normalize(NFC, s1) == normalize(NFC, s2)
 True

This looks to make alphabetical sorting potentially much more complex.
I will have to give this some thought once I know more.

 I don't see a mention of byte strings mentioned in the index of my
 text. Are these just the ASCII character set?

After seeing your explanation below, I was able to find the relevant
material in my book. It was under bytes type and bytearray type.
For some reason these categories did not click in my head as what
Steve was addressing.

 A bytes object (and its mutable cousin bytearray) is a sequence of
 numbers, each in the range of a byte (0-255). bytes literals start
 with b, such as b'spam' and can only use ASCII characters, as does the
 repr of bytes. Slicing returns a new bytes object, but an index or
 iteration returns integer values:

  b'spam'[:3]
 b'spa'
  b'spam'[0]
 115
  list(b'spam')
 [115, 112, 97, 109]

 bytes have string methods as a convenience, such as find, split, and
 partition. They also have the method decode(), which uses a specified
 encoding such as utf-8 to create a string from an encoded bytes
 sequence.

What is the intended use of byte types?

Thanks! This continues to be quite informative and this thread is
greatly helping me to make better sense of the information that I am
self-studying.
-- 
Cheers!
boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Why difference between printing string typing its object reference at the prompt?

2012-10-10 Thread Steven D'Aprano

On 11/10/12 12:23, boB Stepp wrote:

On Tue, Oct 9, 2012 at 4:29 AM, eryksuneryk...@gmail.com  wrote:
snip

Python 3 lets you use any Unicode letter as an identifier, including
letter modifiers (Lm) and number letters (Nl). For example:

   aꘌꘌb = True
   aꘌꘌb
 True

   Ⅰ, Ⅱ, Ⅲ, Ⅳ, Ⅴ = range(1, 6)
   Ⅰ, Ⅱ, Ⅲ, Ⅳ, Ⅴ
 (1, 2, 3, 4, 5)


Is doing this considered good programming practice?


Not really, but it depends who is doing it and why.

If you have a piece of code that is only going to be maintained by people
speaking French, with French keyboards, then why not use French words for
identifiers? That includes those French letters with accents. Python 3
lets you do so.

Silly bits of code like Ⅳ = 4 (or worse, Ⅳ = 9) should be avoided because
they are silly, not because they are illegal. That's about the same as
using:

eine, zwei, drei, vier, fünf = range(1, 6)

in code intended to be read by English speakers, only even harder to type.

Remember that programmers *discourage* most misspellings of words (with a
few exceptions, usually abbreviations):

number_of_pages = 42

is preferred to:

nombar_off_paiges = 42


But for non-English speakers, most languages *force* them to either
write code in Foreign (foreign *to them*), or to misspell words. Allowing
Unicode identifiers means that they can write in their native tongue,
using correct spelling, *if they so choose*.

Of course, if you want your code to be readable world-wide, stick to
English :)



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


Re: [Tutor] iterating over a changing list

2012-10-10 Thread Steven D'Aprano

On 11/10/12 08:49, eryksun wrote:


Also, generally avoid mutating a list while iterating over it.
listiterator is just incrementing an index, so modifying the size of
the list can produce nonsense (e.g. if you remove the current item,
the next item will be skipped). Instead, create an empty list and
append() to it.



If you absolutely have to modify the list you are iterating over,
iterate over it backwards:


# this doesn't work correctly
for i in range(len(mylist)):
x = mylist[i]
if x  0:
del mylist[i]


# this does
for i in range(len(mylist)-1, -1, -1):
x = mylist[i]
if x  0:
del mylist[i]


But really, don't do that either. Iterate over a copy, or make
a new list with the items you want. It's faster and easier.



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