Global variables, Classes, inheritance

D

DaveM

Although I've programmed for fun - on and off - since the mid 70's, I'm
definitely an OO (and specifically Python) beginner.

My first question is about global variables. Are they, as I'm starting to
suspect, a sin against God or just best avoided? Having got my current
application working using them, I'm not sure whether I want to refactor it,
but equally, I'd like to write the best code I can.

Secondly (and this is related), if you have multiple instances of the same
class, but need them all to have access to a dictionary created at run-time,
is there a class way to this without calling the creation method multiple
times? The best thought I've come up with is for the class instance to check
its name and only if it's the first one do the dictionary creation, but I
haven't tried it yet.

My third difficulty is with variables in a class. What's the difference
between the following?:

class Foo:
i = 12345
...

class Foo:
self.i = 12345
...

class Foo:
def __init__(self):
self.i = 12345
...

class Foo:
def __init(self):
i = 12345
...

DaveM
 
C

Claudio Grondi

DaveM said:
Although I've programmed for fun - on and off - since the mid 70's, I'm
definitely an OO (and specifically Python) beginner.

My first question is about global variables. Are they, as I'm starting to
suspect, a sin against God or just best avoided? Having got my current
application working using them, I'm not sure whether I want to refactor it,
but equally, I'd like to write the best code I can.
For me global variables in Python are not that much sin as global
variables in another languages (as e.g. C/C++).
Secondly (and this is related), if you have multiple instances of the same
class, but need them all to have access to a dictionary created at run-time,
is there a class way to this without calling the creation method multiple
times? The best thought I've come up with is for the class instance to check
its name and only if it's the first one do the dictionary creation, but I
haven't tried it yet.

My third difficulty is with variables in a class. What's the difference
between the following?:

class Foo:
i = 12345
...

class Foo:
self.i = 12345
...

class Foo:
def __init__(self):
self.i = 12345
...

class Foo:
def __init(self):
i = 12345
...

DaveM

Before some expert will enlighten you and provide appropriate links, you
can just try to run what you have listed (e.g. to see what is broken)
and watch the outcome.

Maybe it is a good idea to try to look at globals() and locals() to see
what and when happens and take a look at the documentation to see what
this functions are about.

Claudio
 
M

Michael Spencer

DaveM said:
Although I've programmed for fun - on and off - since the mid 70's, I'm
definitely an OO (and specifically Python) beginner.

My first question is about global variables. Are they, as I'm starting to
suspect, a sin against God or just best avoided? Having got my current
application working using them, I'm not sure whether I want to refactor it,
but equally, I'd like to write the best code I can.

Use them sparingly IMO
Secondly (and this is related), if you have multiple instances of the same
class, but need them all to have access to a dictionary created at run-time,
is there a class way to this without calling the creation method multiple
times? The best thought I've come up with is for the class instance to check
its name and only if it's the first one do the dictionary creation, but I
haven't tried it yet.

Make the dictionary an attribute of the class, not the instance. Then it will
be visible by all the instances. See below:

My third difficulty is with variables in a class. What's the difference
between the following?:

class Foo:
i = 12345
...

this sets i as an attribute of the class.

class Foo:
self.i = 12345
...

this probably raises a NameError, unless you happen to have bound 'self' in the
scope containing Foo, which would be a really bad idea

class Foo:
def __init__(self):
self.i = 12345
...

this sets i as an attribute of the instance, self, when it is initialized
class Foo:
def __init(self):
i = 12345
...

this assigns the name 'i' in the local scope of the __init__ function. It has
no effect on self


So, to get your shared dictionary, you could write: ... shared_dict = {}
...
>>>
>>> a1 = A()
>>> a2 = A()
>>> a1.shared_dict is a2.shared_dict True
>>> a1.shared_dict["a"] = 42
>>> a2.shared_dict["a"] 42
>>>

Note also, that you create "classic" classes by writing `class Foo:`, and "new
style" classes by writing `class Foo(object):`. There are several subtle
differences between the two, and, since you are just starting, you might as well
learn with the new ones.

HTH

Michael
 
K

Kirk McDonald

DaveM said:
Although I've programmed for fun - on and off - since the mid 70's, I'm
definitely an OO (and specifically Python) beginner.

My first question is about global variables. Are they, as I'm starting to
suspect, a sin against God or just best avoided? Having got my current
application working using them, I'm not sure whether I want to refactor it,
but equally, I'd like to write the best code I can.

Python globals are actually remarkably safe, at least compared to some
other languages. The key is that, when you import a module, its globals
stay in its namespace. I've got nothing against them.
Secondly (and this is related), if you have multiple instances of the same
class, but need them all to have access to a dictionary created at run-time,
is there a class way to this without calling the creation method multiple
times? The best thought I've come up with is for the class instance to check
its name and only if it's the first one do the dictionary creation, but I
haven't tried it yet.

A class attribute would do this easily:

class Foo(object):
d = {}

a = Foo()
b = Foo()
Foo.d = { 'a' : 'apple' }
print a.d
print b.d

That will print out {'a':'apple'} twice.
My third difficulty is with variables in a class. What's the difference
between the following?:

class Foo:
i = 12345
...

i is a class attribute. It is bound to the class (which is, itself, an
object). You can access i both from the class itself as well as from an
instance of the class, i.e., Foo.i and Foo().i will both work.
class Foo:
self.i = 12345
...

This does not work. There is no name 'self' bound to class Foo.
class Foo:
def __init__(self):
self.i = 12345
...

This binds the name 'i' to all instances of class Foo; if this were C++,
we'd call self.i a member variable.
class Foo:
def __init(self):
i = 12345
...

(You forgot the trailing __, but whatever. :) This binds the name 'i'
to the local namespace of the __init__ function. It is just like any
other local variable in a function.

Namespaces in Python are really great. It is worth reading up on
globals() and locals() if you don't get them yet.

-Kirk McDonald
 
D

DaveM

Thanks very much for the help to all who replied.
I'd completely missed the difference between:

class Foo:
i = 12345

a = Foo()
b = Foo()

a.i = 678

and Foo.i = 678

Yeah, I know...

DaveM
 

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,995
Messages
2,570,231
Members
46,820
Latest member
GilbertoA5

Latest Threads

Top