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

发布于 2024-12-23 17:14:55 字数 574 浏览 4 评论 0原文

在一种语言中使用多种不同的数据类型有什么好处?我最近一直在使用 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++ 中需要它们?

What is the benefit of using many different data types in a language? I have been working with pyqt and pyqwt recently and I keep finding myself typing lines like this:

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)))

What would be lost if the above lines were instead the following?:

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

Even if the specific types are needed for some technical reason, couldn't the strings be converted to those types inside the method that needs them?

Is this because pyqt and pyqwt are simply bindings for C++ libraries? If so why are they needed in C++?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

孤檠 2024-12-30 17:14:55

有一些好处:

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

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

在 pyqt 的情况下,因为该库包装了一个 C++ 库,所以它看起来更像是 C++,而不是 Python 代码。

There are a few benefits:

  1. Type safe languages (like C++) have the advantage that many errors are found at compile time (as opposed to run-time). That means using Qt.grey (note the e) would fail to compile because the type is not defined.

  2. Better performance and less memory. Behind the scenes Qt.gray is a number, and number operations are much faster than strings.

In the pyqt case, because the library wraps a C++ library it looks more like c++ than like Python code.

北凤男飞 2024-12-30 17:14:55

不同的类型可以让您在编译时(至少在 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)

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

Different types let you check at compile time (at least, in C++) that you're passing the right kinds of things - for instance, if everything took strings, it'd be very easy to accidentally typo 'gray' as, say, 'grey', and possibly confuse the library.

A normal pattern is to do something more like this:

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)

That way you don't wind up repeating yourself if you're using the same kinds of attributes multiple times.

琉璃繁缕 2024-12-30 17:14:55

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

It's because they are objects
if you use this QPen::QPen ()
then what it does is Construct a default black solid line pen with 0 width.
but since it's overloaded you can use parameters for those constructors
when you pass a parameter in the QPen class what you send is processed and the result would return. so those are concepts of object orientations. you need to make an instance
and that instance will handle the underlying part of it. if you use a string parameter like what you've used in the second example it will just use string type instead Qt.QPen() type.
setPen() function asks for an object typed QPen() not string typed variable.
the advantage is you don't need to write everything from ground floor. and some parts are predefined like a video game. in video game you can't do a lot of functions. if you shoot at someone he will shoot you or run away so the reaction is depend on the action you make.
the action is the parameter and reaction is the return value from one of functions in that class. behind the scene there might a ton of codes which do various tasks. like how he reacts, the timing, whether he runs or walk or fly when you shoot so those are set at default value unless you change them specially. sometimes you don't need to change those default values or it would take time.in that case just pass the action and get the reaction. that's what this does. it's really useful for complex programs.

§对你不离不弃 2024-12-30 17:14:55

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

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

如果您使用像 'elipse' 这样的字符串进行编码,则在运行时之前无法捕获错误,并且只有在实际调用 setSymbol 时才会捕获错误(因此,如果该调用出现在 >else 分支您在特定运行中从未采用,错误将不会被注意到)。

当然,还有性能方面的原因。

有整本书讨论这个打字问题。例如,您可以学习一些 Ocaml 并阅读 B.Pierce 的类型和编程语言

另请参阅此问题

Imagine that you make a typo, or a spelling mistake. So for example you write Elipse instead of Ellipse.

If you code with Qwt.QwtSymbol.Elipse the error would be caught before running.

If you code with strings like 'elipse' the error cannot be caught before runtime, and would only be caught when actually calling setSymbol (so if that call appear in an else branch you never take in your particular run, the error will stay unnoticed).

And of course, there are also performance reasons.

There are whole books on this typing question. You could e.g. learn a bit of Ocaml and read Types and Programming Languages by B.Pierce.

See also this question.

少年亿悲伤 2024-12-30 17:14:55

我真的很惊讶这个问题得到了赞成。为什么?它显示了研究努力吗?不!也许OP做了研究,但他没有说得很明显。这有用吗?清楚了吗?很明显他在传递匿名对象时遇到了问题。但为什么他个人为获取知识所做的努力会有用呢?

您想知道为什么您必须花这么多“精力”来输入多余的代码,只是为了制作一个简单的灰色虚线椭圆。
首先,您必须记住,使用“Qt”您正在使用面向对象的框架。因此,从术语和概念上来说,您正在使用一组类来实例化对象。您所说的类型就是类。

在您的示例中,您没有执行以下操作:

grid.setPen(Qt.Pen)

它将传递给 setPen TYPE Qt.Pen,但您定义了 TYPE Qt.Pen >对象。与类相反,对象包含单独的值:5(=Qt.gray)、0、3(=Qt.DotLine)。这过于简单化了,但这只是为了让大家明白这一点。

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

回到您的示例,您创建了类(类型)QtPen 的对象,该方法setPen 确实知道处理:

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

你的对象恰好是类(类型) Qt.Pen。因此,您不仅仅是传递类型,而是传递您明确提到的三个值作为参数加上大量其他隐式有用的东西对象(例如 CapStyle、MiterLimit、JoinStyle ...)

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

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

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

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

但首先我会声称你的“替代”问题源于理解面向对象范式的重大困惑,但由于缺乏更深刻的洞察力而无法辨别你的困惑的根源 - 这是先有鸡还是先有蛋的问题。

通往罗马的道路有很多条,你可以决定走哪条路。但是当决定使用“Qt”时,您已经决定了一组通用的道路。这些是为对象构建的。

假设我们要画一些房子。因此,我们使用 magical_drawing_routine 定义了一个方法 draw_house (顺便说一句,这正是您在最初的问题中所寻找的):

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, mdoor = Door(a,b), Door(a,Z) 
pwin, mwin = Window(e,f,g), Window(e,f,Y)
pchimney, mchimney = Chimney(h), Chimney(X)

parentshome = House(pdoor, pwin, pchimney)
myhome = House(mdoor, mwin, mchimney)

如果您只为父级使用一次门,则可以放弃 pdoor 定义并在传递参数时通过生成一个匿名对象(不附加变量)即时实例化该对象:
parentshome = House(Door(...), ...)

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

I'm really surprised, that the question got upvotes. Why? Does it show research effort? No! Maybe the OP did research, but he didn't make it obvious.Is it useful? Is it clear? It's clear he has a problem with passing anonymous objects. But why should his personal struggle in gaining knowledge be useful?

You are wondering why you have to take so much "effort" in typing superfluos code, just to make a simple dotted gray ellipse.
First you must keep in mind, that with "Qt" you are using an object-oriented framework. So terminology and conceptual wise you are using a set of classes from which you instantiate objects. What you would call types are the classes.

In your example you don't do the following:

grid.setPen(Qt.Pen)

Which would pass to setPen the TYPE Qt.Pen, but you define an object. Contrary to classes objects contains individual values: 5(=Qt.gray), 0, 3(=Qt.DotLine). This is an oversimplification, but it's just to drive the point home.

Like the "type" integer says, that every object of this type (class) can contain whole-number values it doesn't contain the individual values itself. But it defines that every instance of the type (class) integer MUST hold whole-number values. The integer-variables hold instances (objects) of the class with individual values.

Back to your example, you create an object of the class (type) QtPen, which the method setPen does know to handle:

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

Your object just happens to be of the class(type) Qt.Pen. So you are not just passing a TYPE but you are passing the three values you explicitly mentioned as arguments PLUS a TON of other useful stuff implicitly with the object (e.g. CapStyle, MiterLimit, JoinStyle ...)

In python there is no implicit type-checking of arguments. So you could pass, what you proposed:

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

BUT the method expects some objects which it's familar with and knows how to handle them. A string-OBJECT it doesn't know to handle. So it would be YOUR job to explain what it should do. So you would either have to subclass Qt.Pen with a constructor which can handle your strings, or modify the Qt.Pen class directly and recompiling QT afterwards.

I concede the Qt.Pen class is not the optimal example. So we could create a better example to illustrate the underlying concepts and where you are under false assumptions.

But first i would claim that your "surrogate" question originates from a major confusion to understand the object-oriented paradigm, but couldn't discern the source of your confussion in the lack of greater insight - it's the chicken/egg problem.

There are many roads to rome, which you take is yours to decide. But with the decision to use "Qt" you already decided on a general set of roads. And those are build for objects.

Let us assume we want to draw some houses. So we define a method draw_house using the magical_drawing_routine (which by the way is exactly what you were looking for at your original question):

def draw_house(house):
        magical_drawing_routine(house)

draw_house('parentshome')
draw_house('myhome')

Now we got exactly two identical drawn houses without doors, windows or the lovely chimney of our parent's home. (And we are completely ignoring how the magical_drawin_routine knows how to interprete the string-values)

Back to the drawing board we would correct the lack of these:

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)

Now we got exactly two identical drawn houses with doors, windows and the lovely chimney of our parent's home.But wait, the windows and doors have the exact same shape. Back to the drawing board...

after some cylces you would have something like:

def draw_house(doormaterial, doorcolor, doorshape, doorwithglass, doorglassparts, windowsnumber, widnowsdistributionpattern, windowsencassing, windowmaterial, windowshape, windowpattern, windowdecoration, chimney):
   ...

or we could define classes: class House, class Window, class Door, class Chimney with reasonable default-values.

pdoor, mdoor = Door(a,b), Door(a,Z) 
pwin, mwin = Window(e,f,g), Window(e,f,Y)
pchimney, mchimney = Chimney(h), Chimney(X)

parentshome = House(pdoor, pwin, pchimney)
myhome = House(mdoor, mwin, mchimney)

if your using the door for your parent only one time, you can forgoe the pdoor definition and instantiate the object on-the-fly while passing the arguments, by gerenating an anonymous object (no variable attached):
parentshome = House(Door(...), ...)

So the simple answer is: you don't pass types! You pass objects, which normaly encapsulte complexities. But for awful simple objects it might look like your overcomplicating simple stuff - but that is just how it looks like.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文