0

I want to get the names of the variables, that were used to create (a large number of) instances of a certain class. Therefore, I'm using dir() to get a list of names in the local scope. After that, I check if one of these names is the name of a variable, that points to an instance of the class Employee.

I'm aware of the fact, that this might be quite slow, if there is a large number of names in the local scope. But speed is not an issue for me at this point.

So my question is: Would that be considered 'bad practice'? - I'm just curious, because I have the strange feeling, that it is somehow not ok / wrong to do it this way...

class Employee:
    def __init__(self, name, age):
        self.name = name
        self.age = age

H1001 = Employee('Tom', 32)
H1002 = Employee('Paula', 28)

for name in dir():
    if eval('isinstance({}, Employee)'.format(name)):
        print("Instance of the class 'Employee' - variable '{}':".format(name))
        print(" The name is {}!".format(eval('{}.name'.format(name))))
        print(" {} years old!".format(eval('{}.age'.format(name))))

Output:

Instance of the class 'Employee' - variable 'H1001':
    The name is Tom!
    32 years old!
Instance of the class 'Employee' - variable 'H1002':
    The name is Paula!
    28 years old!

Edit: I don't think, that this is a duplicate of this question: How do I create a variable number of variables? - I'm not looking for a way to create variable variables in Python.

Think of it like this: Someone else created the class and a huge number of instances. Imagine that this part of the code can't be changed. - Now my task would be, to find out, how many of these instances have been created and how I could get the name of the variables ('H1001', 'H1002' ... 'H2034'), that have been used during this process.

One possible solution I could think of, was to loop through all the names in the local scope and ask for every name in that list: "Are you the name of a variable, that refers to an instance of the class 'Employee'?" - As you can see in the output, I'm getting the result I was looking for. But it felt 'wrong' to do it this way. So I just wanted some kind of feedback, if this could be a valid solution at all.

  • Absolutely that is bad practice. Why not make a dictionary `{'H1001': employee('Tom', 32), ...}` instead? Or include the employee's ID as part of their state, if that's what it is. – jonrsharpe Mar 04 '18 at 17:37
  • I edited the question. Tried to explain, why this might not be a duplicate. – El-Konfetti Mar 06 '18 at 06:04

1 Answers1

0

Yes. Meta-programming is powerful but difficult to debug, fragile, and often hard to read. You shouldn't be encoding critical information in the name of a variable because there are much better data structures available. When in doubt, the simplest approach is probably the best:

class Employee:
    def __init__(self, id, name, age):
        self.id = id
        self.name = name
        self.age = age

employees = [
    Employee('H1001', 'Tom', 32),
    Employee('H1002', 'Paula', 28)
]

for employee in employees:
    print(" The name is {}!".format(employee.name))
    print(" {} years old!".format(employee.age))
Blender
  • 289,723
  • 53
  • 439
  • 496
  • Thank you for your answer. This might be a good solution, if I would be able to change all of the code. - But my question was actually, what I could do, if all those instances have already been created. I edited my question and tried to explain my problem in a more detailed manner. – El-Konfetti Mar 06 '18 at 19:05
  • @El-Konfetti: Why can you not change this part of your code? – Blender Mar 07 '18 at 04:18
  • It's a theoretical question. I just used my example, to explain what I was looking for... Today I found a similiar question: [Enumerate or list all variables in a program](https://stackoverflow.com/questions/430811/enumerate-or-list-all-variables-in-a-program-of-your-favorite-language-here). The accepted answer suggests to use `locals()` instead of `dir()`. The result would be something like `{'H1001': <__main__.employee instance at 0x04822DC8>,'H1002': <__main__.employee instance at 0x04822DA0>}`. I think I'll give it a try... – El-Konfetti Mar 07 '18 at 20:43
  • @El-Konfetti: Your question is sort of like asking, "what's the best type of wrench to hit nails with?". `locals()` and `dir()` can be used for extracting variables from a scope to mimic a dictionary, but you can similarly abuse `eval()` to add two numbers. `locals()` and `dir()` are useful, but there are almost always much better ways to do whatever you're trying to do. – Blender Mar 07 '18 at 20:52
  • I think I get the point. Thanks again! – El-Konfetti Mar 07 '18 at 21:18