В чем преимущество наличия множества разных типов данных? - PullRequest
2 голосов
/ 31 декабря 2011

В чем преимущество использования множества разных типов данных в языке?Я недавно работал с 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 ]

4 голосов
/ 31 декабря 2011

Есть несколько преимуществ:

  1. Типы безопасных языков (таких как C ++) имеют то преимущество, что во время компиляции обнаруживается много ошибок (в отличие от времени выполнения). Это означает, что использование Qt.grey (обратите внимание на e) не сможет скомпилироваться, потому что тип не определен.

  2. Лучшая производительность и меньше памяти. За кулисами Qt.gray - это число, а числовые операции выполняются намного быстрее, чем строки.

В случае pyqt, поскольку библиотека оборачивает библиотеку C ++, она больше похожа на c ++, чем на код Python.

3 голосов
/ 31 декабря 2011

Различные типы позволяют в время компиляции проверять (по крайней мере, в 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)

Таким образом, вы не будете повторять себя, если будете использовать одни и те же типы атрибутов несколько раз.

1 голос
/ 31 декабря 2011

Представьте, что вы допустили опечатку или орфографическую ошибку. Например, вы пишете Elipse вместо Ellipse .

Если вы наберете код Qwt.QwtSymbol.Elipse, ошибка будет обнаружена перед запуском.

Если вы кодируете со строками, такими как 'elipse', ошибка не может быть обнаружена до времени выполнения, и будет обнаружена только при фактическом вызове setSymbol (поэтому, если этот вызов появляется в ветви else, вы никогда не выполняете ее при конкретном запуске ошибка останется незамеченной).

И, конечно же, есть и причины производительности.

Есть целые книги по этому набрав вопрос. Вы могли бы, например, немного изучите Ocaml и прочитайте Типы и языки программирования Б. Пирса.

См. Также этот вопрос .

1 голос
/ 31 декабря 2011

Это потому что они объекты если вы используете этот QPen :: QPen () то, что он делает, это строит черную ручку по умолчанию для сплошной линии с шириной 0. но так как он перегружен, вы можете использовать параметры для этих конструкторов когда вы передаете параметр в классе QPen, то отправленное вами сообщение обрабатывается, и результат возвращается. так что это концепции объектных ориентаций. вам нужно сделать экземпляр и этот экземпляр будет обрабатывать основную часть этого. если вы используете строковый параметр, как во втором примере, он будет использовать строковый тип вместо Qt.QPen (). Функция setPen () запрашивает объект, типизированный QPen (), а не строковую переменную. преимущество в том, что вам не нужно писать все с первого этажа. и некоторые части предопределены как видеоигра. в видеоигре вы не можете выполнять много функций. если вы стреляете в кого-то, он стреляет в вас или убегает, поэтому реакция зависит от того, что вы делаете. действие - это параметр, а реакция - это возвращаемое значение одной из функций в этом классе. за сценой может быть тонна кодов, которые выполняют различные задачи. например, как он реагирует, время, бегает ли он, идет ли он или летит, когда вы стреляете, так что они устанавливаются по умолчанию, если вы не измените их специально. Иногда вам не нужно менять эти значения по умолчанию, или это займет время. В этом случае просто пропустите действие и получите реакцию. вот что это делает. это действительно полезно для сложных программ.

0 голосов
/ 31 декабря 2011

Я очень удивлен, что этот вопрос вызвал недовольство. Зачем? Это показывает исследовательские усилия? Нет! Может быть, ОП провел исследование, но он не сделал это очевидным. Это полезно? Это понятно? Понятно, что у него проблемы с передачей анонимных объектов. Но почему его личная борьба за получение знаний может быть полезной?

Вы задаетесь вопросом, почему вы должны приложить столько «усилий» при наборе кода superfluos, просто чтобы сделать простой пунктирный серый эллипс. Прежде всего вы должны иметь в виду, что с «Qt» вы используете объектно-ориентированную среду. Таким образом, в терминологии и концептуальном плане вы используете набор классов, из которых вы создаете экземпляры объектов. То, что вы называете типами, это классы.

В вашем примере вы не делаете следующее:

grid.setPen (Qt.Pen)

Что бы передать setPen TYPE Qt.Pen, но вы определяете объект . В отличие от классов объекты содержат отдельные значения: 5 (= Qt.gray), 0, 3 (= Qt.DotLine). Это упрощение, но это просто для понимания.

Как и в «type» integer, говорится, что каждый объект этого типа (класса) может содержать целочисленные значения, но сам не содержит отдельных значений. Но он определяет, что каждый экземпляр type (класса) integer ДОЛЖЕН содержать значения целых чисел. Целочисленные переменные содержат экземпляры (объекты) класса с отдельными значениями.

Возвращаясь к вашему примеру, вы создаете объект класса (типа) QtPen, который метод setPen знает для обработки:

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

Ваш объект просто принадлежит к классу (типу) Qt.Pen. Таким образом, вы не просто передаете TYPE , но вы передаете три значения, которые вы явно упомянули в качестве аргументов ПЛЮС ТОННИХ других неявно полезных вещей с объектом ( например, CapStyle, MiterLimit, JoinStyle ...)

В python нет неявной проверки типов аргументов. Чтобы вы могли передать, что вы предложили:

grid.setPen («серый», 0, «пунктирный»)

НО метод ожидает некоторые объекты, с которыми он знаком, и знает, как с ними обращаться. Строка-ОБЪЕКТ, которую не знает для обработки. Так что это будет ВАША работа, чтобы объяснить, что она должна делать. Поэтому вам придется либо подкласс 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 знает, как интерпретировать строковые значения)

Возвращаясь к чертежной доске, мы исправим их отсутствие:

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 и создать экземпляр объекта на лету, передавая аргументы, путем гееренирования анонимного объекта (без прикрепленной переменной): parenthome = House (Дверь (...), ...)

Итак, простой ответ: вы не передаете типы ! Вы передаете объекты , которые обычно инкапсулируют сложности .Но для ужасных простых объектов это может выглядеть как ваши слишком сложные вещи - но это просто так.

...