Python 创建带有类的对象时,为什么需要_init__(self,args):?

Python 创建带有类的对象时,为什么需要_init__(self,args):?,python,class,object,init,Python,Class,Object,Init,很抱歉提出这样奇怪的问题,通常当我感到困惑时,我只是“跟着它走”,直到我有一个顿悟,然后把它整理出来,但是在我的类中调用def\uuu init\uuuuuself:似乎是完全多余的,似乎忽略它也同样有效: class Pet(object): type_of_pet = "" number_of_legs = 0 name = "" 让我创建: fred = pet() fred.type_of_pet = "alligator" 就像我要把课堂改成: class

很抱歉提出这样奇怪的问题,通常当我感到困惑时,我只是“跟着它走”,直到我有一个顿悟,然后把它整理出来,但是在我的类中调用
def\uuu init\uuuuuself:
似乎是完全多余的,似乎忽略它也同样有效:

class Pet(object):
    type_of_pet = ""
    number_of_legs = 0
    name = ""
让我创建:

fred = pet()
fred.type_of_pet = "alligator"
就像我要把课堂改成:

class Pet(object):
    def __init__(self):
         type_of_pet = ""

alice = Pet()
alice.type_of_pet = "Pterodactyl" 
class Pet(object):
    def __init__(self, type_of_pet):
         self.type_of_pet = type_of_pet

我只是不明白为什么我需要
\uuuu init\uuuu
,这里的其他线程没有我希望的那么清楚。我能做些什么来实现这个“点击”吗?

在类定义中放置赋值语句不会声明实例属性;它设置类属性。如果您这样做,所有宠物将共享相同的
名称
宠物类型
,以及
腿数

\uuuu init\uuuu
用于设置实例属性:

def __init__(self, type_of_pet, name, number_of_legs):
    self.type_of_pet = type_of_pet
    self.name = name
    self.number_of_legs = number_of_legs

这将在实例而不是类上设置属性,因此每个对象都有自己的名称、类型和分支数。

当您直接在类中定义成员时,这些成员将成为类本身的一部分,而不是类实例的一部分。您仍然可以通过实例访问它们,但每个实例都没有自己的

\uuuuu init\uuuuu
是一种构造函数,在创建类的实例时, python在实例化期间调用
\uuuu init\uuuu()
,以定义在实例化类时应发生的其他行为,基本上是为该对象设置一些起始值或运行实例化所需的例程

(

例如,您可以将宠物类更改为:

class Pet(object):
    def __init__(self):
         type_of_pet = ""

alice = Pet()
alice.type_of_pet = "Pterodactyl" 
class Pet(object):
    def __init__(self, type_of_pet):
         self.type_of_pet = type_of_pet
并使用以下内容创建一个新实例:

alice = Pet("Pterodactyl")
如果您在
\uuuu init\uuuu
函数之外初始化类变量,则每个实例都将共享该值。这对于静态类很有用,但我认为您不希望在“普通”类上出现这种行为


顺便说一句,您不能在
\uuuu init\uuuu
中使用
type\u of_pet=“”
,它必须是
自身。在创建类的每个实例后,会立即对其调用
type\u of_pet=“”

\uu init\uuu
。这是执行实例级初始化的正确位置

第一个示例中定义的
type\u\u\u宠物
和其他属性是类级信息。该表单声明
pet
类本身具有
type\u\u宠物
值,该值与您可能定义的任何方法处于同一级别

当您检查一个实例的名称时,如果有,它将获得分配给该实例的值,如果没有,则转到类级别。因此:

fred = Pet()
print fred.type_of_pet
实际检查类本身的
类型\u pet

赋值将只修改您实际调用它的对象,因此这将在实例级别设置一个值:

fred.type_of_pet = 'alligator'
这不会对类进行任何更改,只会在
fred
实例中为\u pet
的name
type\u添加一个值。因此,通常使用类级定义作为实例的默认值

但这会给您带来麻烦的是像list这样的可变类型

class Pet:
    vaccinations = []

fido = Pet()
fido.vaccinations.append('rabies')
因为
fido.vaccurations
最终是对类级别定义的单个列表的引用。相反,您可以使用
\uuuuu init\uuuuu
为每个宠物提供自己的独立列表


就我个人而言,我越来越相信使用类级属性作为不可更改类型的默认值会造成更多的混乱,并且应该只保存那些真正应该在类级跟踪的内容,而不是每个实例。但这是我的观点。

你在问为什么需要
\uu init\uuuu()
当类实例化后,您可以在类上分配属性

答案是,您可以在实例化对象时传递属性值,就像您应该传递的那样。这不仅可以节省您键入的时间;在实例化后在类上分配属性很容易出错:如果您意外地分配给
number\u off\u legs
而不是
number\u of\u legs
,这本身不是一个问题n错误,因为属性可能被命名为任何名称,但它将导致其他代码(期望
腿数
)失败,或者在您的情况下,获取错误的数据(因为此时将使用类的默认值)。此外,如果您需要更改属性名称,则该名称会遍布您的代码,因此您需要在许多地方更改它


因此,为了避免这些麻烦,您需要编写一个小函数来创建对象,然后分配对象上的属性,并在将对象返回给您之前执行任何其他必要的初始化(打开文件、创建从属对象等等)
方法和Python将其附加到类中,这样您就可以实例化对象并一次性传递属性值。当您只存储一些数据时,它似乎不是很有用,但当您的类变得更复杂时,您会发现它非常方便。

好的,我注意到将对象放在类下会it’它就像一个全局变量……Init就是这样,每次我执行newThing=Class()时,我都会指定“local”属性,而不是“globals”?@ford:Global/local和class/instance是非常相似的概念,将某些东西放到
\uuuu init\uuuu
vs class-level非常类似于将其设置为局部而不是全局。请注意,属性绑定到对象,而不是
\uuu init\uuuu
方法,因此对该对象的任何方法调用都将看到相同的属性,而不是全局属性创建新的。这与函数中的局部变量不同。太棒了。这真的很有帮助。非常感谢。您肯定不想在
\uuuu init\uuuu
中编写
type\u of_pet=“
。这只会设置一个立即消失的局部变量。您可能需要