Re: creating class objects inside methods
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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