拥有许多不同数据类型有什么好处?

时间:2011-12-31 08:48:58

标签: python types pyqt qwt

在一种语言中使用许多不同的数据类型有什么好处?我最近一直在使用pyqt和pyqwt,我一直在找自己输入这样的行:

grid.setPen(Qt.QPen(Qt.Qt.gray, 0, Qt.Qt.DotLine))
curve.setSymbol(Qwt.QwtSymbol(Qwt.QwtSymbol.Ellipse,
                              Qt.QBrush(),
                              Qt.QPen(Qt.Qt.black),
                              Qt.QSize(5, 5)))

如果以上几行代替以下内容会丢失什么?:

grid.setPen('gray', 0 ,'dotted')
curve.setSymbol('ellipse', 'k', (5,5))

即使由于某些技术原因需要特定类型,也不能将字符串转换为需要它们的方法中的那些类型?

这是因为pyqt和pyqwt只是C ++库的绑定吗?如果是这样,为什么在C ++中需要它们?

5 个答案:

答案 0 :(得分:4)

有一些好处:

  1. 类型安全语言(如C ++)的优点是在编译时发现了许多错误(与运行时相反)。这意味着使用Qt.grey(注意e)将无法编译,因为未定义类型。

  2. 更好的性能和更少的内存。在幕后,Qt.gray是一个数字,数字操作比字符串快得多。

  3. 在pyqt案例中,因为库包装了一个C ++库,所以它看起来更像是c ++,而不像Python代码。

答案 1 :(得分:3)

不同的类型让你在编译时间(至少在C ++中)检查你正在传递正确的东西 - 例如,如果一切都是字符串,那就很容易了意外错误'gray',比如'grey',可能会混淆图书馆。

正常的模式是做更像这样的事情:

greypen = Qt.QPen(Qt.Qt.gray, 0, Qt.Qt.DotLine)
blackpen = Qt.QPen(Qt.Qt.black, 0, Qt.Qt.DotLine)
# ...
grid.setPen(greypen)
# ...
grid.setPen(blackpen)

如果您多次使用相同类型的属性,那么就不会重复自己。

答案 2 :(得分:1)

这是因为它们是对象 如果你使用这个QPen :: QPen() 然后它做的是构造一个0宽度的默认黑色实线笔。 但由于它已经过载,你可以使用那些构造函数的参数 当您在QPen类中传递参数时,您处理的内容将被处理,结果将返回。所以那些是面向对象的概念。你需要做一个实例 并且该实例将处理它的底层部分。如果您使用字符串参数,就像您在第二个示例中使用的那样,它将只使用字符串类型而不是Qt.QPen()类型。 setPen()函数要求输入对象的QPen()而不是字符串类型的变量。 优点是你不需要从底层写下所有东西。并且某些部分是预定义的视频游戏。在视频游戏中你不能做很多功能。如果你向别人开枪,他会射击你或逃跑,所以反应取决于你所做的动作。 动作是参数,反应是该类中某个函数的返回值。在幕后,可能会有大量代码执行各种任务。就像他的反应方式,时间,无论是跑步还是走路或飞行时你都会被设置为默认值,除非你特别改变它们。有时您不需要更改这些默认值,或者需要时间。在这种情况下,只需通过操作并获得反应。这就是它的作用。它对复杂的程序非常有用。

答案 3 :(得分:1)

想象一下,你犯了拼写错误或拼写错误。例如,您编写 Elipse 而不是 Ellipse

如果使用Qwt.QwtSymbol.Elipse进行编码,则会在运行之前捕获错误。

如果您使用'elipse'之类的字符串进行编码,则错误无法在运行时捕获,并且仅在实际调用setSymbol时才会被捕获(因此,如果该调用出现在else分支中,则从不接受你的特定运行,错误将被忽视)。

当然,还有性能原因。

这个typing问题有完整的书籍。你可以,例如学习一点Ocaml并阅读B.Pierce的Types and Programming Languages

另见this question

答案 4 :(得分:0)

我真的很惊讶,这个问题得到了回报。为什么?它是否显示研究工作?没有!也许OP做了研究,但他没有说明显。它有用吗?清楚吗?很明显,他在传递匿名对象方面存在问题。但为什么他在获取知识方面的个人斗争有用呢?

你想知道为什么你必须在输入superfluos代码时花费这么多“努力”,只是为了制作一个简单的点状灰色椭圆。 首先,您必须记住,使用“Qt”您正在使用面向对象的框架。因此术语和概念上,您使用一组类来实例化对象。你称之为类型的是类。

在您的示例中,您不会执行以下操作:

grid.setPen(Qt.Pen)

哪个会传递给setPen TYPE Qt.Pen,但您定义了一个对象。与类相反,对象包含单个值:5(= Qt.gray),0,3(= Qt.DotLine)。这是一个过于简单化,但它只是为了推动这一点。

就像“typeinteger所说的那样,此类型(类)的每个对象都可以包含整数值,它本身不包含单个值。但它定义了type(类)integer的每个实例必须保存整数值。整数变量保存具有单个值的类的实例(对象)。

回到你的例子,你创建了一个类({1}}的对象,方法QtPen知道要处理它:

grid.setPen(Qt.QPen(Qt.Qt.gray,0,Qt.Qt.DotLine))

您的对象恰好属于类(类型)setPen。因此,您不仅要传递 TYPE ,而且还要将明确提及的三个值作为参数传递隐含地加上其他有用的东西。对象(例如CapStyle,MiterLimit,JoinStyle ......)

在python中没有隐式的参数类型检查。所以你可以通过,你提出的建议:

grid.setPen('gray',0,'dotted')

但是该方法需要一些它熟悉的对象并知道如何处理它们。一个字符串-OBJECT它不知道来处理。因此,解释它应该做什么将是你的工作。因此,您必须使用可以处理字符串的构造函数子类Qt.Pen ,或者直接修改Qt.Pen类,然后重新编译 QT。

我承认Qt.Pen类并不是最佳的例子。因此,我们可以创建一个更好的示例来说明基本概念以及您在错误假设下的位置。

但首先我会声称你的“代理”问题源于对理解面向对象范式的重大困惑,但是由于缺乏更深入的洞察力而无法辨别出你的讨论的来源 - 这是鸡/蛋的问题

罗马有很多道路,您可以自行决定。但是由于决定使用“Qt”,你已经确定了一套通用道路。这些是为对象构建的。

让我们假设我们想要画一些房子。因此,我们使用Qt.Pen定义了一个方法draw_house(顺便说一句,这正是您在原始问题中寻找的内容):

magical_drawing_routine

现在我们有两个相同的房子,没有门,窗户或我们父母家的可爱烟囱。 (我们完全无视def draw_house(house): magical_drawing_routine(house) draw_house('parentshome') draw_house('myhome') 如何解释字符串值)

回到绘图板,我们将纠正缺少这些:

magical_drawin_routine

现在我们有两个完全相同的房子,有门,窗户和我们父母家的可爱烟囱。但是等等,门窗的形状完全相同。回到绘图板......

经过一段时间后你会有类似的事情:

def draw_house(door, window, chimney):
    magical_drawing_routine(door, window, chimney)

parentshome = ['oak', 'green', 'yes']
myhome = ['beech', 'red', 'no']
draw_house(parentshome)
draw_house(myhome)

或者我们可以使用合理的默认值定义类:def draw_house(doormaterial, doorcolor, doorshape, doorwithglass, doorglassparts, windowsnumber, widnowsdistributionpattern, windowsencassing, windowmaterial, windowshape, windowpattern, windowdecoration, chimney): ...

class House, class Window, class Door, class Chimney

如果你只为父母使用一次门,你可以放弃pdoor定义并在传递参数的同时实例化对象,通过生成一个匿名对象(没有附加变量): parentshome = House(门(...),...)

所以简单的答案是:你没有传递类型您传递的对象,通常封装复杂性。但对于可怕的简单对象,它可能看起来像你过于复杂的简单东西 - 但这就是它的样子。