Search code examples
pythonsurveyshadowing

How do I check if a variable is type list if I already have list defined as a variable (in Decipher/Forsta survey building platform)?


The platform I am working on, unfortunately, forced me to have "list" defined as a variable name. Additionally, type is a variable name that is built in. Pretty bad oversight considering the server-side language used in this system is Python! I have need of determining whether a variable is of type list. Normally, I would obviously use

isinstance(q, list)

or

type(q) == list

How can I accomplish this?

EDIT FROM SEPT 2023:

I realized that I gave too little information, so I came back to clarify, in case this comes up for anyone else, and make the question more useful for others. The software this is a problem is in a survey programming platform called Decipher/FocusVision (now Forsta). It's wonderful and powerful overall. It's built on Python 3.x, but a restricted environment which uses Python 2.x is what is made available for a survey programmer to use within a survey they're building. And, unfortunately, both list and type are assigned as global variables, so are overridden within the survey.

Therefore, all of these solutions do not work:

isinstance(var, list)
type(var) == list
type(var) == type([]) (I accepted the second answer because I hadn't provided this information and it correctly answered the question as stated)

For anyone who uses Decipher and runs into this, what I had to do was make use of the hooks system and make a global function available within all surveys, as the hooks system exists outside of the restricted survey environment:

embedded.py:

def type_as_str(var):
    """ This function returns the variable type (class) as a string, or 'unknown' 
    if an exception occurs attempting this (to ensure that a str is always returned).
    This is necessary because of Decipher's restricted environment overriding both 
    'list' and 'type'.  'isinstance' can be used for most data types, but this
    function provides a means of identifying data type that works in all scenarios. """

    try:
        return type(var).__name__
    except:
        return 'unknown'

hooks.py:

def survey_environment(env, survey):
    """ This hook function is executed every time someone takes a survey, and allows you to modify 
    the survey and its environment. """
    
    #
    # Loading globals into an object e, which will contain everything run in embedded.py once done.  
    # Globals will be able to be used in embedded.py This allows us to make some of the global 
    # variables and functions available within embedded.py.
    #
    e = {}
    e['allQuestions'] = env['allQuestions']
    e['decLang'] = env['decLang']
    e['res'] = env['res']
    e['setMarker'] = env['setMarker']
    e['gv'] = env['gv']

    #
    # Executing embedded.py with globals loaded into e.  This allows us to then add the variables 
    # and functions from that file into the survey's environment, creating global functions/etc
    # that are available in every survey without having to hard-code them into the surveys,
    # and with a greater range of functionality, since the hooks system is not run in the restricted
    # environment that surveys are.
    #
    execfile('selfserve/53b/embedded.py', e)
    
    #
    # Storing functions from embedded.py's environment into the survey's
    #
    env['load_zip_code_db_file'] = e['load_zip_code_db_file']
    # In our environment, we have 73 different items loaded from embedded.py, it's incredibly useful 

Then in a survey, you can use the function like so:

if type_as_str(some_list_var) == 'list':
    #do something

Or in any other way you might want to. And not only with list type, but any type at all.

I know many companies use Decipher/Forsta software in the market research industry, so I hope this updated question and self-answer helps someone.


Solution

  • Built-in names are also available via the builtins module, should you shadow the name.

    >>> import builtins
    >>> builtins.list is list
    True
    >>> list = 3
    >>> builtins.list is list
    False
    >>> builtins.list("abc")
    ['a', 'b', 'c']
    >>> del list
    >>> builtins.list is list
    True
    

    The module is also available without explicitly importing it using the built-in name __builtins__.