问题
Possible Duplicate:
Variables inside and outside of a class __init__() function
I understand that when a class is called it will run the code in __init__
before anything. I still don't see the difference between that, and writing the code directly under the class.
For example:
class main():
x = 1
def disp(self):
print self.x
class main():
def __init__(self):
self.x = 1
def disp(self):
print self.x
To me, both have the same functionality. (Maybe I am missing out something.) I would like to know which is more (ahem) pythonic and why.
回答1:
There are a couple key differences here, both between __init__
and writing it just under the class, as well as what you wrote.
Working with x = 1
First, you are right--these two items of code do effectively the same thing for your purposes (specifically because we're working with int
objects here, this would be different for mutable objects):
Note that they don't actually do the same thing--please see the comments on this answer for clarification.
class main(object):
x = 1
class main(object):
def __init__(self):
self.x = 1
This is why many non-standard Python libraries, like mongoengine
and django
models, have a standard where you create classes without using an __init__
statement so as not to override the built-in one, but still allowing you to create class attributes, e.g., a Django example:
class mymodel(models.model):
name = models.CharField(max_length=20)
url = models.UrlField()
However, as the other poster points out, there is a difference between the two in that when x=1
is outside of the __init__
function, it is part of the class itself even when not intialized--see Zagorulkin Dmitry's answer for more detail on that. In most cases, though, that distinction won't be relevant for you.
Other considerations
There are more uses for __init__
beyond just setting variables. The most important one offhand is the ability to accept arguments during initialization. To my knowledge, there is not a way to do this without an __init__
function. I'll show you what I mean by this in this example.
Let's say we're creating a Person
class, and when we create a Person
, we supply their age, and then their birth year is automatically calculated from that for us.
import datetime
class Person(object):
def __init__(self, age):
self.age = age
self.birth_year = (datetime.date.today() - datetime.timedelta(days=age*365)).year
In use:
>>>joe = Person(23)
>>>joe.age
23
>>>joe.birth_year
1990
This wouldn't be possible without __init__
, since we couldn't pass the initialization the age
argument otherwise.
回答2:
Yes, as stated in various other questions, variables defined within the class body are attributes of the class, whereas those defined in a def __init__(self)
block are attributes of an instance of a class.
Difference between defining a member in init to defining it in the class body in Python?
回答3:
As already indicated, class attributes (assigned at class level) and instance attributes (assigned as a self attribute for example in __init__
) are different.
On the other hand, in your first class you are defining two different attributes (class x
and instance x
) that coexist, but that can interfere with each other. The code below try to show the problems you can get if you define the class that way.
In [32]: class main():
....: x = 1
....: def disp(self):
....: print(self.x)
....:
# I create 2 instances
In [33]: jim = main()
In [34]: jane = main()
# as expected...:
In [35]: main.x
Out[35]: 1
In [36]: jim.x
Out[36]: 1
In [37]: jane.x
Out[37]: 1
# now, I assign to jim attribute x
In [38]: jim.x = 5
# main class preserves its attribute value as well as jane instance
In [39]: main.x
Out[39]: 1
In [40]: jane.x
Out[40]: 1
# But what happens if I change the class attribute ?
In [41]: main.x = 10
# nothing to jim (I overwrote before jim.x)
In [42]: jim.x
Out[42]: 5
# but jane did see the change
In [43]: jane.x
Out[43]: 10
回答4:
Let us consider the following class definition:
class Main:
x = 1
def __init__(self):
self.y = 5
In this case, we can refer x directly like: Main.x
i.e. it is a class attribute, this belongs to every objects of this class.
>>>Main.x
1
But, attribute y
is specific to each object. We can not refer it directly like this:
>>> Main.y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: class Main has no attribute 'y'
You need to instantiate an object of the class Main to refer to y:
>>> obj = Main()
>>> obj.y
5
This is similar to static
variables in C++ and Java.
回答5:
it's different.
in first example you have x
without initialization.
>>> class main():
... def __init__(self):
... self.x =1
...
>>> test2 = main()
>>> dir(test2)
['__doc__', '__init__', '__module__', 'x']
>>> class main1():
... x =1
... def disp(self):
... print self.x
...
>>> dir(main1)
['__doc__', '__module__', 'disp', 'x']
>>> dir(main)
['__doc__', '__init__', '__module__']
>>>
来源:https://stackoverflow.com/questions/14037768/what-is-the-difference-writing-code-in-a-class-and-in-def-init-self-in-pyth