[英]Generate blocks of Python code with for loop
我用PyGtk制作了一個小的GUI程序,用於參數化繪制自行車的框架(這個想法:你移動一些滑塊,然后用更新的參數重新繪制框架)。
在代碼的某處,我必須為每個參數創建一個滑塊,我得到這個非pythonic和重復的代碼(抱歉,我寫這條消息時無法正確縮進):
def adjustbottomBracketHeight(par):
BikeDrawing.p.bottomBracketHeight = par.get_value()
painelhoriz.queue_draw()
bottomBracketHeightAdjust = gtk.Adjustment(value=BikeDrawing.p.bottomBracketHeight, lower=180., upper=400., step_incr=10.)
bbhScale = gtk.HScale(adjustment=bottomBracketHeightAdjust)
bbhScale.set_value_pos(gtk.POS_LEFT)
bbhScale.connect("value-changed", adjustbottomBracketHeight)
bbhLabel = gtk.Label("Bottom bracket height")
topcolumn1.pack_start(bbhLabel, False, False)
topcolumn1.pack_start(bbhScale, True, True)
def adjustseatTubeAngle(par):
BikeDrawing.p.seatTubeAngle = par.get_value()
painelhoriz.queue_draw()
seatTubeAngleAdjust = gtk.Adjustment(value=BikeDrawing.p.seatTubeAngle, lower=60., upper=85., step_incr=0.5)
staScale = gtk.HScale(adjustment=seatTubeAngleAdjust)
staScale.set_value_pos(gtk.POS_LEFT)
staScale.connect("value-changed", adjustseatTubeAngle)
staLabel = gtk.Label("Seat tube angle")
topcolumn1.pack_start(staLabel, False, False)
topcolumn1.pack_start(staScale, True, True)
def adjustSeatTubeLength(par):
BikeDrawing.p.seatTubeLength = par.get_value()
painelhoriz.queue_draw()
seatTubeLengthAdjust = gtk.Adjustment(value=BikeDrawing.p.seatTubeLength, lower=300., upper=700., step_incr=10.)
stlScale = gtk.HScale(adjustment=seatTubeLengthAdjust)
stlScale.set_value_pos(gtk.POS_LEFT)
stlScale.connect("value-changed", adjustSeatTubeLength)
topcolumn1.pack_start(stlScale, True, True)
def adjusttopTubeLength(par):
BikeDrawing.p.topTubeLength = par.get_value()
painelhoriz.queue_draw()
topTubeLengthAdjust = gtk.Adjustment(value=BikeDrawing.p.topTubeLength,
lower=400., upper=700., step_incr=10.)
ttlScale = gtk.HScale(adjustment=topTubeLengthAdjust)
ttlScale.set_value_pos(gtk.POS_LEFT)
ttlScale.connect("value-changed", adjusttopTubeLength)
topcolumn1.pack_start(ttlScale, True, True)
好了一些小修改,我想(知道如何; o)“創建”這種代碼迭代參數名稱列表,類似於:
par_list = ['bottomBracketHeight', 'seatTubeAngle', 'seatTubeHeight']
def widgetize(PARAMETER):
""" Create blocks of code where the name PARAMETER would be used to personalize names of handlers, functions, objects, etc. """
for par in par_list:
widgetize(par)
我讀了一些以前的問題/答案,似乎沒有這個具體問題的答案。
我非常感謝你的關注
我認為這或多或少是你所追求的:
def makeAdjuster(name, attr, lower, upper, step):
def doAdjust(par):
setattr(Bikedrawing.p, attr, par.get_value())
panelhoriz.queue_draw()
val = getattr(Bikedrawing.p, attr)
adjust = gtk.Adjustment(value=val, lower=lower, upper=upper, step_incr=step)
label = gtk.Label(name)
topcolumn1.pack_start(label, False, False)
scale = gtk.HScale(adjustment=adjust)
scale.set_value_pos(gtk.POS_LEFT)
scale.connect("value-changed", doAdjust)
topcolumn1.pack_start(scale, True, True)
for adj in (
('Bottom bracket height', 'bottomBracketHeight', 180., 400., 10.),
('Seat tube angle', 'seatTubeAngle', 60., 80., 0.5),
('Seat tube length', 'seatTubeLength', 300., 700., 10.),
('Top tube length', 'topTubeLength', 400., 700., 10.)
):
makeAdjuster(*adj)
如果我理解你:
def widgetize(parameter):
def handler(par):
setattr(BikeDrawing.p, parameter, par.get_value()
painelhoriz.queue_draw()
adjust = gtk.Adjustment(value=getattr(BikeDrawing.p, parameter), lower=300., upper=700., step_incr=10.)
stlScale = gtk.HScale(adjustment=adjust)
stlScale.set_value_pos(gtk.POS_LEFT)
stlScale.connect("value-changed", handler)
topcolumn1.pack_start(stlScale, True, True)
您可能還希望將其他參數(例如BikeDrawing.p)傳遞給widgetize。
請注意,不需要為對象或函數名稱自定義本地名稱,只有屬性名稱在這里很重要。 對於更通用的代碼,請使用更通用的函數和對象名稱。
這個高階函數為您創建函數。 但是你需要確保像painelhoriz
和BikeDrawing
這樣的變量要么在定義的范圍內,要么手動傳遞它們。
def widgetize(name, needsLabel = False, labelText = None):
def adjust(par):
val = par.get_value()
setattr(BikeDrawing.p, name, val)
painelhoriz.queue_draw()
adjustment = gtk.Adjustment(value=val, lower=180., upper=400., step_incr=10.0)
scale = gtk.HScale(adjustment=adjustment)
scale.set_value_pos(gtk.POS_LEFT)
scale.connect("value-changed", adjust)
if needsLabel:
label = gtk.Label(labelText)
topcolumn1.pack_start(Label, False, False)
topcolumn1.pack_start(scale, True, True)
# add nice name for debugging
adjust.__name__ = "adjust{}".format(name[0].upper() + name[1:])
return adjust
一句話:你似乎混淆了一代小部件與屬性調整和每幀繪圖。 因此,代碼將在每次更改時重新生成所有小部件...
從字面上回答你的問題 - exec
。 但是當其他選項不可行時,應該保留這一點,並且可以輕松地重構代碼以使其更通用。 查看getattr
和setattr
,即代替BikeDrawing.p.something = foo
do setattr(BikeDrawing.p, 'something', foo)
- 然后可以使用變量作為屬性名稱,類似於訪問屬性和getattr
。 這都是關於尋找模式(你有很多 - 創建Adjustment
/ HScale
實例,設置BikeDrawing.p
)和移動代碼。
您可能想要使用內省,例如:
for par in par_list:
value=getattr(BikeDrawing.p, par)
# ...
我建議把它包裝成一個知道如何管理/繪制自己的類。 你仍然需要傳遞屬性名稱來修改(例如"bottomBracketHeight"
)並在BikeDrawing.p
上使用getattr
/ setattr
(或者你甚至可以將它們存儲為這個新類的實例變量,如果沒有其他代碼接觸這些值!),每個類都會得到自己的HScale
和Label
進行操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.