Python Module: nift

Discussion in 'Python' started by J, Feb 8, 2009.

  1. J

    J Guest

    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
    J, Feb 8, 2009
    #1
    1. Advertising

  2. J

    Chris Rebert Guest

    On Sun, Feb 8, 2009 at 10:42 AM, J <> 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
    Chris Rebert, Feb 8, 2009
    #2
    1. Advertising

  3. J

    Guest

    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
    , Feb 8, 2009
    #3
  4. En Sun, 08 Feb 2009 17:59:41 -0200, <> 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
    Gabriel Genellina, Feb 8, 2009
    #4
  5. J

    Paul McGuire Guest

    On Feb 8, 12:42 pm, J <> 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
    Paul McGuire, Feb 8, 2009
    #5
  6. J

    Guest

    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
    , Feb 8, 2009
    #6
  7. J

    Chris Rebert Guest

    On Sun, Feb 8, 2009 at 12:57 PM, Paul McGuire <> wrote:
    > On Feb 8, 12:42 pm, J <> 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
    Chris Rebert, Feb 8, 2009
    #7
  8. J

    Guest

    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
    , Feb 8, 2009
    #8
  9. J

    J Guest

    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)
    J, Feb 8, 2009
    #9
  10. J

    Chris Rebert Guest

    On Sun, Feb 8, 2009 at 2:45 PM, J <> 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
    Chris Rebert, Feb 8, 2009
    #10
  11. J

    Paul McGuire Guest

    On Feb 8, 3:28 pm, Chris Rebert <> wrote:
    > 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"}
    >


    Maybe so, I was trying to illustrate zip() and maybe this was getting
    too far ahead for a new Python user.

    I *do* find that when initializing a list of characters (and for some
    reason a string wont do), then instead of this:

    vowels = ["A", "E", "I", "O", "U"]


    using the list constructor is much easier:

    vowels = list("AEIOU")


    Or more non-deterministically,

    sometimes = lambda s : if random.random() > 0.5 else []
    vowels = list("AEIOU") + sometimes("Y")


    -- Paul
    Paul McGuire, Feb 9, 2009
    #11
  12. J

    Terry Reedy Guest

    J wrote:
    > What are your thoughts on this module I created?
    >
    > '''
    > A Python Module created by a High School Student.
    > Includes rev(), reet(), and leet().


    Gutsy of you to post this.

    > Setup:
    > * Save to Python Directory\Lib\ as nift.py


    Add-in modules and packages like this should better go in
    pythonxy/Lib/site-packages, which is there just for this purpose.
    One can then easily see what add-ons ore present or not, or delete them,
    or avoid deletion with uninstallation, or move to another version of
    Python.

    tjr
    Terry Reedy, Feb 9, 2009
    #12
  13. On Sun, 08 Feb 2009 13:34:50 -0800, bearophileHUGS wrote:

    > 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 think a better description is, use as little code as you need, and no
    extra, but no less. As Einstein said about physics theories: "As simple
    as possible, but no simpler."


    > 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.


    [pedant]
    There's less code, fewer bugs and lines. Less applies to continuous
    quantities, like weight and "amount of code", and fewer applies to
    countable quantities.

    Don't worry, I frequently get it wrong too, and I'm a native English
    speaker :)


    > 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).


    Within reason, naturally. There's a reason why we write:

    for button in buttons:
    move(button, delta_x, delta_y)

    instead of

    for b in bs: mv(b, x, y)

    even though the second is significantly shorter. Keyword arguments versus
    positional arguments is another example where more verbose code is easier
    to read and maintain than shorter code.


    Also, I don't think there's much advantage in trying to push new
    programmers to reduce the amount of code. Until you're really comfortable
    with the language, you need training wheels and scaffolding in the form
    of verbose code. Sometimes you really don't appreciate Python's labour
    saving features until you've experienced how much labour there is to be
    saved.


    --
    Steven
    Steven D'Aprano, Feb 9, 2009
    #13
  14. J

    Guest

    Steven D'Aprano:
    > There's less code, fewer bugs and lines. Less applies to continuous
    > quantities, like weight and "amount of code", and fewer applies to
    > countable quantities.


    Thank you, I'll try to improve my use of the language.


    > Within reason, naturally. There's a reason why we write:
    > for button in buttons:
    >     move(button, delta_x, delta_y)
    > instead of
    > for b in bs: mv(b, x, y)
    > even though the second is significantly shorter.


    Often Shortening names and packing more stuff in single lines that
    deserve to be two lines aren't good ways to shorten code.


    > Also, I don't think there's much advantage in trying to push new
    > programmers to reduce the amount of code. Until you're really comfortable
    > with the language, you need training wheels and scaffolding in the form
    > of verbose code. Sometimes you really don't appreciate Python's labour
    > saving features until you've experienced how much labour there is to be
    > saved.


    I don't agree. When you learn to code you also have to learn what does
    it mean to write "good code", you have to learn that there are several
    things that are important beside writing a correct output, like good
    comments, well thought out names, good indentation, good idioms, quick
    running time, small memory usage, writing clear and readable code, and
    later develop elegance, the power of composition, abstraction,
    indirection, meta programming, etc. Among such things there's the
    importance of writing short programs. All such things are the seeds
    that will develop into the personal style of the future programmer.

    Such things are also useful for another purpose: to help the student
    understand that code is craftsmanship, so she/he/shi can (and is
    supposed to) be proud of the code that writes. This helps the student
    understand that programming isn't just an ugly way to tell orders to a
    moronic CPU, that helps develop appreciation for the act of writing
    code, because it becomes something you do also for the sake of it, as
    you do art, beside for usefulness. So you have to teach and show such
    things from more or less the beginning.

    Bye,
    bearophile
    , Feb 9, 2009
    #14
  15. J

    r0g Guest

    J 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)



    Hey J,

    Python's all about the libraries (extensions), you won't be able to do
    much without them but that's no big whoop. AFAIK most python libs are
    released under LGPL or BSD style licenses so there's pretty much no
    restriction on what you can use them for. A lot of games are written in
    C for performance reasons but most python gaming libs are just wrappers
    round C gaming libs and share the same names and methods so your
    knowledge should travel with you.

    As for which libs to use...

    There's PyGame which is a a good mature library for 2D stuff.

    Pyglet seem to be the most popular OpenGL lib for 3D stuff.

    You might also want to look at the "Blender Game Engine" and the free
    game "Yo Frankie", they use C for the heavy lifting and Python for
    scripting levels and stuff, it might be a good way to test the waters.

    Regards,

    Roger Heathcote.
    r0g, Feb 10, 2009
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Daniel Ortmann
    Replies:
    4
    Views:
    558
    Skip Montanaro
    Jul 2, 2003
  2. mathieu gontier
    Replies:
    1
    Views:
    312
    Alex Martelli
    Sep 1, 2004
  3. Mothra
    Replies:
    5
    Views:
    475
    Dennis Lee Bieber
    Apr 15, 2005
  4. Maric Michaud
    Replies:
    0
    Views:
    7,178
    Maric Michaud
    Jun 24, 2006
  5. Gabriel Genellina
    Replies:
    0
    Views:
    429
    Gabriel Genellina
    Nov 21, 2008
Loading...

Share This Page