[Tutor] self.attribute and import attribute

Steven D'Aprano steve at pearwood.info
Sat Apr 24 05:10:00 CEST 2010


On Sat, 24 Apr 2010 12:27:12 pm Joson wrote:
> Hi all,
> I have a problem about variables efficiency.

99% of the time, you waste more of your time than you save by worrying 
about tiny efficiencies. Saving 1 minute in a program that runs for 3 
minutes is worthwhile. Saving 0.0002 seconds in a program that runs for 
0.03 seconds is not.


> As below, I import f from config.py, Then f is appended to app1.py
> global variables.

You should avoid using global variables whenever possible. They are a 
bad idea for many reasons. Just a few reasons:

They lead to excessive coupling between objects and functions.

For anything except tiny scripts, they make code harder to read, write 
and understand.

They make maintenance of the code much more difficult.

They make testing much more difficult.


> In class App, there're two ways to use this variable. One is
> "self.file =f", then use self.file; the other is using "f" directory.

Will you ever have more than one file? Then using f directly is a bad 
idea.



> Which way is high efficient?
>
> config.py:
> f = file("test.txt")

Surely there is a better name than "f" for a configuration file.



> app1.py:
> from config import *

Using import * is generally (but not always) a mistake. It makes 
debugging more difficult and leads to hard-to-find bugs. It is usually 
recommended that you write 

import config 

and then later refer to

config.f



> class App:
>     def __init__(self):
>         self.file = Attr1

Where is Attr1 defined? This code currently fails.


>     def run(self):
>         self.file.write("...")
>         # f.write("...")

The second line forces you into only ever having a single file.

The first method lets you have different files, so you could do 
something like this:

app1 = App()
app2 = App()
app1.file = file("my first file.txt", "w")
app2.file = file("my first file.txt", "w")

app2.run()
app1.run()


without each instance destroying the other instance's file.


Also, note that you keep the file open for long periods of time. This is 
generally a bad idea. If your application crashes, or the power goes 
out, the chances are very good that the data will never be written to 
disk and you will lose the data you thought you wrote to the file! It 
is best to do this:

    def run(self):
        self.file.write("...")
        self.file.flush()

Also, under some operating systems (Windows?), while the file is open, 
no other process can read from it, so backup programmers can't copy the 
file. So it is often better not to keep the file open for very long, 
but do something like this:

    def run(self):
        f = open(self.filename, 'a')
        f.write("...")
        f.close()


Even better, if you are running Python 2.6 or higher:

    def run(self):
        with open(self.filename, 'a') as f:
            f.write("...")

and the file will be automatically closed safely even if an error 
occurs!

(In Python 2.5, you can also do this if you run

from __future__ import with_statement

at the very top of your program.)




-- 
Steven D'Aprano


More information about the Tutor mailing list