Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Python Module: nift

Reply
Thread Tools

Python Module: nift

 
 
J
Guest
Posts: n/a
 
      02-08-2009
What are your thoughts on this module I created?

'''
A Python Module created by a High School Student.
Includes rev(), reet(), and leet().

Import nift

Function: nift.rev()
Description: Reverses a string
Usage: nift.rev('string')
Example: nift.rev('Testing function.')
Output: '.noitcnuf gnitseT'

Function: nift.reet()
Description: Reverses a string
and transforms to leet text.
Usage: nift.reet('string')
Example: nift.reet('Hello World!')
Output: 'dlr0W 0ll3H'

Function: nift.leet()
Description: Transforms a string
into leet text.
Usage: nift.leet('string')
Example: nift.leet('Hello there!')
Output: 'H3ll0 7h3r3!'

Setup:
* Save to Python Directory\Lib\ as nift.py
* Now you may import it by:
from nift import function
function()
OR
import nift
nift.function()

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* This Module and its functions were created for my own fun, also
*
* contributing to Inter-Society. I don't mind if anyone modifies
*
* this module or adds on to it, as long as you attribute it to
*
* Myself.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
'''

def rev(string):
list = []
final = ''
for letters in string:
list.append(letters)
list.reverse()
for letters in list:
final = final + letters
return final

def reet(string):
list = []
final = ''
for letters in string:
list.append(letters)
list.reverse()
for letters in list:
if letters == 'e' or letters == 'E':
letters = '3'
elif letters == 'a' or letters == 'A':
letters = '4'
elif letters == 'i' or letters == 'I':
letters = '1'
elif letters == 't' or letters == 'T':
letters = '7'
elif letters == 's' or letters == 'S':
letters = '5'
elif letters == 'o' or letters == 'O':
letters = '0'
elif letters == 'b' or letters == 'B':
letters = '8'
final = final + letters
return final

def leet(string):
list = []
final = ''
for letters in string:
if letters == 'e' or letters == 'E':
letters = '3'
elif letters == 'a' or letters == 'A':
letters = '4'
elif letters == 'i' or letters == 'I':
letters = '1'
elif letters == 't' or letters == 'T':
letters = '7'
elif letters == 's' or letters == 'S':
letters = '5'
elif letters == 'o' or letters == 'O':
letters = '0'
elif letters == 'b' or letters == 'B':
letters = '8'
list.append(letters)
for letters in list:
final = final + letters
return final
 
Reply With Quote
 
 
 
 
Chris Rebert
Guest
Posts: n/a
 
      02-08-2009
On Sun, Feb 8, 2009 at 10:42 AM, J <(E-Mail Removed)> wrote:
> What are your thoughts on this module I created?


* You should probably use individual docstrings for each function
rather than one giant module docstring
* Don't use 'list' as a variable name; it shadows the name of the
builtin list type
* You can use the .lower() or .upper() method of strings to get rid of
half the 'or'-s in leet() and reet(). Better yet, use a dict rather
than a long if-elif chain.
* To convert a list of strings to a single string, use
''.join(the_list) instead of:
final = ''
for letters in the_list:
final = final + letters #also, += is preferred in cases like this
* To convert a string to a list of characters, use list(string) instead of:
the_list = []
final = ''
for letters in string:
the_list.append(letters)

Cheers,
Chris

--
Follow the path of the Iguana...
http://rebertia.com
 
Reply With Quote
 
 
 
 
bearophileHUGS@lycos.com
Guest
Posts: n/a
 
      02-08-2009
More suggestions for a real-world Python programmer:
- There's code duplication, the original poster may express reet as a
composition of the other functions.
- A Python string/list/array can be inverted with [::-1]
- I suggest to convert the examples of the main doscstring into
doctests.
- The main docstring looks too much heavy.
- To convert many ASCII chars there's the str.translate method.
- Generally I suggest to learn to code in the small, using as little
code as possible.

Bye,
bearophile
 
Reply With Quote
 
Gabriel Genellina
Guest
Posts: n/a
 
      02-08-2009
En Sun, 08 Feb 2009 17:59:41 -0200, <(E-Mail Removed)> escribiˇ:

> More suggestions for a real-world Python programmer:
> - There's code duplication, the original poster may express reet as a
> composition of the other functions.
> - A Python string/list/array can be inverted with [::-1]
> - I suggest to convert the examples of the main doscstring into
> doctests.
> - The main docstring looks too much heavy.
> - To convert many ASCII chars there's the str.translate method.
> - Generally I suggest to learn to code in the small, using as little
> code as possible.


I completely agree with all the above suggestions, except this last one.
Ok, I think I know what you mean, but a beginner might understand this
completely wrong. Readability is important, and trying to compress too
much code into one single line should not be the ultimate goal.

--
Gabriel Genellina

 
Reply With Quote
 
Paul McGuire
Guest
Posts: n/a
 
      02-08-2009
On Feb 8, 12:42*pm, J <(E-Mail Removed)> wrote:
> What are your thoughts on this module I created?
>

Here are a few steps to illustrate some good basic Python idioms worth
learning:

Step 1: Replace many-branched if-elif with dict

While translating characters in a string is a special case that
usually warrants using str.translate, a more general-purpose technique
to learn is to define a dict that captures the various branching
options, and then use the selecting value as a key to access the
desired branch.
Here is a dict containing your branches:

LEET_LETTERS = {
"e" : "3",
"E" : "3",
"a" : "4",
"A" : "4",
"i" : "1",
"I" : "1",
"t" : "7",
"T" : "7",
"s" : "5",
"S" : "5",
"o" : "0",
"O" : "0",
"b" : "8",
"B" : "8",
}

Now you can implement leet() using access to the LEET_LETTERS
mapping. Here are 3 different versions, that illustrate the usual
options when accessing entries from a map:
1. Look before you leet, uh, I mean "leap" (check for key existence
before using)
2. Better to ask forgiveness than permission (just use the key and
handle the exception that gets raised if the key is not found - an
homage to Grace Hopper)
3. Slightly different strategy, using dict.get() method instead of key/
indexing into the dict

def leet1(string):
outlist = []
for letter in string:
if letter in LEET_LETTERS:
letter = LEET_LETTERS[letter]
outlist.append(letter)
return "".join(outlist)

def leet2(string):
outlist = []
for letter in string:
try:
letter = LEET_LETTERS[letter]
except KeyError:
pass
outlist.append(letter)
return "".join(outlist)

def leet3(string):
outlist = []
for letter in string:
outlist.append( LEET_LETTERS.get(letter,letter) )
return "".join(outlist)

You can test each in turn without changing your test code, just assign
leet to each of these variants in turn:

leet = leet1
print leet("Hello You Beautiful Sweet World!")

I'm partial to option number 3, so let me show you a few other helpful
tips.

By the way, you can do this if you are doing any kind if if-elif, such
as:

if a=="0":
fn_1()
elif a=="1":
fn_100()
elif a=="7":
fn_greater_than_five()
....

Instead you would write:

# note: values are the methods only, no ()'s
fns = { "0" : fn_1, "1" : fn_100, "7" : fn_greater_than_five }
if a in fns:
# get desired function from fns map, and call it
fns[a]()


Step 2: dict construction instead of {} syntax

LEET_LETTERS is so space-consuming, sometimes it is easier to use the
dict constructor with a list expression of list comprehension. That
is, instead of the built-in syntax P{}'s to define a dict, you can use
the dict constructor and pass a list of (key,value) tuples.

LEET_LETTERS = dict( [("E","3"), ("e","3"), ("A","4"),
("a","4"), ...] )

Well, my fingers are tired and I'm bored already, how about if we
could just list the two strings of key and value characters, and some
how build the tuples by pulling an item from each list one at a time.
Fortunately, that is what Python's zip() function does:

LEET_LETTERS = dict( zip("eEaAiItTsSoObB",
"33441177550088") )

(I've listed the key-value pairs one above the other to illustrate how
the mapping will work, but of course, that isn't required.)

Now if I want to add another leet-speak letter (like "6" for "G"), I
just add the two characters on the end of the two strings.


Step 3: Use list comprehension instead of explicit list.appends using
for loop

As was already mentioned in another post, ''.join
(list_of_characters_to_join_together) is preferred to final +=
next_letter_to_add_to_final. But there is also a nice short and clean
way to build up the list besides explicitly calling append in a loop.
Instead, use a list comprehension. To do this, you convert:

outlist = []
for letter in string:
outlist.append( LEET_LETTERS.get(letter,letter) )

to:
outlist = [ LEET_LETTERS.get(letter,letter) for letter in string ]


In fact, Python is so smart, you can skip the list entirely, and just
pass that expression inside the brackets (called a generator
expression) directly to ''.join:

final = ''.join( LEET_LETTERS.get(letter,letter) for letter in
string )

Just a "list" is not desired variable name since it masks the built-in
list type, I avoid "string" as a name since there is a commonly-used
string module. How about just plain "s"?

Here is the final version of leet - we even got rid of the variable
final, and just return the value that would have been assigned to it:

LEET_LETTERS = dict( zip("eEaAiItTsSoObB", "33441177550088") )
def leet(s):
return ''.join( LEET_LETTERS.get(c,c) for c in s )

Soon you'll be writing Python just like all the cool kids!

-- Paul
 
Reply With Quote
 
bearophileHUGS@lycos.com
Guest
Posts: n/a
 
      02-08-2009
Paul McGuire:
> LEET_LETTERS = dict( zip("eEaAiItTsSoObB", "33441177550088") )
> def leet(s):
> * * return ''.join( LEET_LETTERS.get(c,c) for c in s )


This may be better:

from string import maketrans

def leet(txt):
leet_chars = maketrans("eEaAiItTsSoObB", "33441177550088")
return txt.translate(leet_chars)

Moving leet_chars outside the function increases speed a bit.

Or for more expert Python programmers, you can add an attribute the
object function, I don't know if you like this:

from string import maketrans

def leet(txt):
return txt.translate(leet.chars)
leet.chars = maketrans("eEaAiItTsSoObB", "33441177550088")

It's executes maketrans once only and keeps the namespace tidy. So
it's a bit like a static variable in other languages.

Bye,
bearophile
 
Reply With Quote
 
Chris Rebert
Guest
Posts: n/a
 
      02-08-2009
On Sun, Feb 8, 2009 at 12:57 PM, Paul McGuire <(E-Mail Removed)> wrote:
> On Feb 8, 12:42 pm, J <(E-Mail Removed)> wrote:
>> What are your thoughts on this module I created?
>>

> Here are a few steps to illustrate some good basic Python idioms worth
> learning:
>
> Step 1: Replace many-branched if-elif with dict
>
> While translating characters in a string is a special case that
> usually warrants using str.translate, a more general-purpose technique
> to learn is to define a dict that captures the various branching
> options, and then use the selecting value as a key to access the
> desired branch.
> Here is a dict containing your branches:
>
> LEET_LETTERS = {
> "e" : "3",
> "E" : "3",
> "a" : "4",
> "A" : "4",
> "i" : "1",
> "I" : "1",
> "t" : "7",
> "T" : "7",
> "s" : "5",
> "S" : "5",
> "o" : "0",
> "O" : "0",
> "b" : "8",
> "B" : "8",
> }

<snip>
> LEET_LETTERS is so space-consuming, sometimes it is easier to use the
> dict constructor with a list expression of list comprehension. That
> is, instead of the built-in syntax P{}'s to define a dict, you can use
> the dict constructor and pass a list of (key,value) tuples.
>
> LEET_LETTERS = dict( [("E","3"), ("e","3"), ("A","4"),
> ("a","4"), ...] )
>
> Well, my fingers are tired and I'm bored already, how about if we
> could just list the two strings of key and value characters, and some
> how build the tuples by pulling an item from each list one at a time.
> Fortunately, that is what Python's zip() function does:
>
> LEET_LETTERS = dict( zip("eEaAiItTsSoObB",
> "33441177550088") )
>
> (I've listed the key-value pairs one above the other to illustrate how
> the mapping will work, but of course, that isn't required.)
>
> Now if I want to add another leet-speak letter (like "6" for "G"), I
> just add the two characters on the end of the two strings.


This I disagree with as being unnecessarily clever; the dict literal
is just fine as-is and the zip() makes it less clear. However, I would
definitely rewrite the dict to use less lines, which, after removing
the capital dupes (as I mentioned in my post, just use .lower()),
looks like:

LEET_LETTERS = {"e" : "3", "a" : "4", "i" : "1", "t" : "7", "s" : "5",
"o" : "0", "b" : "8"}

which is better, IMHO.

Cheers,
Chris

--
Follow the path of the Iguana...
http://rebertia.com
 
Reply With Quote
 
bearophileHUGS@lycos.com
Guest
Posts: n/a
 
      02-08-2009
Gabriel Genellina:
> bearophile:
> > - Generally I suggest to learn to code in the small, using as little
> > code as possible.

>
> I completely agree with all the above suggestions, except this last one. *
> Ok, I think I know what you mean, but a beginner might understand this *
> completely wrong. Readability is important, and trying to compress too *
> much code into one single line should not be the ultimate goal.


What I meant is to use less code as possible, keeping readability and
the original flexibility.

I can't stress enough the importance of writing less code. Every new
programmer has to learn how much important it is. Less code means less
bugs, less lines to edit and debug, etc. Less code is usually more
elegant, and often more readable (even if you take 3 times to read
each line it may be good anyway if you have 1/10 of the lines of code.
Recently in the "Java to Python" thread someone has posted some Java
class that is scary, you can probably write the same thing in
1/10-1/20 of the lines of code).

The sense for "elegance" in coding is of course (as in every other
human activity) something you learn after many years of exercise, it's
a matter of balance among many opposite things, a matter of
compromises, and it's also tight related with your personal style of
coding. Every programmer develops tastes and and one or more styles,
that other people may not appreciate much.

Bye,
bearophile
 
Reply With Quote
 
J
Guest
Posts: n/a
 
      02-08-2009
Thanks for your answers, especially Chris Rebert and Paul McGuire's. I
have a question:
How far does Python go in the Game Development field? (Using Python
only, no extensions)
 
Reply With Quote
 
Chris Rebert
Guest
Posts: n/a
 
      02-08-2009
On Sun, Feb 8, 2009 at 2:45 PM, J <(E-Mail Removed)> wrote:
> Thanks for your answers, especially Chris Rebert and Paul McGuire's. I
> have a question:
> How far does Python go in the Game Development field? (Using Python
> only, no extensions)


You pretty much need to integrate with some C(++) libraries in order
to write fancier games. However, you yourself don't need to write any
non-Python in order to utilize these libraries.
Pygame (http://www.pygame.org/) is a popular collection of multimedia
library bindings for Python.

Cheers,
Chris

--
Follow the path of the Iguana...
http://rebertia.com
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: [Python-Dev] [python-committers] [RELEASED] Python 3.2 rc 1 R. David Murray Python 0 01-17-2011 02:23 PM
Re: [Python-Dev] [python-committers] [RELEASED] Python 3.2 rc 1 Senthil Kumaran Python 0 01-17-2011 10:31 AM
Re: [Python-Dev] [Python-3000] RELEASED Python 2.6a1 and 3.0a3 Martin v. L÷wis Python 0 03-01-2008 10:51 PM
Re: [Python-Dev] [Python-3000] RELEASED Python 2.6a1 and 3.0a3 Paul Moore Python 0 03-01-2008 10:39 PM
Searching comp.lang.python/python-list@python.org (was: UTF-8) skip@pobox.com Python 0 03-10-2007 02:50 PM



Advertisments