After using Django for a while, I got use to using classes without def __init__(self): ... when declaring variables. I used to declare my variables in the __init__ function, I now realize that there are cases where don't need to, I'm just unclear on when to use it or not. It seems there is a problem when trying to pass a class to a variable, should I use init in these cases?
I know I could just use __init__ for all cases, but it just makes my short classes like cleaner without it, so I would like to know when I can and cannot use it.
example:
class BaseScraper(object):
# whithout __init__, passing Site() to site wont work.
# site = Site()
# parser = None
def __init__(self):
self.site = Site()
self.parser = None
class Site(object):
# no trouble declaring url as a str
url = ""
def set(self, url):
self.url = url
def get(self):
return self.url
if __name__ == "__main__":
scraper = BaseScraper()
scraper.site.set('http://www.google.com')
print scraper.site.get()
2 Answers 2
Attributes declared in the class are owned by the class rather than by individual instances of the class. In your site example, url is no more a property of individual Site objects than set or get are. For this kind of example, you want instance data - which you can initialize in __init__.
Python: Difference between class and instance attributes has a good discussion of the differences.
Comments
This fails because Site class is not defined yet.
And (as @Peter DeGlopper) said, there is a big difference between class variables and instance variables.
class BaseScraper(object):
# This fails!
site = Site()
parser = None
class Site(object):
# no trouble declaring url as a str
url = ""
def set(self, url):
self.url = url
def get(self):
return self.url
When the virtual machine compile a python module, read and compile everything in class declaration, but on method declaration (like def __init__(...):) only read this line, ignoring the method body.
Example:
class Foo(object):
bar1 = "bar"
foo1 = "foo"
def __init__(self):
self.bar2 = "BAZ"
foo = Foo #Put a class in a veriable? yes, you can.
foo.bar1 # returns "bar"
foo.foo1 # returns "foo"
foo.bar2 # fails!!!! This will be a instance variable, but doesn't exist yet
foo2 = Foo() # Here the __init__ is called
foo2.bar2 # returns "BAZ"
foo2.bar1 #Returns "bar" because all class variables are availables from instances
Hope this helps =)
Model's__init__()method (or some other part of that wad of code) uses to automagically create instance-level attributes and do a bunch of other stuff. Python doesn't normally work that way.__init__unless you know what you're doing. (That class-level attributes kinda sorta act like they're default values for instance attributes is a bit of a hack with a bunch of caveats.)