-3

I'm a newby and just learned about classes in python3. Now i wrote an exchanchable code to practice a little bit, and wonder, if there's a way to make this code "smarter".

dic = {
    "1": ["I", "am", "the", "1.", "entry"],
    "2": ["I", "am", "the", "2.", "entry"],
    "3": ["I", "am", "the", "3.", "entry"],
    "4": ["I", "am", "the", "4.", "entry"],
    "5": ["I", "am", "the", "5.", "entry"],
}

class words:
    def __init__(self, word1, word2, word3, word4, word5):
        self.word1 = word1
        self.word2 = word2
        self.word3 = word3
        self.word4 = word4
        self.word5 = word5

for i in dic:
    globals()[f"entry{i}"] = words(dic[i][0],dic[i][1],dic[i][2],dic[i][3],dic[i][4])

print(entry3.__dict__)

The dic above is meant to define the start-values for each instance of the class. Later on there can be ways to modify the attributes for these instances, but that's not important right now.

Like this is written, it's pretty unflexible. If I wanna add another element into an dic-element like this

"1": ["I", "am", "the", "1.", "entry", "!"],

I would have to add a parameter in init like

__init__(self,word1,...,word5,word6)

and also add into init-function

self.word6 = word6

and also add parameter-entry in the definition of the instances like

globals()[f"entry{i}"] = words(Vz[i][0],...,Vz[i][4],Vz[i][5])

Is there any way to automate this process (like looping through them), so if I wanna add another start value for the instances of the class, I don't have to add all these things too?

1 Answers1

0

As soon as you use globals()[...] to create instances in your global namespace you are doing something seriously wrong.and You can store word instances under names using a new dict that you create. You also dont need the word class at all - simply add the strings into a list.

Think about how you want to USE the things you just created inside globals.

You either get the dic from some unknown input then you have no clue how your just generated instances are called and need to lookup keys and recreate the names every time - or you know the keys beforehand - then you can create them as instances under a name in a dictionary.

If you do not need the names, skip that and simply create a list of instancen:

dic = {
    "1": ["I", "am", "the", "1.", "entry"],
    "2": ["I", "am", "the", "2.", "entry"],
    "3": ["I", "am", "the", "3.", "entry"],
    "4": ["I", "am", "the", "4.", "entry"],
    "5": ["I", "am", "the", "5.", "entry"],
}

class words:
    def __init__(self, word1, word2, word3, word4, word5):
        self.word1 = word1
        self.word2 = word2
        self.word3 = word3
        self.word4 = word4
        self.word5 = word5
    def __repr__(self): return str(self)
    def __str__(self): return f"Words({self.word4})"


myD = { f"entry_{k}": words(*dic[k]) for k in dic}

entries = [words(*dic[k]) for k in dic]

print(entries)
print(myD)

Now you KNOW where the instances are, you know how to get to them without looking up keys first and can code with it either by iterating the list or using the known dictionary without smudging your globals:

# as list
[Words(1.), Words(2.), Words(3.), Words(4.), Words(5.)]

# as dict
{'entry_1': Words(1.), 'entry_2': Words(2.), 'entry_3': Words(3.),
 'entry_4': Words(4.), 'entry_5': Words(5.)}

You can make your word class accept any amount of params like so:

class words:
    def __init__(self, *args):
        self.wordlist = [w for w in args]
    def __getitem__(self, idx):
        if isinstance(idx,int):
            return self.wordlist[idx]

        # maybe handle bad (non int, non 2 tuple ints) 
        return self.wordlist[idx]
    def __str__(self): return f"Words({self.wordlist})"

w = words(*"A B C D E F G H I J K L M N O P Q".split()) # add as single args

print(w)
print (w[4])
print (w[2:5])

to enable:

Words(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q'])
E
['C', 'D', 'E']

Read more:

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69