簡體   English   中英

使用for循環生成Python代碼塊

[英]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。

請注意,不需要為對象或函數名稱自定義本地名稱,只有屬性名稱在這里很重要。 對於更通用的代碼,請使用更通用的函數和對象名稱。

這個高階函數為您創建函數。 但是你需要確保像painelhorizBikeDrawing這樣的變量要么在定義的范圍內,要么手動傳遞它們。

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 但是當其他選項不可行時,應該保留這一點,並且可以輕松地重構代碼以使其更通用。 查看getattrsetattr ,即代替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 (或者你甚至可以將它們存儲為這個新類的實例變量,如果沒有其他代碼接觸這些值!),每個類都會得到自己的HScaleLabel進行操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM