繁体   English   中英

为什么要在具有功能的模块上使用python类?

[英]Why use python classes over modules with functions?

我正在自学python(3.x),我正在尝试了解类的用例。 我开始理解它们的实际作用,但是我正在努力理解为什么要使用类而不是创建带有函数的模块。

例如,如何:

class cls1:
    def func1(arguments...):
    #do some stuff


obj1 = cls1()
obj2 = cls1()

obj1.func1(arg1,arg2...)
obj2.func1(arg1,arg2...)

与......不同:

#module.py contents
    def func1(arguments...):
        #do some stuff

import module

x = module.func1(arg1,arg2...)
y = module.func1(arg1,arg2...)

这可能很简单,但是我无法理解。

到目前为止,我在编写python程序方面已经取得了相当大的成功,但是它们都具有相当的程序性,并且仅导入基本模块功能。 上课是我的下一个最大障碍。

如果需要一个类的多个实例,并且希望这些实例不会互相干扰,则可以使用该类。

模块的行为类似于单例类,因此您只能有一个实例。

编辑:例如,如果您有一个名为example.py的模块:

    x = 0
    def incr():
           global x
           x = x + 1

    def getX():
           return x

如果您尝试两次导入这些模块:

    import example as ex1
    import example as ex2

    ex1.incr()
    ex1.getX()
    1
    ex2.getX()
    1

这就是为什么仅一次导入模块,所以ex1和ex2指向同一对象的原因。

只要您仅使用纯函数(仅对它们的参数起作用的函数,对于相同的参数集始终返回相同的结果,不依赖于任何全局/共享状态并且不更改任何内容 ,也不更改其参数)也不是任何全局/共享状态-没有任何副作用的IOW函数),那么类的使用确实是有限的。 但这是函数式编程 ,尽管Python在技术上可以以函数样式使用,但在这里可能不是最佳选择。

一旦您必须在功能之间共享状态,并且特别是如果其中某些功能应该更改此共享状态,则您确实可以使用OO概念。 在函数之间共享状态的方法主要有两种:在函数之间传递状态,或使用全局变量。

第二种解决方案-全局状态-麻烦,首先是因为它使对程序流的理解(因此调试)更加困难,而且还因为它使您的代码无法重新进入 ,这在很多情况下是肯定的当前常见的用例(多线程执行,大多数服务器端Web应用程序代码等)。 实际上,它使您的代码几乎无法使用或几乎无法使用,除了简短的简单一枪脚本之外的任何事情……

第二种解决方案通常暗示使用半非正式的复杂数据结构(具有给定键集的字典,通常包含其他字典,列表,字典列表,集合等),正确地初始化它们并将它们从一个函数传递到另一个函数-当然具有在给定数据结构上工作的一组功能。 IOW您实际上是在定义新的复杂数据类型(一个数据结构和对该数据结构的一组操作)时,仅使用该语言提供的最低级别的工具。

类实际上是在更高级别上定义此类数据类型的一种方法,将数据和操作分组在一起。 它们还提供了更多的功能,特别是多态性 ,它使代码更通用,可扩展,并且使单元测试更加容易。

假设您有一个包含产品的文件或数据库,并且每个产品都有产品ID,价格,可用性,折扣,以网络状态发布以及更多值。 您将拥有包含数千个包含新价格,新产品和折扣的产品的第二个文件。 您想更新值并控制要更改的产品数量和其他统计信息。 您可以使用过程编程和函数式编程来做到这一点,但是您会发现自己试图找到使之起作用的技巧,并且很可能您会迷失在许多不同的列表和集合中。

另一方面,通过面向对象的编程,您可以创建一个具有实例变量的产品类,该实例变量包括产品ID,旧价格,旧可用性,旧折扣,旧发布状态以及一些新值(新价格)的实例变量。 ,新的可用性,新的折扣,新的发布状态)。 您要做的就是读取第一个文件/数据库,并为每个产品创建Product类的新实例。 比您可以阅读第二个文件并找到产品对象的新值。 最后,第一个文件/数据库的每个产品都将是一个对象,并将被标记并带有旧值和新值。 这种方式可以更轻松地跟踪更改,进行统计和更新数据库。

再举一个例子。 如果使用tkinter,则可以为顶级窗口创建一个类,并且每次您想要显示信息窗口或关于窗口(具有自定义颜色背景和尺寸)时,都可以简单地创建此类的新实例。

对于简单的事情,不需要类。 但是对于更复杂的事情,类有时可以使解决方案更容易。

我认为最好的答案是,这取决于缩进对象应该/应该做什么。 但是通常,类和导入的模块之间存在一些差异,这将使它们在当前模块中具有不同的功能。 最重要的是,该类已被定义为对象,这意味着它们具有很多选项,可以像模块所没有的对象一样工作。 例如,一些特殊属性,如__getattr____getattr__ __setattr__ __iter____getattr__ __setattr__等,并且具有创建大量实例甚至控制其创建方式的能力。 但是对于模块,文档很好地描述了它们的用例:

如果从Python解释器退出并再次输入,则所做的定义(函数和变量)将丢失。 因此,如果要编写更长的程序,最好使用文本编辑器为解释器准备输入,然后使用该文件作为输入来运行它。 这称为创建脚本。 随着程序时间的延长,您可能需要将其拆分为多个文件,以便于维护。 您可能还想使用在多个程序中编写的便捷功能,而无需将其定义复制到每个程序中。

为此,Python提供了一种将定义放入文件中并在脚本或解释器的交互式实例中使用它们的方法。 这样的文件称为模块; 可以将模块中的定义导入其他模块或主模块中(您可以在顶层和计算器模式下执行的脚本中访问的变量集合)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM