Search code examples
python-3.xclassexeccustomization

exec with customization string in python3


I want to generate the object that the user can input the variable name, but I have no idea why Nameerror happens when I do with the following code:

class Layer: 
    def __init__(self,Diameter,Thickness,Porosity,Name):
        self.d = Diameter
        self.t = Thickness
        self.phi = Porosity
        self.name = Name
    
Name = input('Name of the layer:    ')
d1 = 1
d2 = 2
d3 = 3
exec('%s = Layer(%d,%d,%d,%s)'%(Name,d1,d2,d3,Name))

If I have the input like

Name of the layer:    Trial

Then it comes to the error like:

NameError: name 'Trial' is not defined

I have tried some other ways like:

class Layer:

    def __init__(self,Diameter,Thickness,Porosity,Name):
        self.d = Diameter
        self.t = Thickness
        self.phi = Porosity
        self.name = Name
        
Name = input('Name of the layer:    ')
name = Name
d1 = 1
d2 = 2
d3 = 3
exec('%s = Layer(%d,%d,%d,%s)'%(Name,d1,d2,d3,name))

Even something like this fail:

class Layer
    def __init__(self,Diameter,Thickness,Porosity,Name):
        self.d = Diameter
        self.t = Thickness
        self.phi = Porosity
        self.name = Name
    
Name = input('Name of the layer:    ')
name = 'Trial2'
d1 = 1
d2 = 2
d3 = 3
exec('%s = Layer(%d,%d,%d,%s)'%(Name,d1,d2,d3,name))

And returned NameError: name 'Trial2' is not defined

However, if I removed `name', like the following:

class Layer:

def __init__(self,Diameter,Thickness,Porosity):
    self.d = Diameter
    self.t = Thickness
    self.phi = Porosity
    self.name = Name
    
Name = input('Name of the layer:    ')
d1 = 1
d2 = 2
d3 = 3
exec('%s = Layer(%d,%d,%d)'%(Name,d1,d2,d3))

The object can be generated. But it then lost the properties name.


Solution

  • Replacing exec with print gives a hint of what's wrong:

    print('%s = Layer(%d,%d,%d,%s)'%(Name,d1,d2,d3,Name))
    

    gives

    Trial = Layer(1,2,3,Trial)
                        ^^^^^ here is the problem
    

    but what you actually need is

    Trial = Layer(1,2,3,"Trial")
    

    because the last argument should be a string. Otherwise, Python will look for a variable named Trial, cannot find one and thus raises a NameError. Translated back to your code, this means adding quotes around the second occurrence of Name:

    exec('%s = Layer(%d,%d,%d,"%s")'%(Name,d1,d2,d3,Name))
    

    The reason for this is that although Name is a string, you use it to create a code snippet with it. This snippet has to be valid Python syntax which requires the addition of quotes. The original type of Name disappears once you pass it into the string formatting.