Jay Gattuso
Jay Gattuso

Reputation: 4130

Making a dynamic variable set

I'm trying to put together a tool that has a notion of 'level'. Each 'level' has a set of variables that are needed to support the activity I want to achieve that are specific to each level.

I have written a hard-coded version that works (to a degree) but it is limited to the number of levels I have hard-coded. It strikes me that there must be a slicker way of writing this func so can generate the level vars on the fly:

def levelVarsGetter(level):
    if level == 1:
        levelDict = {'URLRegEx':baseDict['L1Regex'], 'titleRegEx':baseDict['L1TitleRegex'], 'buildPortion':baseDict['L1buildPortion'], 'levelParser':'level_1'}
    elif level ==2:
        levelDict = {'URLRegEx':baseDict['L2Regex'], 'titleRegEx':baseDict['L2TitleRegex'], 'buildPortion':baseDict['L2buildPortion'], 'levelParser':'level_2'}
    elif level ==3:
        levelDict = {'URLRegEx':baseDict['L3Regex'], 'titleRegEx':baseDict['L3TitleRegex'], 'buildPortion':baseDict['L3buildPortion'], 'levelParser':'level_3'}
    elif level ==4:
        levelDict = {'URLRegEx':baseDict['L4Regex'], 'titleRegEx':baseDict['L4TitleRegex'], 'buildPortion':baseDict['L4buildPortion'], 'levelParser':'level_4'}
    elif level ==5:
        levelDict = {'URLRegEx':baseDict['L5Regex'], 'titleRegEx':baseDict['L5TitleRegex'], 'buildPortion':baseDict['L5buildPortion'], 'levelParser':'level_5'}
    return levelDict 

All the vars in the dict are manually entered in an initialisation func. There labels can be changed if required.

for context, the referring code:

for x in xrange (1, baseDict['numberOfLevels']+1):
    links=[]
    levelDict= levelVarsGetter(x)
    URLRegEx = levelDict['URLRegEx'] 
    titleRegEx = levelDict['titleRegEx']
    buildPortion = levelDict['buildPortion']
    level = levelDict['levelParser'] 
    go = siteParser()

Upvotes: 0

Views: 101

Answers (2)

David Robinson
David Robinson

Reputation: 78610

You could just do:

def levelVarsGetter(l):
    return {'URLRegEx': baseDict['L%dRegex' % l],
            'titleRegEx': baseDict['L%dTitleRegex' % l],
            'buildPortion': baseDict['L%dbuildPortion' % l],
            'levelParser': 'level_%d' % l}

However, I suspect your data structure should be designed differently. Whatever is stored in baseDict could instead be stored in a dictionary that is first keyed by level, then by type, like

{1: {"Regex": ..., "TitleRegex": ..., "buildPortion": ...},
 2: {"Regex": ..., "TitleRegex": ..., "buildPortion": ...}...

If your levels are sequential (doesn't skip numbers), you should keep them as a list:

levels = [{"Regex": ..., "TitleRegex": ..., "buildPortion": ...},
          {"Regex": ..., "TitleRegex": ..., "buildPortion": ...}...

(though note that you'd have to access it as levels[0] to get level 1).

Indeed, it's likely the the best design is to have a class called Level that has attributes regex, title_regex, and so on. This would let the Level class also contain methods for common tasks. For example:

class Level:
    def __init__(self, url_regex, title_regex, build_portion):
        self.url_regex = url_regex
        self.title_regex = title_regex
        self.build_portion = build_portion

    def method1(self):
        """use build_portion to do something"""
        self.build_portion.do_something()

    def method2(self):
        """use title_regex and url_regex to do something else"""
        x = self.title_regex + self.url_regex 
        x.do_something_else()

Upvotes: 7

Silas Ray
Silas Ray

Reputation: 26160

Is there a reason you can't just put this in a list, and use the list indeces as your level numbers? Ex:

levels = [{'URLRegEx' : 'l1url', 'titleRegEx' : 'l1title', 'buildPortion' : 'l1build'},
          {'URLRegEx' : 'l2url', 'titleRegEx' : 'l2title', 'buildPortion' : 'l2build'},
          ...]

Upvotes: 0

Related Questions