Re: creating class objects inside methods

2009-10-06 Thread Rhodri James

On Sun, 04 Oct 2009 19:44:48 +0100, horos11 horo...@gmail.com wrote:

[somehow managing to trim all other attributions: he's the innermost,
then me next]


 Thanks for the info, but a couple of points:

 1. it wasn't meant to be production code, simply a way to teach
 python.

Speaking as someone who does teach Python, Ew, no!  If you start by
teaching people bad habits, every educator who comes along afterwards
will curse your name.  That includes teaching yourself.


No offense, but I disagree. By programming without regards to pre-
existing style or convention I learned far more than I otherwise would
have if I had simply mimicked someone else.

And I still think that unbridled assignment - especially assignment
that can change the operational semantics of surrounding terms, at a
distance no less - is a horrid thing.


[snip]

Thank you for providing a perfect example of my point.  How are you
getting on unlearning that assumption?

Pretty much every assignment in every language changes the operational
semantics of surrounding terms.  Most such changes are trivial, but for
an obvious example consider programs running finite state machines.
When you change the state variable, you change what the program will
do in the future, usually in fairly major ways that may not be visible
from wherever your assignment takes place.

I'm hardly an expert in the area, but that does seem to be the point
of a lot of object-oriented design.

--
Rhodri James *-* Wildebeest Herder to the Masses
--
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread Carl Banks
On Oct 3, 10:12 pm, horos11 horo...@gmail.com wrote:
   a

  __main__.Myclass instance at 0x95cd3ec b

  __main__.Myclass instance at 0x95cd5ac

  What's the problem?

 Like I said, the code was a sample of what I was trying to do, not the
 entire thing.. I just wanted to see if the metaphor was kosher.

 It sounds to me from your answer that this is unexpected behavior, so
 I'll go ahead and post the whole thing. My guess is that it is a
 python bug..

Sure.


 Run it (a simple puzzle game solved by breadth first search), and the
 first time state() is called inside the method, it calls __init__.
 Second time, and therafter, it calls __call__. I've highlighted where
 the code fails by putting a pdb.set_trace().

 Anyways, I've got a workaround (simply pass in any new objects needed
 from the caller), but it is truly annoying that python is either
 misleading or broken in this way.

 Attached find code, does not work vs. 2.6..
[snip]

I don't believe you couldn't reduce that to something simpler.

Anyway, I didn't bother reading all the code or running it, but I had
a suspicion what is was so I looked for it and saw what I was looking
for.

Here's you class statement:


 class state:


Now here's some code that appears much later at the top level:


     else:
         seen_states.add(curstate.to_string())
         for state in curstate.next_states():
             if not state.to_string() in seen_states:
                 dq.append(state)

                 print Trying..\n
                 state.print_board()
                 print \n


Whoops.  It looks like you rebound the global variable state to a
new value, which makes the class no longer accessible by that name.

My immediate suggestion is to change the name of the class, and to
capitalize the first letter.  state is a terrible name for a class.
Class instances, almost by default, maintain state, so naming a class
state says almost nothing about what the class is.  Something like
GameState or PlayerState would be better.

Here is some reading material that can help you adjust your coding
style to help avoid such errors in the future:

http://www.python.org/dev/peps/pep-0008


Carl Banks
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread Carl Banks
On Oct 3, 10:34 pm, horos11 horo...@gmail.com wrote:
 Anyways, I see what's going on here:

 With the line,

 for state in curstate.next_states():
     if not state.to_string() in seen_states:
         dq.append(state)

 Inadvertently using the name of a module as a variable seems to be
 causing this.

Nope, unless by module you meant class.


 In any case, this shouldn't cause issues with constructors, so I'd
 call this a bug..

It's not a bug.  In Python classes and global variables share the same
namespace.

Don't you think you should learn a bit more about how Python manages
objects and namespaces before going around calling things bugs?


Carl Banks
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread horos11
Carl,

Thanks for the info, but a couple of points:

1. it wasn't meant to be production code, simply a way to teach
python.

2. this should either be a compile time or a runtime error.

'Actions at a distance' like this are deadly both to productivity and
to correctness - not only is this a runtime error, it is a *silent*
runtime error. Any other language I know would catch this, whether it
be lua, java, or perl.

Saying that 'whoa, this coding error should be handled by naming
convention' may be the only practical way of getting around this
limitation, but it is a limitation nonetheless, and a pretty big one.

Ed



O
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread horos11

 It's not a bug.  In Python classes and global variables share the same
 namespace.

 Don't you think you should learn a bit more about how Python manages
 objects and namespaces before going around calling things bugs?

 Carl Banks

No, I don't think so..

Say you went to another country, where the people wore lead shoes,
hence not only going slower, but getting lead poisoning from time to
time.

Pointing out that shoes made of fabric might just be better should not
be heresy.

In this case, I think the overall goal was syntax simplicity, but it
sure as hell makes things confusing. No warning, or anything. The sane
behavior IMO would be to disallow the assignment unless put through a
special function, something like:

class(state) = ...

After all, python does have a precedent when you try to join, when:

:.join([1,2])

does not work because [1,2] is an array of ints, whereas

: . join( str(x) for x in [1,2])

does.

Ed
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread Carl Banks
On Oct 3, 11:14 pm, horos11 horo...@gmail.com wrote:
 Carl,

 Thanks for the info, but a couple of points:

     1. it wasn't meant to be production code, simply a way to teach
 python.

I understand, and if you think it's overkill for your pedagogical
application then feel free not to follow the suggestions I gave you.


     2. this should either be a compile time or a runtime error.

 'Actions at a distance' like this are deadly both to productivity and
 to correctness - not only is this a runtime error, it is a *silent*
 runtime error. Any other language I know would catch this, whether it
 be lua, java, or perl.

I'm afraid that's just not reasonable given the nature of classes in
Python.  Python made a deliberate design trade-off by treating classes
as first-class objects.  This decision carries benefits and
drawbacks.  You've seen one of the drawbacks.  Benefits include
simpler data model and increased opportunities for dynamicism.  Perl,
Java, and Lua made the opposite choice, thus they are able to catch
the above mistake.

You could argue that Python made the wrong choice, and that classes
ought not to be first-class objects.  Fine.  But it didn't, and the
protection you seek is sacrificed.

I suggest looking at tools like PyChecker and PyLint.  I don't know if
they'd have found your error in this case, but they can find a lot of
problems Python itself misses.


 Saying that 'whoa, this coding error should be handled by naming
 convention' may be the only practical way of getting around this
 limitation, but it is a limitation nonetheless, and a pretty big one.

I believe it's a miniscule limitation in practice.  It seems like a
big deal but doesn't actually happen much.  YMMV.


Carl Banks
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread Dave Angel

horos11 wrote:

Carl,

Thanks for the info, but a couple of points:

1. it wasn't meant to be production code, simply a way to teach
python.

2. this should either be a compile time or a runtime error.

'Actions at a distance' like this are deadly both to productivity and
to correctness - not only is this a runtime error, it is a *silent*
runtime error. Any other language I know would catch this, whether it
be lua, java, or perl.

Saying that 'whoa, this coding error should be handled by naming
convention' may be the only practical way of getting around this
limitation, but it is a limitation nonetheless, and a pretty big one.

Ed


  
The bug in your code that we're discussing is caused because you rebound 
a global attribute to a new value, and lost the original object..  Your 
complaint is that when the global name happens to reference a class, and 
the new value doesn't,  you think the compiler should give an error.


If you would call this a limitation of Python, and think it should be 
fixed, then you clearly do not understand the language or its 
philosophy.  I can't compare to either lua or perl, but Java is a vastly 
different language from Python, and this type of thing is at the heart 
of the difference.  In Java you must declare the types of everything at 
compile time (except they had to make a big hole for collections), and 
the compiler is therefore told much about the possible behavior of each 
variable.


In Python you declare nothing, and much of the power of the language 
comes from the fact that every construct is a first-class object.  
Function definitions are fancy literal values for function objects, 
class declarations are just one of the ways of making a factory 
function, and classes themselves are instances of metaclasses.  You can 
declare new objects that mimic existing ones without having to define a 
new class that derives from the old class (duck-typing).  And you can 
frequently reuse the runtime semantics intended for one purpose to 
accomplish something very different.


Python also deliberately doesn't have a notion of constant 
declaration, nor private.  It doesn't have the notion of a library (or 
class) building a sealed implementation which cannot be customized.


What Python offers for many of these is some conventions.  Names 
starting with leading underscores are private by convention.  Names 
all uppercase are constant.  Names starting with an uppercase letter 
are classes.  But rather than trying to make a language definition of 
each of these terms, it's just a convention, observed among the 
consenting adults (?) cooperating in the codebase.


I'm not saying (here) whether Python is better or worse than the 
languages which are strongly typed at compile time, but just that it's a 
deliberate set of design decisions.  And special-casing one or two of 
the more obscure danger spots is not in keeping with the Python 
philosophy.  Further, I don't see that you did anything that the runtime 
should disallow.  You assigned a new value to the 'state' attribute.  
And when you tried to call it, it called the __str__() method of that 
object.


DaveA

--
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread Hendrik van Rooyen
On Sunday, 4 October 2009 08:14:08 horos11 wrote:

 Saying that 'whoa, this coding error should be handled by naming
 convention' may be the only practical way of getting around this
 limitation, but it is a limitation nonetheless, and a pretty big one.

You misunderstand the dynamic nature of python - YOU rebound the name to 
something else - how on earth can the interpreter know that this is not what 
you meant?

Could you formulate a rule that the interpreter should follow to be able to 
flag what you have done as an error?

- Hendrik

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread Carl Banks
On Oct 3, 11:45 pm, horos11 horo...@gmail.com wrote:
  It's not a bug.  In Python classes and global variables share the same
  namespace.

  Don't you think you should learn a bit more about how Python manages
  objects and namespaces before going around calling things bugs?

  Carl Banks

 No, I don't think so..

 Say you went to another country, where the people wore lead shoes,
 hence not only going slower, but getting lead poisoning from time to
 time.

 Pointing out that shoes made of fabric might just be better should not
 be heresy.

This analogy is wrong on two counts:

1. Pointing out that the fabric might be better is not analogous to
what you did.  You claimed that Python's behavior was a bug, which
would be analogous to me saying, lead shoes should be illegal.

2. I know enough about the properties of fabric and lead to make an
informed complaint over the use of lead for shoes, even if I am new to
the country.   However you very clearly have a poor understanding of
Python's namespace and object models, and so you have little standing
to claim that Python is buggy in how it treats its namespaces.

I'd say the strongest claim you have grounds to make, given the level
of understanding you've shown, is this is very confusing to noobs.

BTW, the Python maintainers are very particular to define bug as
Python behaves differently than it is documentated to, and Python is
most definitely documented as acting the way it does.


 In this case, I think the overall goal was syntax simplicity, but it
 sure as hell makes things confusing. No warning, or anything. The sane
 behavior IMO would be to disallow the assignment unless put through a
 special function, something like:

 class(state) = ...
 After all, python does have a precedent when you try to join, when:

 :.join([1,2])

 does not work because [1,2] is an array of ints, whereas

 : . join( str(x) for x in [1,2])

 does.

No, it really isn't a precedent.  Yes, Python does type-checking quite
a bit, however there is no precedent at all for customizing assignment
to a regular variable.  When you write a = b, a gets bound to the
same object as b is bound to, end of story.  You can't customize it,
you can't prevent it, you can hook into it, and neither object is
notified that an assignment is happening.  This is true even if a or b
happen to be a class.

And if you say, Well you should be able to customize assigment, my
answer is, You were saying there was a precedent, I said there was
not.  If you want to argue that it should be possible to customize
assignment, be my guest, but you'll have to do it without the benefit
of a precedent.

(You can customize assignment to an attribute or item, but that is not
what we're talking about, especially since classes are hardly ever
attributes or items.)


Carl Banks
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread Albert Hopkins
Just by a brief look at your code snippet there are a few things that I
would point out, stylistically, that you may consider changing in your
code as they are generally not considered pythonic:

  * As already mentioned the state class is best if given a name
that is capitalized.
  * As already mentioned the name state is (unintentionally)
re-used within the same scope.  This could have been avoided
with the above naming convention change and also if the main
body of the code were in a function, say main()
  * The methods default_board, default_types, and default_moves
appear to be static methods but are not defined as such.
  * Also, since the above methods have no logic and simply return
a value they are probably best defined as static attributes
rather than methods. But if doing so you would need to alter
your constructor.
  * You used a number of built-in names as attribute names (dir,
type). While this is legal Python it is generally not
recommended.
  * You use range(0, n).  0 is the default start value for range()
so it is generally left out.
  * You define a to_string() method. To have a string representation
of a class, one usually defines a __str__ method.  This gives
the advantage whereby print myobject or '%s' % myjobject just
work.

Probably others can make more suggestions. You will find a lot of these
suggestions are borrowed from PEP8 [1] but you can peruse other people's
Python code to learn from the masters.

Hope this helps,
-a


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread Rhodri James

On Sun, 04 Oct 2009 07:14:08 +0100, horos11 horo...@gmail.com wrote:


Carl,

Thanks for the info, but a couple of points:

1. it wasn't meant to be production code, simply a way to teach
python.


Speaking as someone who does teach Python, Ew, no!  If you start by
teaching people bad habits, every educator who comes along afterwards
will curse your name.  That includes teaching yourself.

--
Rhodri James *-* Wildebeest Herder to the Masses
--
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread Simon Forman
On Sun, Oct 4, 2009 at 1:12 AM, horos11 horo...@gmail.com wrote:

  a

 __main__.Myclass instance at 0x95cd3ec b

 __main__.Myclass instance at 0x95cd5ac

 What's the problem?

 Like I said, the code was a sample of what I was trying to do, not the
 entire thing.. I just wanted to see if the metaphor was kosher.

Right, but it doesn't help if you post code that doesn't actually
display the unexpected behaviour you're asking about.

 It sounds to me from your answer that this is unexpected behavior, so
 I'll go ahead and post the whole thing. My guess is that it is a
 python bug..

/What/ is unexpected behaviour?  I ran the code you posted and worked
exactly like I expected.

Posting the whole thing is better than posting code that doesn't
display the issue, but this is too long.  I'd ask you to repost a
minimal version that actually displays the problem you're asking about
but I see from the rest of this thread that you've already figured it
out.

Related to that, two points.

Learn python AS python, don't get caught up in what it does
differently than other languages.  IMHO it's hands-down the most
useful. productive language out there for a tremendous number of
problem domains.  Treat yourself to it. ;]

And second, please don't /teach/ python until you've learned it...

Regards,
~simon

 Run it (a simple puzzle game solved by breadth first search), and the
 first time state() is called inside the method, it calls __init__.
 Second time, and therafter, it calls __call__. I've highlighted where
 the code fails by putting a pdb.set_trace().

 Anyways, I've got a workaround (simply pass in any new objects needed
 from the caller), but it is truly annoying that python is either
 misleading or broken in this way.

 Attached find code, does not work vs. 2.6..


 Ed

 

 from collections import deque
 import copy
 import pdb

 class state:

    def default_board():

        return [
              [ 1, 'x', 'x', 0 ],
              [ 2, 2,  3,  4 ],
              [ 5, 6,  6,  7 ],
              [ 5, 6,  6,  7 ],
              [ 8, 9, 10, 10 ],
              [ 0, 'x', 'x', 0 ]
            ]

    def default_types():

        return {
                1  : [ 0, 0 ],
                2  : [ 0, 0, 0, 1 ],
                3  : [ 0, 0 ],
                4  : [ 0, 0 ],
                5  : [ 0, 0, 1, 0 ],
                6  : [ 0, 0, 1, 0, 0, 1, 1, 1 ],
                7  : [ 0, 0, 1, 0 ],
                8  : [ 0, 0 ],
                9  : [ 0, 0 ],
                10 : [ 0, 0, 0, 1 ]
            }

    def default_moves():

        return []

    def print_move(self, moveno, move):
        print str(moveno) + :  + str(move) + \n


    def __init__(self, _board=default_board(), _moves=default_moves(),
 _types=default_types()):

        self.board = _board
        self.moves = _moves
        self.types = _types

    def possible_moves(self):

        moves_so_far = set()
        moves_so_far.add('x')
        moves_so_far.add(0)
        ret = []
        for y_idx in range(0, len(self.board)):
            for x_idx in range(0, len(self.board[y_idx])):

                piece = self.board[y_idx][x_idx]

                if not piece in moves_so_far:

                    moves = self.legal_moves(y_idx, x_idx)
                    moves_so_far.add(piece)

                    if moves:
                        ret.extend(moves)

        return ret

    def is_answer(self):

        if self.board[5][3] == 1:
            return True
        else:
            return False

    def legal_moves(self, ycoord, xcoord):

        ret = []
        for dir in [ [ 0, 1 ], [ 0, -1 ], [ 1, 0 ], [ -1, 0 ] ]:
            ret.extend(self.addmove(dir[0], dir[1], ycoord, xcoord))

        return ret

    def empty(self, type, ycoord, xcoord, pieceno):

        for itr in range(0, len(type), 2):

            yy = type[itr]
            xx = type[itr+1]

            if not (len(self.board)  (yy+ycoord) = 0)  or not (len
 (self.board[yy+ycoord])  xx+xcoord = 0):
                return False

            if not self.board[yy+ycoord][xx+xcoord] in [ 0, pieceno ]:
                return False

        return True

    def addmove(self, ymult, xmult, ycoord, xcoord):

        ret = []
        pieceno = self.board[ycoord][xcoord]
        type    = self.types[pieceno]

        if xmult != 0:
            for xx in range(xcoord + xmult, -1 if xmult  0 else 4, -1
 if xmult  0 else 1):
 #               if xx == 0:
 #                   continue
                if self.empty(type, ycoord, xx, pieceno):
                    ret.append(self.newmove(ycoord, xcoord, ycoord,
 xx ))
                else:
                    break

        if ymult != 0:
            for yy in range(ycoord + ymult, -1 if ymult  0 else 6, -1
 if ymult  0 else 1):
 #               if yy == 0:
 #                   continue
                if self.empty(type, yy, xcoord, pieceno):
                    ret.append(self.newmove(ycoord, xcoord, yy,
 xcoord))
                else:
                

Re: creating class objects inside methods

2009-10-04 Thread horos11


  Thanks for the info, but a couple of points:

      1. it wasn't meant to be production code, simply a way to teach
  python.

 Speaking as someone who does teach Python, Ew, no!  If you start by
 teaching people bad habits, every educator who comes along afterwards
 will curse your name.  That includes teaching yourself.

 --
 Rhodri James *-* Wildebeest Herder to the Masses

No offense, but I disagree. By programming without regards to pre-
existing style or convention I learned far more than I otherwise would
have if I had simply mimicked someone else.

And I still think that unbridled assignment - especially assignment
that can change the operational semantics of surrounding terms, at a
distance no less - is a horrid thing.

It gets even worse because the way python handles assignment. To go
back to my original program: why isn't the state variable that I
defined local to that 'if' loop?

while len(dq):

...
if curstate.is_answer():
...
else:
for state in ...


The answer? Because you can't explicitly declare it. It therefore
looks globally, finds the 'class state:' statement, and runs with it.
I should be able to say:

for my state in curstate.next_states():

to show explicitly what I'm doing.


Anyways, maybe I got off to a bad start, but I'm a bit leery of the
language. In my estimation it's trying to be 'too clever by half', and
this coming from a veteran bash/perl programmer. I mean, free form is
one thing, but too much of a good thing can be harmful to your
programming health. Maybe PyChecker or PyLint will help, I don't know.

Ed

(
ps - an aside, but what was the rationale behind only displaying one
error at a time on trying to run a script? I typically like to run a
compilation phase inside my editor (vim), get a list of errors, and
then go to each one and fix them.

And how do you just check a script's syntax without running it
anyways?
)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread Benjamin Kaplan
On Sun, Oct 4, 2009 at 2:44 PM, horos11 horo...@gmail.com wrote:


  Thanks for the info, but a couple of points:

      1. it wasn't meant to be production code, simply a way to teach
  python.

 Speaking as someone who does teach Python, Ew, no!  If you start by
 teaching people bad habits, every educator who comes along afterwards
 will curse your name.  That includes teaching yourself.

 --
 Rhodri James *-* Wildebeest Herder to the Masses

 No offense, but I disagree. By programming without regards to pre-
 existing style or convention I learned far more than I otherwise would
 have if I had simply mimicked someone else.

 And I still think that unbridled assignment - especially assignment
 that can change the operational semantics of surrounding terms, at a
 distance no less - is a horrid thing.

 It gets even worse because the way python handles assignment. To go
 back to my original program: why isn't the state variable that I
 defined local to that 'if' loop?

 while len(dq):

    ...
    if curstate.is_answer():
        ...
    else:
        for state in ...


 The answer? Because you can't explicitly declare it. It therefore
 looks globally, finds the 'class state:' statement, and runs with it.
 I should be able to say:

    for my state in curstate.next_states():

 to show explicitly what I'm doing.


 Anyways, maybe I got off to a bad start, but I'm a bit leery of the
 language. In my estimation it's trying to be 'too clever by half', and
 this coming from a veteran bash/perl programmer. I mean, free form is
 one thing, but too much of a good thing can be harmful to your
 programming health. Maybe PyChecker or PyLint will help, I don't know.

 Ed

 (
 ps - an aside, but what was the rationale behind only displaying one
 error at a time on trying to run a script? I typically like to run a
 compilation phase inside my editor (vim), get a list of errors, and
 then go to each one and fix them.

 And how do you just check a script's syntax without running it
 anyways?
 )

Because these aren't compile-time errors. Python has no compilation
phase- every statement (including def and class) is an executable
statement and it gets turned into byte code at execution time. Just
like any other language, when Python hits a runtime error, it stops.
 --
 http://mail.python.org/mailman/listinfo/python-list

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread Carl Banks
On Oct 4, 11:56 am, Benjamin Kaplan benjamin.kap...@case.edu wrote:
 On Sun, Oct 4, 2009 at 2:44 PM, horos11 horo...@gmail.com wrote:

  (
  ps - an aside, but what was the rationale behind only displaying one
  error at a time on trying to run a script? I typically like to run a
  compilation phase inside my editor (vim), get a list of errors, and
  then go to each one and fix them.

  And how do you just check a script's syntax without running it
  anyways?
  )

 Because these aren't compile-time errors. Python has no compilation
 phase- every statement (including def and class) is an executable
 statement and it gets turned into byte code at execution time. Just
 like any other language, when Python hits a runtime error, it stops.

No, there is a compile phase, but the only error that is raised at
compile-time is SyntaxError.  Because of Python's dynamicism the
compiler knows hardly anything about the objects at compile-time
(except in a few cases involving constants, which Python takes
advantage of to do some compile-time constant folding).


Carl Banks
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread Carl Banks
On Oct 4, 3:12 am, Albert Hopkins mar...@letterboxes.org wrote:
       * You define a to_string() method. To have a string representation
         of a class, one usually defines a __str__ method.  This gives
         the advantage whereby print myobject or '%s' % myjobject just
         work.


In fairness, a lot of types define a to_string() method (especially
third-party types like numpy), but it's usually to produce a raw
binary output.

Presumably in Python 3 these methods will be renamed to_bytes.


Carl Banks
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread Simon Forman
On Sun, Oct 4, 2009 at 2:44 PM, horos11 horo...@gmail.com wrote:


  Thanks for the info, but a couple of points:

      1. it wasn't meant to be production code, simply a way to teach
  python.

 Speaking as someone who does teach Python, Ew, no!  If you start by
 teaching people bad habits, every educator who comes along afterwards
 will curse your name.  That includes teaching yourself.

 --
 Rhodri James *-* Wildebeest Herder to the Masses

 No offense, but I disagree. By programming without regards to pre-
 existing style or convention I learned far more than I otherwise would
 have if I had simply mimicked someone else.

Don't teach newbies bad idiom.

 And I still think that unbridled assignment - especially assignment
 that can change the operational semantics of surrounding terms, at a
 distance no less - is a horrid thing.

That's opinion.

Python allows you to shoot yourself in the foot.  It's on us as
programmers to be able to grok our code well enough to prevent nasty
errors.  With great power comes great responsibility. and all that.

 It gets even worse because the way python handles assignment. To go
 back to my original program: why isn't the state variable that I
 defined local to that 'if' loop?

There's no such thing as an if loop.

The only answer to your question is that's the way it is...  or,
equivalently, that's the way Guido made it.

Check out Python Scopes and Name Spaces
http://www.python.org/doc/2.2/tut/node11.html#SECTION001120

 while len(dq):

    ...
    if curstate.is_answer():
        ...
    else:
        for state in ...


 The answer? Because you can't explicitly declare it. It therefore
 looks globally, finds the 'class state:' statement, and runs with it.
 I should be able to say:

    for my state in curstate.next_states():

 to show explicitly what I'm doing.

You can, you just have to be careful not to shadow some other name
in your namespace(s).  Again, python makes a trade off between
babysitting the programmer on the one hand vs. raw flexibility on
the other.

 Anyways, maybe I got off to a bad start, but I'm a bit leery of the
 language. In my estimation it's trying to be 'too clever by half', and
 this coming from a veteran bash/perl programmer. I mean, free form is
 one thing, but too much of a good thing can be harmful to your
 programming health. Maybe PyChecker or PyLint will help, I don't know.

I think if you let python seep into your thinking you'll eventually
come to love it.

It /IS/ very (too) clever, but the cleverness is (IMHO) spent on
getting out of your way, rather than trying to insure you're doing
things right.

Eric Raymond has a great article where he talks about learning python:
http://www.linuxjournal.com/article/3882

My second [surprise] came a couple of hours into the project, when I
noticed (allowing for pauses needed to look up new features in
Programming Python) I was generating working code nearly as fast as I
could type. When I realized this, I was quite startled. An important
measure of effort in coding is the frequency with which you write
something that doesn't actually match your mental representation of
the problem, and have to backtrack on realizing that what you just
typed won't actually tell the language to do what you're thinking. An
important measure of good language design is how rapidly the
percentage of missteps of this kind falls as you gain experience with
the language.

I can vouch for this: I can routinely write 200~300 lines of python
code and have it run flawlessly the first time.  This doesn't happen
every time, but it's the norm rather than the exception.


Give it a chance.  It's (IMHO) /beautiful/.


Happy hacking,
~Simon


 Ed

 (
 ps - an aside, but what was the rationale behind only displaying one
 error at a time on trying to run a script? I typically like to run a
 compilation phase inside my editor (vim), get a list of errors, and
 then go to each one and fix them.

I dunno the rationale, but the mechanism is uncaught exceptions
propagate up and halt the interpreter.  Since nothing keeps going
after an uncaught exception, there's nothing there to report the next
error.

 And how do you just check a script's syntax without running it
 anyways?

Just run it. ;]

FWIW, use the interactive interpreter (or IPython variant) to play
with the language until you learn the syntax well enough not to write
bad syntax.  For me anyway, that was the best/fastest way to learn it.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread Rob Williscroft
Benjamin Kaplan wrote in news:mailman.838.1254682604.2807.python-
l...@python.org in comp.lang.python:

 And how do you just check a script's syntax without running it
 anyways?
 )
 
 Because these aren't compile-time errors. Python has no compilation
 phase- 

Sure it does, compilation happens for every script that is executed.

And for every import, if the pre-compiled byte code can't be found it 
is compiled (and the byte code saved as a .pyc or .pyo file).

Its only when a the interpreter has the complete compiled byte code
for a script or imported module that it executes anything.

Python could, if it was wanted, detect multiple syntax and other 
compilation errors, but AIUI the (CPython) developers choose not 
to, as it significantly simplifies (and thus speeds up) the 
compilation process, which can be significant for an interpreted
language.

For example I just ran a script with the one line:

print hello world

through IronPython (2.0 (2.0.0.0) on .NET 2.0.50727.3082)

I counted 1 and 2 and ... 12 before I seeing hello world

(Aside I think this is something that the current IronPython beta 
(2.6) fixes, but I havent tried it myself yet.)

 every statement (including def and class) is an executable

Yes but for example the execution of the statement:

def example() : pass

just assignes (binds) the compiled function to the name example.

 statement and it gets turned into byte code at execution time. Just
 like any other language, when Python hits a runtime error, it stops.
 

Rob.
-- 
http://www.victim-prime.dsl.pipex.com/
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread Stephen Hansen

 Anyways, maybe I got off to a bad start, but I'm a bit leery of the
 language. In my estimation it's trying to be 'too clever by half', and
 this coming from a veteran bash/perl programmer. I mean, free form is
 one thing, but too much of a good thing can be harmful to your
 programming health. Maybe PyChecker or PyLint will help, I don't know.


There's nothing at all clever going on here, though. There just seems to be
a lack of understanding of how assignment and variables operate in Python.
Nothing is being changed at a distance; the lookup and binding semantics
of Python are actually really, really simple.

Everytime you reference a name, it is first looked up in the local scope: if
it's not found there, it's looked up in the global scope. That's it.

Everytime you assign a name, it is always assigned to the local scope.

Those are the basic rules, and that's really all you need to know for all
the basic doings. Anytime you try to get the value of state, it looks in
two places -- local, then global. Anytime you try to assign the value of
state, it assigns it to the local scope.

The global scope remains unchanged in the assignment; you're not altering
anything at a distance or going and messing with the class definition that
lives in the global scope of the module. You've just made a local variable
that shadows it.

Okay, things get slightly more complicated in two places-- if you use the
'global name' statement within a function, subsequent assignments to name
will assign to the global namespace instead of the local namespace. Also, if
you nest functions within each-other, there is a limited searching up that
nesting of local scopes to find names. There's no other nested / lexical
scoping in any other context in Python.

But, overall, things are simple. Just different. There's only two scopes or
namespaces: the current function body, and the global scope. Nothing's
clever going on. All assignment is local, lookups search first the local and
then the global namespace. In my experience, once you grasp that it's
trivial to never run into this sort of error ever again. I don't just mean
finding it when you do it-- but never even writing it anymore.

Just don't shadow global names in the local namespace. It's really not a big
deal.

--S
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-04 Thread Terry Reedy

horos11 wrote:


Anyways, maybe I got off to a bad start,


Blaming programming errors on non-existent bugs in the interpreter is 
not a way to endear yourself.


And perhaps Python truly is not your style.


Maybe PyChecker or PyLint will help, I don't know.


I do not use them, but others swear by them.


ps - an aside, but what was the rationale behind only displaying one
error at a time on trying to run a script? I typically like to run a
compilation phase inside my editor (vim), get a list of errors, and
then go to each one and fix them.


It would complicate the compiler. It is consistent with the rest of 
Python's error reporting system (one runtime error only also). Error 
reports after the first may be bogus. Python aware editors, like the one 
with IDLE, put the cursor at the reported location of a syntax error. 
And they only have one cursor ;-).



And how do you just check a script's syntax without running it
anyways?


The checker programs parse the code, so I would expect they report 
syntex errors.


Or: put $, a syntax error, on a line at the bottom of your script to 
abort execution. If the interpreter stops there, everything before is 
syntacally OK. If using a Python-aware editor, you will pop back into 
the edit window at the bottom of the file.


But of course, not running means not running the test code, so the 
program is not necessarily OK at all.


Terry Jan Reedy


--
http://mail.python.org/mailman/listinfo/python-list


creating class objects inside methods

2009-10-03 Thread horos11
All,

I've got a strange one..

I'm trying to create a class object inside another class object by
using the code template below (note.. this isn't the exact code.. I'm
having difficulty reproducing it without posting the whole thing)

Anyways, the upshot is that the first time the Myclass() constructor
is called, the __init__ function gets executed.. The second time, it
calls the '__call__' method (and dies, because I don't have a call
method defined).

To get around this, I've made __call__ a synonym of __init__, which is
a horrid hack, and doesn't help me much (since I don't have a good
idea what's going on).

So - anyone have an idea of what's going on here? It looks like the
second time, the Myclass() call is interpreted as a class instance,
not a  class object, but that seems odd to me.. Is this a python bug?
I'm seeing it in 2.6..If necessary, I can post the whole piece of
code..

Ed

class Myclass:

def __init__(self, b='default1', c='default2'):

self.b = b;
self.c = c;

def function(self):

 other = Myclass();
 return(other)

a = Myclass();

b = a.function()
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-03 Thread Simon Forman
On Sat, Oct 3, 2009 at 11:32 PM, horos11 horo...@gmail.com wrote:
 All,

 I've got a strange one..

 I'm trying to create a class object inside another class object by
 using the code template below (note.. this isn't the exact code.. I'm
 having difficulty reproducing it without posting the whole thing)

 Anyways, the upshot is that the first time the Myclass() constructor
 is called, the __init__ function gets executed.. The second time, it
 calls the '__call__' method (and dies, because I don't have a call
 method defined).

 To get around this, I've made __call__ a synonym of __init__, which is
 a horrid hack, and doesn't help me much (since I don't have a good
 idea what's going on).

 So - anyone have an idea of what's going on here? It looks like the
 second time, the Myclass() call is interpreted as a class instance,
 not a  class object, but that seems odd to me.. Is this a python bug?
 I'm seeing it in 2.6..If necessary, I can post the whole piece of
 code..

 Ed

 class Myclass:

    def __init__(self, b='default1', c='default2'):

        self.b = b;
        self.c = c;

    def function(self):

         other = Myclass();
         return(other)

 a = Myclass();

 b = a.function()
 --
 http://mail.python.org/mailman/listinfo/python-list



class Myclass:
def __init__(self, b='default1', c='default2'):
self.b = b
self.c = c

def function(self):
other = Myclass()
return other

a = Myclass()
b = a.function()


 a
__main__.Myclass instance at 0x95cd3ec
 b
__main__.Myclass instance at 0x95cd5ac


What's the problem?


(Also, you can leave out the ';' at the end of statements. And
'return' isn't a function, you can leave out the ()'s.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: creating class objects inside methods

2009-10-03 Thread horos11

  a

 __main__.Myclass instance at 0x95cd3ec b

 __main__.Myclass instance at 0x95cd5ac

 What's the problem?

Like I said, the code was a sample of what I was trying to do, not the
entire thing.. I just wanted to see if the metaphor was kosher.

It sounds to me from your answer that this is unexpected behavior, so
I'll go ahead and post the whole thing. My guess is that it is a
python bug..

Run it (a simple puzzle game solved by breadth first search), and the
first time state() is called inside the method, it calls __init__.
Second time, and therafter, it calls __call__. I've highlighted where
the code fails by putting a pdb.set_trace().

Anyways, I've got a workaround (simply pass in any new objects needed
from the caller), but it is truly annoying that python is either
misleading or broken in this way.

Attached find code, does not work vs. 2.6..


Ed



from collections import deque
import copy
import pdb

class state:

def default_board():

return [
  [ 1, 'x', 'x', 0 ],
  [ 2, 2,  3,  4 ],
  [ 5, 6,  6,  7 ],
  [ 5, 6,  6,  7 ],
  [ 8, 9, 10, 10 ],
  [ 0, 'x', 'x', 0 ]
]

def default_types():

return {
1  : [ 0, 0 ],
2  : [ 0, 0, 0, 1 ],
3  : [ 0, 0 ],
4  : [ 0, 0 ],
5  : [ 0, 0, 1, 0 ],
6  : [ 0, 0, 1, 0, 0, 1, 1, 1 ],
7  : [ 0, 0, 1, 0 ],
8  : [ 0, 0 ],
9  : [ 0, 0 ],
10 : [ 0, 0, 0, 1 ]
}

def default_moves():

return []

def print_move(self, moveno, move):
print str(moveno) + :  + str(move) + \n


def __init__(self, _board=default_board(), _moves=default_moves(),
_types=default_types()):

self.board = _board
self.moves = _moves
self.types = _types

def possible_moves(self):

moves_so_far = set()
moves_so_far.add('x')
moves_so_far.add(0)
ret = []
for y_idx in range(0, len(self.board)):
for x_idx in range(0, len(self.board[y_idx])):

piece = self.board[y_idx][x_idx]

if not piece in moves_so_far:

moves = self.legal_moves(y_idx, x_idx)
moves_so_far.add(piece)

if moves:
ret.extend(moves)

return ret

def is_answer(self):

if self.board[5][3] == 1:
return True
else:
return False

def legal_moves(self, ycoord, xcoord):

ret = []
for dir in [ [ 0, 1 ], [ 0, -1 ], [ 1, 0 ], [ -1, 0 ] ]:
ret.extend(self.addmove(dir[0], dir[1], ycoord, xcoord))

return ret

def empty(self, type, ycoord, xcoord, pieceno):

for itr in range(0, len(type), 2):

yy = type[itr]
xx = type[itr+1]

if not (len(self.board)  (yy+ycoord) = 0)  or not (len
(self.board[yy+ycoord])  xx+xcoord = 0):
return False

if not self.board[yy+ycoord][xx+xcoord] in [ 0, pieceno ]:
return False

return True

def addmove(self, ymult, xmult, ycoord, xcoord):

ret = []
pieceno = self.board[ycoord][xcoord]
type= self.types[pieceno]

if xmult != 0:
for xx in range(xcoord + xmult, -1 if xmult  0 else 4, -1
if xmult  0 else 1):
#   if xx == 0:
#   continue
if self.empty(type, ycoord, xx, pieceno):
ret.append(self.newmove(ycoord, xcoord, ycoord,
xx ))
else:
break

if ymult != 0:
for yy in range(ycoord + ymult, -1 if ymult  0 else 6, -1
if ymult  0 else 1):
#   if yy == 0:
#   continue
if self.empty(type, yy, xcoord, pieceno):
ret.append(self.newmove(ycoord, xcoord, yy,
xcoord))
else:
break

return ret

def newmove(self, fromy, fromx, toy, tox):

move = {
'fromx' : fromx,
'fromy' : fromy,
'toy'   : toy,
'tox'   : tox,
'piece' : self.board[fromy][fromx]
}

return move

def printout_path(self):

#   print self
pdb.set_trace()
answer = state()

moveno = 0
print \n==\n

for moveno in range(0, len(self.moves)):
move = self.moves[moveno]
self.print_move(moveno, move)
answer.apply_move(move)
answer.print_board()
print \n==\n

def print_board(self):

for xx in self.board:

print : .join([ %2s % str(ii) for ii in xx ])

def to_string(self):

return str(self.board)

def apply_move(self, move):

  

Re: creating class objects inside methods

2009-10-03 Thread horos11
Anyways, I see what's going on here:

With the line,

for state in curstate.next_states():
if not state.to_string() in seen_states:
dq.append(state)

Inadvertently using the name of a module as a variable seems to be
causing this.

In any case, this shouldn't cause issues with constructors, so I'd
call this a bug..

Ed
-- 
http://mail.python.org/mailman/listinfo/python-list