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.