为什么我们在 Python 类中使用 __init__? [英] Why do we use __init__ in Python classes?

查看:28
本文介绍了为什么我们在 Python 类中使用 __init__?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法理解类的初始化.

I am having trouble understanding the Initialization of classes.

它们的意义何在?我们如何知道要在其中包含哪些内容?在类中编写与创建函数是否需要不同类型的思维(我认为我可以创建函数,然后将它们包装在一个类中,以便我可以重复使用它们.这行得通吗?)

What's the point of them and how do we know what to include in them? Does writing in classes require a different type of thinking versus creating functions (I figured I could just create functions and then just wrap them in a class so I can re-use them. Will that work?)

这是一个例子:

class crawler:
  # Initialize the crawler with the name of database
  def __init__(self,dbname):
    self.con=sqlite.connect(dbname)

  def __del__(self):
    self.con.close()

  def dbcommit(self):
    self.con.commit()

或其他代码示例:

class bicluster:
  def __init__(self,vec,left=None,right=None,distance=0.0,id=None):
    self.left=left
    self.right=right
    self.vec=vec
    self.id=id
    self.distance=distance

我在尝试阅读其他人的代码时遇到了很多带有 __init__ 的类,但我不明白创建它们的逻辑.

There are so many classes with __init__ I come across when trying to read other people's code, but I don't understand the logic in creating them.

推荐答案

根据您所写的内容,您缺少一个重要的理解:类和对象之间的区别.__init__ 不初始化一个类,它初始化一个类或一个对象的实例.每条狗都有颜色,但狗作为一个类没有.每只狗有四只或更少的脚,但狗类没有.类是对象的概念.当您看到 Fido 和 Spot 时,您会认识到他们的相似之处,他们的狗血统.这就是课堂.

By what you wrote, you are missing a critical piece of understanding: the difference between a class and an object. __init__ doesn't initialize a class, it initializes an instance of a class or an object. Each dog has colour, but dogs as a class don't. Each dog has four or fewer feet, but the class of dogs doesn't. The class is a concept of an object. When you see Fido and Spot, you recognise their similarity, their doghood. That's the class.

当你说

class Dog:
    def __init__(self, legs, colour):
        self.legs = legs
        self.colour = colour

fido = Dog(4, "brown")
spot = Dog(3, "mostly yellow")

你是说,Fido 是一只棕色的狗,有 4 条腿,而 Spot 有点跛子,大部分是黄色的.__init__ 函数称为构造函数或初始化程序,并在您创建类的新实例时自动调用.在该函数中,新创建的对象被分配给参数self.符号self.legs 是变量self 中对象的称为legs 的属性.属性有点像变量,但它们描述对象的状态,或对象可用的特定操作(函数).

You're saying, Fido is a brown dog with 4 legs while Spot is a bit of a cripple and is mostly yellow. The __init__ function is called a constructor, or initializer, and is automatically called when you create a new instance of a class. Within that function, the newly created object is assigned to the parameter self. The notation self.legs is an attribute called legs of the object in the variable self. Attributes are kind of like variables, but they describe the state of an object, or particular actions (functions) available to the object.

但是,请注意您没有为 doghood 本身设置 colour - 这是一个抽象概念.有些属性对类有意义.例如,population_size 就是这样一个——计算 Fido 没有意义,因为 Fido 总是一.数狗确实有意义.假设世界上有 2 亿只狗.它是 Dog 类的属性.Fido 与 2 亿这个数字无关,Spot 也没有.它被称为类属性",而不是实例属性".上面的 colourlegs.

However, notice that you don't set colour for the doghood itself - it's an abstract concept. There are attributes that make sense on classes. For instance, population_size is one such - it doesn't make sense to count the Fido because Fido is always one. It does make sense to count dogs. Let us say there're 200 million dogs in the world. It's the property of the Dog class. Fido has nothing to do with the number 200 million, nor does Spot. It's called a "class attribute", as opposed to "instance attributes" that are colour or legs above.

现在,少一些犬类,更多与编程相关.正如我在下面写的那样,添加东西的类是不明智的 - 它是什么类?Python 中的类由行为相似的不同数据的集合组成.狗类包括 Fido 和 Spot 以及 199999999998 其他与它们相似的动物,它们都在灯柱上撒尿.添加东西的类由什么组成?它们的不同之处在于它们固有的哪些数据?他们共享哪些操作?

Now, to something less canine and more programming-related. As I write below, class to add things is not sensible - what is it a class of? Classes in Python make up of collections of different data, that behave similarly. Class of dogs consists of Fido and Spot and 199999999998 other animals similar to them, all of them peeing on lampposts. What does the class for adding things consist of? By what data inherent to them do they differ? And what actions do they share?

然而,数字……那些是更有趣的主题.说,整数.他们有很多,比狗多得多.我知道 Python 已经有整数了,但让我们玩个哑巴实现"吧.再次(通过欺骗和使用 Python 的整数).

However, numbers... those are more interesting subjects. Say, Integers. There's a lot of them, a lot more than dogs. I know that Python already has integers, but let's play dumb and "implement" them again (by cheating and using Python's integers).

所以,整数是一个类.它们有一些数据(值)和一些行为(将我添加到另一个数字").让我们展示一下:

So, Integers are a class. They have some data (value), and some behaviours ("add me to this other number"). Let's show this:

class MyInteger:
    def __init__(self, newvalue):
        # imagine self as an index card.
        # under the heading of "value", we will write
        # the contents of the variable newvalue.
        self.value = newvalue
    def add(self, other):
        # when an integer wants to add itself to another integer,
        # we'll take their values and add them together,
        # then make a new integer with the result value.
        return MyInteger(self.value + other.value)

three = MyInteger(3)
# three now contains an object of class MyInteger
# three.value is now 3
five = MyInteger(5)
# five now contains an object of class MyInteger
# five.value is now 5
eight = three.add(five)
# here, we invoked the three's behaviour of adding another integer
# now, eight.value is three.value + five.value = 3 + 5 = 8
print eight.value
# ==> 8

这有点脆弱(我们假设 other 将是一个 MyInteger),但我们现在将忽略.在实际代码中,我们不会;我们会测试它以确保,甚至可能会强制它(你不是整数?天哪,你有 10 纳秒变成整数!9 ... 8 ....")

This is a bit fragile (we're assuming other will be a MyInteger), but we'll ignore now. In real code, we wouldn't; we'd test it to make sure, and maybe even coerce it ("you're not an integer? by golly, you have 10 nanoseconds to become one! 9... 8....")

我们甚至可以定义分数.分数也知道如何相加.

We could even define fractions. Fractions also know how to add themselves.

class MyFraction:
    def __init__(self, newnumerator, newdenominator):
        self.numerator = newnumerator
        self.denominator = newdenominator
        # because every fraction is described by these two things
    def add(self, other):
        newdenominator = self.denominator * other.denominator
        newnumerator = self.numerator * other.denominator + self.denominator * other.numerator
        return MyFraction(newnumerator, newdenominator)

分数比整数还多(不是真的,但计算机不知道).让我们做两个:

There's even more fractions than integers (not really, but computers don't know that). Let's make two:

half = MyFraction(1, 2)
third = MyFraction(1, 3)
five_sixths = half.add(third)
print five_sixths.numerator
# ==> 5
print five_sixths.denominator
# ==> 6

您实际上并未在此处声明任何内容.属性就像一种新的变量.正常变量只有一个值.假设您编写了 colour = "grey".您不能有另一个名为 colour 的变量,即 "fuchsia" - 不在代码中的同一位置.

You're not actually declaring anything here. Attributes are like a new kind of variable. Normal variables only have one value. Let us say you write colour = "grey". You can't have another variable named colour that is "fuchsia" - not in the same place in the code.

数组在一定程度上解决了这个问题.如果你说 colour = [grey", fuchsia"],你已经将两种颜色堆叠到变量中,但是你可以通过它们的位置(0 或 1,在这种情况下)来区分它们.

Arrays solve that to a degree. If you say colour = ["grey", "fuchsia"], you have stacked two colours into the variable, but you distinguish them by their position (0, or 1, in this case).

属性是绑定到对象的变量.和数组一样,我们可以有很多 color 变量,针对不同的狗.所以,fido.colour 是一个变量,而 spot.colour 是另一个变量.第一个绑定到变量 fido 内的对象;第二个,spot.现在,当您调用 Dog(4, "brown")three.add(five) 时,总会有一个不可见的参数,它将被分配给参数列表前面的额外悬空.它通常被称为self,它将获取点前面的对象的值.因此,在 Dog 的 __init__(构造函数)中,self 将成为新 Dog 将成为的任何东西;在MyIntegeradd中,self将绑定到变量three中的对象.因此,three.value 将是 add 之外的相同变量,与 add 内的 self.value 相同.

Attributes are variables that are bound to an object. Like with arrays, we can have plenty colour variables, on different dogs. So, fido.colour is one variable, but spot.colour is another. The first one is bound to the object within the variable fido; the second, spot. Now, when you call Dog(4, "brown"), or three.add(five), there will always be an invisible parameter, which will be assigned to the dangling extra one at the front of the parameter list. It is conventionally called self, and will get the value of the object in front of the dot. Thus, within the Dog's __init__ (constructor), self will be whatever the new Dog will turn out to be; within MyInteger's add, self will be bound to the object in the variable three. Thus, three.value will be the same variable outside the add, as self.value within the add.

如果我说the_mangy_one = fido,我将开始用另一个名称来引用称为fido 的对象.从现在开始,fido.colourthe_mangy_one.colour 完全相同.

If I say the_mangy_one = fido, I will start referring to the object known as fido with yet another name. From now on, fido.colour is exactly the same variable as the_mangy_one.colour.

那么,__init__ 里面的东西.你可以把它们看作是在狗的出生证明上记下的东西.color 本身是一个随机变量,可以包含任何内容.fido.colourself.colour 就像是狗身份证上的一个表单域;而__init__是第一次填写的文员.

So, the things inside the __init__. You can think of them as noting things into the Dog's birth certificate. colour by itself is a random variable, could contain anything. fido.colour or self.colour is like a form field on the Dog's identity sheet; and __init__ is the clerk filling it out for the first time.

有更清楚的吗?

编辑:扩展下面的评论:

您是说对象的列表,对吗?

首先,fido 实际上不是一个对象.它是一个变量,当前包含一个对象,就像当你说 x = 5 时,x 是一个当前包含数字 5 的变量.如果你后来改变主意,你可以做 fido = Cat(4, "pleasing")(只要你创建了一个 Cat 类),并且 fido 将从那时起包含"一个猫对象.如果您执行 fido = x,它将包含数字 5,而根本不是动物对象.

First of all, fido is actually not an object. It is a variable, which is currently containing an object, just like when you say x = 5, x is a variable currently containing the number five. If you later change your mind, you can do fido = Cat(4, "pleasing") (as long as you've created a class Cat), and fido would from then on "contain" a cat object. If you do fido = x, it will then contain the number five, and not an animal object at all.

一个类本身不知道它的实例,除非你专门编写代码来跟踪它们.例如:

A class by itself doesn't know its instances unless you specifically write code to keep track of them. For instance:

class Cat:
    census = [] #define census array

    def __init__(self, legs, colour):
        self.colour = colour
        self.legs = legs
        Cat.census.append(self)

这里,censusCat类的类级属性.

Here, census is a class-level attribute of Cat class.

fluffy = Cat(4, "white")
spark = Cat(4, "fiery")
Cat.census
# ==> [<__main__.Cat instance at 0x108982cb0>, <__main__.Cat instance at 0x108982e18>]
# or something like that

请注意,您不会得到 [fluffy, sparky].这些只是变量名.如果你想让猫自己有名字,你必须为名字做一个单独的属性,然后覆盖__str__方法来返回这个名字.此方法(即类绑定函数,就像add__init__)的目的是描述如何将对象转换为字符串,就像打印出来时一样.

Note that you won't get [fluffy, sparky]. Those are just variable names. If you want cats themselves to have names, you have to make a separate attribute for the name, and then override the __str__ method to return this name. This method's (i.e. class-bound function, just like add or __init__) purpose is to describe how to convert the object to a string, like when you print it out.

这篇关于为什么我们在 Python 类中使用 __init__?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆