Search code examples
pythonglobal-variablesrenamemaya

Global variable defining fails


I have created a simple renaming script but I would like to ask for some advice so that I can refine the coding as well as honing my python scripting. Below is a small portion of code for now...

Though this may not be an issue in my point of view, but other than the two functions I have stated below, I have came to realize that almost all my functions, they contains objects = cmds.ls(selection=True) Though I do not mind retyping over and over again but I do believe there is a better way to rectify this problem.

However, when I tried to make them global before the class function, it is able to run until when I tired to execute one of the functions, it prompts an error saying that global name 'objects' is not defined or 'objects are not defined' etc.

Pertaining to that, any suggestions?

class mainWindow(QDialog):
    def __init__(self, parent=None):
        super(mainWindow, self).__init__(parent)
        self.resize(300,225)
        self.initUI()
        self.createConnections()

    def searchReplace(self):
        wordSearch = str(self.searchTxt.text())
        wordReplace = str(self.replaceTxt.text())

        objCnt = cmds.ls(sl=True, sn=True)

        if len(objCnt) == 0:
            self.searchTxt.clear()
            self.replaceTxt.clear()
            cmds.warning('Nothing is selected')
        else:
            for wordString in sorted(objCnt):
                if wordSearch in wordString:
                    newWordString = wordString.replace(wordSearch, wordReplace)
                    cmds.rename(wordString, newWordString)
                    self.searchTxt.clear()
                    self.replaceTxt.clear()
                    print '%s' %wordString + " has changed to : " + "%s" %newWordString

    def addPrefix(self):
        objects = cmds.ls(selection=True)
        pfx = str(self.prefixTxt.text())

        for item in objects:
            if pfx == "":
                cmds.warning('No prefix values in the field')
            else:
                cmds.rename(item, pfx + "_" + item)
                self.prefixTxt.clear()
                print 'Prefix added: %s_' %pfx

    def addSuffix(self):
        objects = cmds.ls(selection=True)
        sfx = str(self.suffixTxt.text())

        for item in objects:
            cmds.rename(item, item + "_" + sfx)
            self.suffixTxt.clear()
            print 'Suffix added: _%s' %sfx

    def numPadding(self):
        objects = pm.ls(selection=True)
        num = self.numTxt.text()
        padding = self.paddingTxt.text()

        if num != "" and padding !="":
            try:
                for currentWordStr in objects:
                pad = ("%%0%ii" % int(padding)) % int(num)
                newWordStr = currentWordStr.rename(currentWordStr.name() + "_" + pad)

            except Exception:
                self.numTxt.clear()
                self.paddingTxt.clear()
                cmds.warning('Input numerical values only')
        else:
            cmds.warning('Entries of Num or Padding are empty')

    def selectHierarchy(self):
        sel = cmds.ls(selection = True)
        selCnt = len(sel)

        if int(selCnt) == 0:
            cmds.warning('Nothing is selected')
        else:
            objHierarchy = cmds.listRelatives(ad=True, type='transform', fullPath=True)          
            cmds.select(sel, objHierarchy)

    def clearHierarchy(self):
        sel = cmds.ls(selection = True)
        selCnt = len(sel)

        if int(selCnt) != 0 :
            objHierarchy = cmds.select(clear=True)
        else:
            cmds.warning('Selection is empty. Nothing to be cleared')

Solution

  • All right, I think I understand what you tried, going to take a shot at an answer.

    First, take a look at the following posts, should get you up to speed on globals:

    Using global variables in a function other than the one that created them (great, succinct summary)

    Variable scope outside of classes (example with classes)

    So, first off, you don't need to use the global keyword when first declaring objects outside of the class definition. So, instead of:

    global objects
    objects = cmds.ls(selection=True)
    class mainWindow(QDialog):
        ...
    

    You would do:

    objects = cmds.ls(selection=True)
    class mainWindow(QDialog):
        ...
    

    Then, your functions can just refer to "objects". If you need to WRITE to objects from within your functions in the class, then you need to first use the global keyword (this code assumes objects was defined before the class):

    def my_method(self):
        global objects
        objects = some_function()
    

    That said, I'm not 100% sure how the above code is being invoked, so it's possible that something else is causing "objects" to be undefined.

    You might be better served with a class attribute here. You could do this:

    class mainWindow(QDialog):
        objects = cmds.ls(selection=True)
    
        def my_func(self):
            for item in self.objects:
                do_stuff()
    

    Keep in mind that objects would be the same for all instances of mainWindow, and any updates to objects in one instance will affect all other instances. That should be fine from what I can tell, but you should definitely become familiar with instance vs. class vs. module.

    Hope that helps!

    UPDATE: Whoops, changed the class attribute in one place, but not the other in the last example. Updated the example, it should make way more sense now.