My first Python program

S

Seebs

Not really. Files will be closed when the garbage collector collects the
file object, but you can't be sure the GC will run within the next N
seconds/instructions or something like that. So you should *always* make
sure to close files after using them. That's what context managers were
introduced for.
with open('foobar') as fileobject:
do_something_with(fileobject)

That makes sense. I don't think it'd quite work in this case, because I
want to open several files all at once, do a ton of work that populates
them with files, and then close them all.

This is a nice idiom, though. In C, I've been sort of missing that idiom,
which I first encountered in Ruby. (I mean, spelled differently, but the
same basic thing.)

-s
 
S

Seebs

Unfortunately "with" is newish and this code currently has to
support python 2.3 (if not even older versions).

I think it might be 2.4 and later. I'm not sure. Of course, this being
the real world, the chances that I'll be able to stick with "Python 2" and
not have to simultaneously also support Python 1 and Python 3 are probably
about 20%.

-s
 
M

MRAB

Yes. I'm getting used to that -- it's a bit of a shift, because I'm
used to exceptions being *exceptional* -- as in, not a failure mode
you would expect to see happening. So for instance, I wouldn't expect
to get an exception for EOF, because that's not exceptional, that's
virtually guaranteed to happen whenever you interact with files. I am
gonna have to retrain a bit.


Interesting! That may take me some getting used to.
Basically, Python tries to avoid returning 'magic' values which you
need to check, but could equally just ignore.

If it can't open a file, it doesn't return None, it complains.

If it can't parse an int from a string, it doesn't return 0 (which it
could return if it's successful) or None or whatever, it complains.

There are times when, say, C# complains but Python doesn't, like trying
to get a substring starting at a position which is off the end of the
source string.

In practice I find that the Python way just works better.
 
E

Emmanuel Surleau

Seebs said:
From that expectation, it's an even more fundamental shift. Python
encourages (and tends toward) raising exceptions in any exceptional
circumstance — that is, in any circumstance that isn't the usual
behaviour for the function.

So, for example, an exception (StopIteration) is how iterables signal
that they've finished iterating; but that's not an error, only an
exception. Likewise for the ‘str.index’ example given earlier.

I'd say more succintly that Python uses (at times) exception for flow control.
Whether that's elegant or not is debatable.

Cheers,

Emm
 
S

Seebs

Python borrows from C in that consecutive literal strings are
concatenated in the bytecode::

stderr.write(
"WARNING:"
" Pants on fire\n")

Hmm. So I just indent stuff inside the ()s or whatever? I can work with
that.

-s
 
H

Hallvard B Furuseth

Ethan said:
Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.

--> a = 2
--> b = 7
--> c = 13
--> a = b = c = 'right to left'
--> a, b, c
('right to left', 'right to left', 'right to left')

Eek. I just meant to remark it's quite different from C where it means
a=(b=(c='...')), the assignments even happen in left-to-right _order_.
In this Python version anyway. Not that you'd be setting a string to a
variable:)
... def __setattr__(*args): print "%s.%s = %s" % args
... f.x = 3
g.y = 3
match = re.match('(.*)\(\*([a-zA-Z0-9_]*)\)\((.*)\)', text)
Make a habit of using r'' for strings with lots of backslashes,
like regexps.

Hmm. There's an interesting question -- does this work as-is? I'm
assuming it must or it would have blown up on me pretty badly, so
presumably those backslashes are getting passed through untouched
already. But if that's just coincidence (they happen not to be valid
\-sequences), I should definitely fix that.

Unknown backslash sequences are passed through as-is.

Personally I don't want to need to remember, I'm already confusing the
backslash rules of different languges. Often you can just ask Python
what it thinks of such things, as I did with open("nonesuch"), and
then either imitate the answer or use it to help you zoom in on it in
the doc now that you know the rough answer to look for. So,

$ python
>>> '(.*)\(\*([a-zA-Z0-9_]*)\)\((.*)\)'
'(.*)\\(\\*([a-zA-Z0-9_]*)\\)\\((.*)\\)'

Thus I'd personally spell it that way or with r'':

r'(.*)\(\*([a-zA-Z0-9_]*)\)\((.*)\)'

Note that [a-zA-Z0-9_] is equivalent to \w or [\w] in Python 2 unless
you give a LOCALE or UNICODE flag, and in Python 3 if you give the
ASCII flag.
 
E

Ethan Furman

Ian said:
here is an example
where the order of assignment actually matters:
Traceback (most recent call last):
File said:
{'a': {...}}

As you can see, they're assigned left-to-right.

<Flash of inspiration>

Ah! I was thinking the assignments went in a filter fashion, but now
what I think is happening is that the first item is bound to the last,
then the next item is bound to the last, etc, etc.

Is this correct?

~Ethan~
 
J

Jonas H.

Hmm. So I just indent stuff inside the ()s or whatever? I can work with
that.

I think common is

stderr.write("WARNING: ",
"Pants on fire")

or

stderr.write(
"WARNING: "
"Pants on fire"
)

If you haven't got braces around an expression and you want it to be
multi-line, you need a '\' at the end of each line, just like C macros:

msg = "WARNING: " \
"Pants on fire"

Though that is not commonly used afaik.
 
H

Hallvard B Furuseth

Seebs said:
Interesting. Do I just rely on files getting closed?

Sometimes, but that's not it. Think Lisp, not C++. __del__ is not that
useful. Python is garbage-collected and variables have dynamic lifetime,
so the class cannot expect __del__ to be called in a timely manner.
Destructors have several issues, see __del__ in the Python reference.

A class which holds an OS resource like a file, should provide a context
manager and/or a release function, the latter usually called in a
'finally:' block. When the caller doesn't bother with either, the class
often might as well depend on the destructor in 'file'.

Still, open().read() is common. open().write() is not. The C
implementation of Python is reference-counted on top of GC, so the file
is closed immediately. But this way, exceptions from close() are lost.
Python cannot propagate them up the possibly-unrelated call chain.


Some other points:

For long strings, another option is triple-quoting as you've seen in doc
strings: print """foo
bar""".


class SourceFile(object):
def emit(self, template, func = None):
# hey, at least it's not a global variable, amirite?
self.file.write(SourceFile.copyright)
def main():
SourceFile.copyright = copyright_file.read()

emit() can use self.copyright instead of SourceFile.copyright.

I've written such code, but I suppose the proper way is to use a
classmethod to set it, so you can see in the class how the copyright
gets there. SourceFile.<classmethod>() and self.<classmethod>() both
get called with the class as 1st argument.

class SourceFile(object):
def setup_copyright(cls, fname):
cls.copyright = open(fname).read()
setup_copyright = classmethod(setup_copyright)
# In python >= 2.4 you can instead say @classmethod above the def.
def main():
SourceFile.setup_copyright('guts/COPYRIGHT')


SourceFile.__repr__() looks like it should be a __str__(). I haven't
looked at how you use it though. But __repr__ is supposed to
look like a Python expression to create the instance: repr([2]) = '[2]',
or a generic '<foo instance>': repr(id) = '<built-in function id>'.


"How new are list comprehensions?"

Python 2.0, found as follows:
- Google python list comprehensions.
- Check the PEP (Python Enhancement Proposal) which shows up. PEPs
are the formal documents for info to the community, for the Python
development process, etc. <http://www.python.org/dev/peps/pep-0202/>:
Title: List Comprehensions
Status: Final
Type: Standards Track
Python-Version: 2.0
 
S

Seebs

A class which holds an OS resource like a file, should provide a context
manager and/or a release function, the latter usually called in a
'finally:' block. When the caller doesn't bother with either, the class
often might as well depend on the destructor in 'file'.

That makes sense.

In this case, I'm pretty sure context managers aren't the right tool (even
apart from version questions), because they appear to be syntax-level
tools -- but it's a runtime decision how many files I have to open and
close.
For long strings, another option is triple-quoting as you've seen in doc
strings: print """foo
bar""".

I assume that this inserts a newline, though, and in this case I don't
want that.
I've written such code, but I suppose the proper way is to use a
classmethod to set it, so you can see in the class how the copyright
gets there. SourceFile.<classmethod>() and self.<classmethod>() both
get called with the class as 1st argument.

Oh, that makes more sense.
def setup_copyright(cls, fname):
cls.copyright = open(fname).read()
setup_copyright = classmethod(setup_copyright)
# In python >= 2.4 you can instead say @classmethod above the def.

I *think* I get to assume 2.4.
SourceFile.__repr__() looks like it should be a __str__(). I haven't
looked at how you use it though. But __repr__ is supposed to
look like a Python expression to create the instance: repr([2]) = '[2]',
or a generic '<foo instance>': repr(id) = '<built-in function id>'.

Ahh! I didn't realize that. I was using repr as the "expand on it enough
that you can see what it is" form -- more for debugging than for
something parsable.
Python 2.0, found as follows:
- Google python list comprehensions.
- Check the PEP (Python Enhancement Proposal) which shows up. PEPs
are the formal documents for info to the community, for the Python
development process, etc. <http://www.python.org/dev/peps/pep-0202/>:
Title: List Comprehensions
Status: Final
Type: Standards Track
Python-Version: 2.0

Ah-hah! That's helpful. Thanks -- now I know how to find out next time
I'm curious.

-s
 
H

Hallvard B Furuseth

Seebs said:
I assume that this inserts a newline, though, and in this case I don't
want that.

True.
$ python ... bar"""
'foo\nbar' ... bar"""
'foobar' ... bar"
'foobar' 'foobar'
SourceFile.__repr__() looks like it should be a __str__(). I haven't
looked at how you use it though. But __repr__ is supposed to
look like a Python expression to create the instance: repr([2]) = '[2]',
or a generic '<foo instance>': repr(id) = '<built-in function id>'.

Ahh! I didn't realize that. I was using repr as the "expand on it enough
that you can see what it is" form -- more for debugging than for
something parsable.

No big deal, then, except in the "idiomatic Python" sense.
__str__ for the informal(?) string representation of the object,
def __repr__(self):
return "<%s object with %s>" % (self.__class__.__name__, <foo>)
and you have a generic 2nd case, but looks like it'll be unusually long
in this case, or just define some ordinary member name like info() or
debug().
 
D

Dennis Lee Bieber

True.
$ python
... bar"""
'foo\nbar'
... bar"""
'foobar'
... bar"
'foobar'
'foobar'
Or use multiple lines of strings wrapped in parentheses...
.... "bar")
'foobar'.... "seven years ago "
.... "Prohibition was causing depression in people"
.... " before the Depression lead to drinking")
'Four score and seven years ago Prohibition was causing depression in
people before the Depression lead to drinking'
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top