2011-12-31 51 views
2

在一種語言中使用多種不同數據類型有什麼好處?我一直在與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++中?

+0

這僅僅是不可能的,並表明你沒有考慮過。你提出的方式,每個功能都必須知道一切。重新考慮你的問題,這樣很搞笑。 – 2011-12-31 09:08:20

+0

我很抱歉,如果這個問題來的熱鬧,我自學編程,並不知道太多的理論。你能解釋爲什麼它很愚蠢嗎?我學到的第一門編程語言是Matlab,它可以讓你完成我所說的:plot(x,'r-') – jminardi 2011-12-31 09:16:10

+0

http://en.wikipedia.org/wiki/Data_type已經包含了一些答案,你可以即使沒有正式的計算機科學教育,也很容易找到它。另見我的回覆。 – 2011-12-31 09:19:24

回答

4

有幾個好處:

  1. 類型安全的語言(如C++)的優點在於,許多錯誤是在編譯時發現(而不是運行時)。這意味着使用Qt.grey(注意e)將無法編譯,因爲該類型未定義。

  2. 更好的性能和更少的內存。在幕後Qt.gray是一個數字,數字操作比字符串快得多。

在pyqt的情況下,因爲庫封裝了一個C++庫,它看起來更像是Python,而不像Python代碼。

+0

由於python不是一種編譯語言,這是否意味着唯一的好處是性能更好? – jminardi 2011-12-31 09:25:13

+0

從技術上講,Python中的許多字符串都是幕後數字(http://en.wikipedia.org/wiki/String_interning)。 – Amber 2011-12-31 09:27:22

+1

Python解釋器解析腳本,並解釋與文件不同的東西(通常是某種抽象語法樹......),因此解析腳本時可能會發現一些錯誤。 – 2011-12-31 09:51:31

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) 

這樣,你不拉閘,如果您使用的是同種屬性的多次重複自己。

+0

爲什麼'灰色' - >'灰色'的錯字比Qt.Qt.grey - > Qt.Qt.gray糟糕?兩者似乎都很容易製作。既然python被解釋了,這兩個錯誤同時被捕獲了嗎? – jminardi 2011-12-31 09:27:26

+1

不是,因爲解釋是在腳本文件加載之後立即將腳本文件轉換爲內部表示 - 在運行之前,並且在該更改期間(您可以將其稱爲解析)發生一些錯誤檢測。 – 2011-12-31 09:54:18

+0

@jminardi不,一個會被方法調用捕獲,一個會被抓到。此外,它將依靠方法調用自己來完成所有轉換 - 並且每個方法調用都必須執行相同的轉換。通過在整個代碼中定義一個常量值,方法變得更簡單,可以通過IDE捕獲錯別字等。 – 2012-01-07 15:57:51

1

這是因爲它們是對象 如果您使用此QPen :: QPen() 那麼它所做的就是構造一個寬度爲0的默認黑色實線筆。 但是因爲它已經超載了,所以當你在QPen類中傳遞一個參數時,你可以使用這些構造函數的參數 處理髮送的內容並返回結果。所以這些都是面向對象的概念。您需要創建一個實例 並且該實例將處理它的基礎部分。如果你像第二個例子中使用的那樣使用字符串參數,它將只使用字符串類型,而不是Qt.QPen()類型。 setPen()函數要求輸入QPen()而不是字符串類型變量。 的好處是你不需要寫下底層的所有東西。並且一些部分是像電子遊戲那樣預定義的。在視頻遊戲中,你不能做很多功能。如果你向某人射擊,他會向你射擊或逃跑,所以反應取決於你所做的動作。 該動作是參數,反應是該類中某個函數的返回值。在現場後面可能有很多代碼可以完成各種任務。比如他如何反應,時機,他是否跑步,走路或飛行,這些都是默認值,除非你專門改變它們。有時你不需要改變這些默認值,或者需要時間。在這種情況下,只需通過行動並獲得反應。這就是這樣做的。對於複雜的程序非常有用。

1

想象一下,你犯了一個拼寫錯誤或拼寫錯誤。因此,例如,你寫Elipse而不是Ellipse

如果您使用Qwt.QwtSymbol.Elipse進行編碼,則錯誤會在運行前被捕獲。

如果你喜歡'elipse'字符串錯誤不能在運行之前被抓的代碼,實際調用setSymbol時將只被捕獲(因此,如果這一呼籲出現在else分支你在特定運行從來沒有拿地,錯誤將保持被忽視)。

當然,也有性能的原因。

有關於這個問題typing整本書。你可以例如學習一下Ocaml並閱讀B.Pierce的Types and Programming Languages。請參閱this question

0

我真的很驚訝,問題得到了提升。爲什麼?它顯示研究工作嗎?沒有!也許OP做了研究,但他沒有明顯表現出來,它有用嗎?清楚嗎?很明顯,他在傳遞匿名對象方面存在問題。但是爲什麼他個人在獲取知識方面的鬥爭是有用的呢?

你想知道爲什麼你要這麼多的「功夫」中鍵入superfluos代碼,只是做一個簡單點的灰色橢圓形。 首先您必須記住,使用「Qt」您使用的是面向對象的框架。所以術語和概念上明智的是,您正在使用一組從中實例化對象的類。你會稱之爲類的是類。

在你的榜樣,你不執行下列操作:

grid.setPen(Qt.Pen)

這將傳遞給setPen的TYPEQt.Pen,但你定義一個對象。與類相反,對象包含單個值:5(= Qt.gray),0,3(= Qt.DotLine)。這只是過分簡單化,但它只是爲了把這個觀點帶回家。

就像「typeinteger所說,這種類型(類)的每個對象都可以包含整數值,但它不包含單個值本身。但它定義了type(class)integer的每個實例必須保存整數值。整數變量保存具有單個值的類的實例(對象)。

回到你的榜樣,您所創建的類(類型)的對象QtPensetPen不知道的方法來處理其中:

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

你的對象恰好是類(類型)Qt.Pen的。所以,你不只是傳遞一個TYPE但你傳遞你明確提到作爲參數三個值PLUS的其他有用的東西一噸含蓄與對象(例如CapStyle,miterLimit分別,JoinStyle ...)

在python中沒有參數的隱式類型檢查。所以,你可以傳球,你提出什麼:

grid.setPen(「灰色」,0,「點」)

但方法需要一些物體,它是familar與和知道如何處理它們。一個字符串-OBJECT它不知道要處理。所以這將是YOUR工作來解釋它應該做什麼。所以你要麼必須子類Qt.Pen帶有一個可以處理你的字符串的構造函數,或者直接修改Qt.Pen類,然後重新編譯 QT。

我承認Qt.Pen類不是最佳例子。因此,我們可以創建一個更好的示例來說明基本概念以及您處於錯誤假設下的位置。

但是我首先聲稱你的「代理」問題源自於理解面向對象範式的重大混淆,但在缺乏更深入的洞察力的情況下卻無法辨別出你的理由來源 - 這就是雞/蛋問題。

有很多通往羅馬的道路,你需要的是你的決定。但是隨着決定使用「Qt」,你已經決定了一整套道路。而這些都是針對對象構建的。

讓我們假設我們想繪製一些房屋。因此,我們定義一個方法draw_house使用magical_drawing_routine(其中的方式正是你在你原來的問題尋找):

def draw_house(house): 
     magical_drawing_routine(house) 

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

現在我們得到了整整兩個相同的畫房子沒有門,窗或可愛的煙囪我們父母的家。 (我們完全忽略了magical_drawin_routine如何知道如何interprete字符串值)

回到繪圖板,我們會糾正缺少這些:

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) 

現在我們得到了整整兩個相同的畫房子與門,窗戶和我們父母的家的可愛的煙囪。但等等,窗戶和門具有完全相同的形狀。回到繪圖板...

一些cylces後你會是這樣的:

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) 

如果你使用你的父母只有一次門,就可以forgoe的pdoor定義和實例化對象上即時,同時傳遞參數,通過gerenating一個匿名對象(不變量附後): parentshome =房屋(門(...),......)

所以簡單的答案是:你不通過類型您傳遞對象,這通常是封裝複雜性。但是對於非常簡單的對象,它可能看起來像你簡單的東西 - 但這只是它的樣子。

+0

我不確定這是正確的答案,因爲被調用的函數(例如'setPen')必須知道(或至少必須處理)其參數的所有變體。一些腳本語言(例如* Tcl *我不喜歡)主要接受字符串。 – 2011-12-31 09:23:58

相關問題