What is the difference writing code in a class and

2019-03-02 19:07发布

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.

5条回答
仙女界的扛把子
2楼-- · 2019-03-02 19:50

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.

查看更多
你好瞎i
3楼-- · 2019-03-02 19:53

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__']
>>>
查看更多
该账号已被封号
4楼-- · 2019-03-02 20:00

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
查看更多
放荡不羁爱自由
5楼-- · 2019-03-02 20:04

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?

查看更多
仙女界的扛把子
6楼-- · 2019-03-02 20:04

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.

查看更多
登录 后发表回答