Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 无需初始化的面向对象编程_Python_Oop - Fatal编程技术网

Python 无需初始化的面向对象编程

Python 无需初始化的面向对象编程,python,oop,Python,Oop,我读过很多类似的问题,但我还是不明白 看看这个例子: class Cat: pass a_cat = Cat a_cat.name = "hs" a_cat.name 'hs' #returns this 上面我已经创建了一个cat类的实例,它的名字是关于那只猫的。没有使用初始化 下面是一个类似的示例,但使用了_uinit 问题: 如果两个版本都允许将方法传递给每个类的各个实例,那么为什么还要费心做第二种方法呢?它们看起来是相同的结果。不同之处在于初始化对象时调用init方法,例如,

我读过很多类似的问题,但我还是不明白

看看这个例子:

class Cat:
    pass

a_cat = Cat
a_cat.name = "hs"
a_cat.name
'hs' #returns this
上面我已经创建了一个cat类的实例,它的名字是关于那只猫的。没有使用初始化

下面是一个类似的示例,但使用了_uinit

问题:
如果两个版本都允许将方法传递给每个类的各个实例,那么为什么还要费心做第二种方法呢?它们看起来是相同的结果。

不同之处在于初始化对象时调用init方法,例如,这意味着您需要传递参数。假设您有一个具有颜色的类狗,您不能使用没有颜色的狗,因此您需要传递颜色,否则依赖于此颜色的函数将无法运行。 这里还有一个很好的链接可以解释:

以狗为例,假设你有一个函数

打印颜色


如果不使用颜色初始化该类,该函数将不会运行。__init__函数始终在初始化时运行,您可以指定从对象初始化时必须传递的参数。参考狗->颜色。

不同之处在于初始化对象时调用init方法,例如,这意味着您需要传递参数。假设您有一个具有颜色的类狗,您不能使用没有颜色的狗,因此您需要传递颜色,否则依赖于此颜色的函数将无法运行。 这里还有一个很好的链接可以解释:

以狗为例,假设你有一个函数

打印颜色


如果不使用颜色初始化该类,该函数将不会运行。__init__函数始终在初始化时运行,您可以指定从对象初始化时必须传递的参数。参考狗->颜色。

第一种方法和第二种方法的区别在于,在第二种方法的帮助下,您强制新创建的对象在调用其任何方法之前具有一些默认值


通过这种方式,我们可以避免在调用处理没有值的属性的方法时出错。

第一种方法和第二种方法的区别在于,在第二种方法的帮助下,在调用其任何方法之前,您将强制新创建的对象具有一些默认值


通过这种方式,我们可以避免在调用处理没有值的属性的方法时出错。

第一种方法的问题是,除非指定属性,否则猫没有名称属性。在实用的OOP中,它更像是一种范例,而不是任何特定的语言实现,而且肯定也可以在Python中正确完成,您希望同一类的对象具有相同的协议(属性和方法集),这在编写使用这些类的代码时非常有帮助。例如,如果您有使用Cat类的Vet类,Vet的程序员不需要在使用它之前检查Cat的每个实例是否有名称,因为名称是Cat协议的一部分,并且始终存在


在Python中,init通常用于确保类的所有实例在实例化时都具有所有必需的属性,因此当Vet类中的某个人使用“A”进行初始化时,如果cat.name.startswith“A”,则不会在cat的特定实例中未设置name属性时出现AttributeError异常。

第一种方法是,除非指定名称属性,否则猫没有名称属性。在实用的OOP中,它更像是一种范例,而不是任何特定的语言实现,而且肯定也可以在Python中正确完成,您希望同一类的对象具有相同的协议(属性和方法集),这在编写使用这些类的代码时非常有帮助。例如,如果您有使用Cat类的Vet类,Vet的程序员不需要在使用它之前检查Cat的每个实例是否有名称,因为名称是Cat协议的一部分,并且始终存在


在Python中,init通常用于确保类的所有实例在实例化时都具有所有必需的属性,因此当Vet类中的某个人使用“A”进行初始化时,如果cat.name.startswith“A”,则不会在cat的特定实例中未设置name属性时出现AttributeError异常。

面向对象编程就是封装。当您定义一个对象时,您将一些关于真实世界的知识封装到这个对象中

封装就是禁止直接从外部世界操纵对象的内部状态。通过操纵内部状态,我指的是直接修改对象属性,与您的示例完全相同:

dog = Dog()
dog.name = 'Spot'
这与OOP试图实现的目标恰恰相反

相反,OOP建立了一个定义良好的模式:在创建对象时使用初始状态初始化对象。那么,这里是哪里 构造函数来自。为了在创建对象时初始化它,您需要将一些参数传递给构造函数


这就是为什么带参数的构造函数方法总是优于创建然后分配属性的方法。更重要的是,在理想世界中,每个对象在创建初始状态后都应该是不可变的,并且只允许查询它的状态并禁止更改它。

面向对象编程就是封装。当您定义一个对象时,您将一些关于真实世界的知识封装到这个对象中

封装就是禁止直接从外部世界操纵对象的内部状态。通过操纵内部状态,我指的是直接修改对象属性,与您的示例完全相同:

dog = Dog()
dog.name = 'Spot'
这与OOP试图实现的目标恰恰相反

相反,OOP建立了一个定义良好的模式:在创建对象时使用初始状态初始化对象。所以,这里是构造函数的来源。为了在创建对象时初始化它,您需要将一些参数传递给构造函数


这就是为什么带参数的构造函数方法总是优于创建然后分配属性的方法。更重要的是,在理想世界中,每个对象在使用初始状态创建后都应该是不可变的,并且只允许查询它的状态并禁止更改它。

关于您答案的最后一部分:我编写的版本没有使用名称初始化,但它正常运行。在a_cat=cat之后,我没有得到它,如果您尝试打印a_cat.name,您将得到错误。对于狗,在doggo=Dogad之后。如果您厌倦了printdogo.name,您将不会得到错误,因为它在对象初始化过程中添加了函数init。对于从父对象类运行init的cat示例,也会执行函数init。就你的狗而言,您希望init中有一个值function@SanthoshKumar我试过你说的话,两人都没有犯错误all@user12436030尝试运行此类Cat:def print_color:printself.color c=Cat c.print_color,因为您没有设置self.color的初始化函数,因此它将失败。关于答案的最后一部分:我编写的版本没有用名称初始化,但它运行正常。在a_cat=cat之后,我没有得到它,如果您尝试打印a_cat.name,您将得到错误。对于狗,在doggo=Dogad之后。如果您厌倦了printdogo.name,您将不会得到错误,因为它在对象初始化过程中添加了函数init。对于从父对象类运行init的cat示例,也会执行函数init。就你的狗而言,您希望init中有一个值function@SanthoshKumar我试过你说的话,两人都没有犯错误all@user12436030尝试运行此类Cat:def print_color:printself.color c=Cat c.print_color,因为您没有设置self.color的init函数,它将失败,因此这两个版本的工作方式相同,但是有助于组织使用init完成这项工作,并设置将用作参数的方法?当然,这两种方法的最终结果是相同的。使用init的方式更实用、更干净、更可预测。此外,您不需要在uuu init_uuu中拥有所有初始化属性。例如,当您从文件初始化Cat时,您可能只有_init__self、文件及其主体打开文件并加载所有参数等等。。。这两个版本的工作原理是一样的,但它有助于组织使用init并设置将用作参数的方法?当然,这两种方法的最终结果是相同的。使用init的方式更实用、更干净、更可预测。此外,您不需要在uuu init_uuu中拥有所有初始化属性。例如,当您从文件初始化Cat时,您可能只有_init__self、文件及其主体打开文件并加载所有参数等等。。。因此,并非所有情况下都完全相同。