![]() |
Help creating a class instance dynamically - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: Help creating a class instance dynamically (/thread-12238.html) |
Help creating a class instance dynamically - Kotevski - Aug-15-2018 Hey folks, I've been trying to dump the contents of my google drive sheet into class instances. My understanding of classes and object oriented programming in python feels a little bit incomplete so if I misuse any terminology feel free to correct me at any point here. The output of the drive sheet spits the contents into a dictionary contained inside of a list. This is the output here This is my class here: class Turret: def __init__(self, copyable, turret_name, burst, fire_rate, hull_dmg, shield_dmg, sound_name, random, man_accuracy, life_time, laser_thickness, speed, burst_time_in_between, price, color): self.copyable = copyable self.turret_name = turret_name self.burst = burst self.fire_rate = fire_rate self.hull_damage = hull_dmg self.shield_damage = shield_dmg self.sound_name = sound_name self.random = random self.man_accuracy = man_accuracy self.life_time = life_time self.laser_thickness = laser_thickness self.speed = speed self.burst_time_in_between = burst_time_in_between self.price = price self.color = colorFor the class object/instance name I am trying to use the TurretName value from the sheet output, but I have been unable to do this successfully. To convert the raw output of the drive sheet into a readable format, I have been using this ugly and inefficient function here. # Take turret sheet output and log it's contents as objects under the Turret class. def clean_turret_sheet_data(currentTurrets): i = 0 b = 0 selected_item_list = [] for dict in currentTurrets: selected_turret = currentTurrets[i] for key, value in selected_turret.items(): temp = [key, value] selected_item_list.append(temp) copyable = selected_item_list[b][1] b += 1 turret_name = selected_item_list[b][1] b += 1 burst = selected_item_list[b][1] b += 1 fire_rate = selected_item_list[b][1] b += 1 hull_dmg = selected_item_list[b][1] b += 1 shield_dmg = selected_item_list[b][1] b += 1 sound_name = selected_item_list[b][1] b += 1 random = selected_item_list[b][1] b += 1 man_accuracy = selected_item_list[b][1] b += 1 life_time = selected_item_list[b][1] b += 1 laser_thickness = selected_item_list[b][1] b += 1 speed = selected_item_list[b][1] b += 1 burst_time_in_between = selected_item_list[b][1] b += 2 price = selected_item_list[b][1] b += 2 color= selected_item_list[b][1] b += 1 turretList[i] = Turret(copyable, turret_name, burst, fire_rate, hull_dmg, shield_dmg, sound_name, random, man_accuracy, life_time, laser_thickness, speed, burst_time_in_between, price, color) print(turretList[i].turret_name, "logged!") i += 1It seems like the class instance has to be defined before the script can be run? My question is: is there any way to initiate the class using external variables from outside the code after the script has been run. TLDR: I am trying to create a class by calling an specific list item that doesn't exist until the script is run but I don't know how to do it and I cant find how online. RE: Help creating a class instance dynamically - Windspar - Aug-15-2018 Your code scare me. Example. You can try something like this. class Turret: pass def clean_turret_sheet_data(currentTurrets): turret_list = [] for turret in currentTurrets: new_turret = Turret() for key, value in turret.items(): setattr(new_turret, key, value) turret_list.append(new_turret) return turret_list RE: Help creating a class instance dynamically - Gribouillis - Aug-16-2018 You can do even shorter: class Turret: def __init__(self, attrdict): self.__dict__.update(attrdict) def clean_turret_sheet_data(currentTurrets): return [Turret(turret) for turret in currentTurrets] RE: Help creating a class instance dynamically - Gribouillis - Aug-16-2018 I suggest using a namedtuple object for better control from collections import namedtuple _Turret = namedtuple('Turret', """ copyable, turret_name, burst, fire_rate, hull_dmg, shield_dmg, sound_name, random, man_accuracy, life_time, laser_thickness, speed, burst_time_in_between, price, color""") class Turret(_Turret): __slots__ = () def clean_turret_sheet_data(currentTurrets): return [Turret(**t) for t in currentTurrets] # or [Turret(*t.values()) for t in currentTurrets] if attribute names are changed from the initial data. RE: Help creating a class instance dynamically - Kotevski - Aug-16-2018 Hey guys thanks for the replies, these suggestions really are helping me improve my skills. Unfortunately I don't think these changes would solve my issue (probably my own fault for explaining poorly). The problem is that since the instances are created when the code is run, I am unable to call them and their attributes in the code since the interpreter doesnt think they exist (I think). So for example, even after defining all of that, if I try to do something like print(SmallSuppressor.burst)I get the error "NameError: name 'SmallSuppressor' is not defined". RE: Help creating a class instance dynamically - Windspar - Aug-16-2018 class Turret: pass def clean_turret_sheet_data(currentTurrets): for turret in currentTurrets: new_turret = Turret() for key, value in turret.items(): setattr(new_turret, key, value) setattr(Turret, turret['TurretName'], new_turret) clean_turret_sheet_data(arg) print(Turret.SmallSuppressor.burst) RE: Help creating a class instance dynamically - ichabod801 - Aug-16-2018 You could use the code Gribouillis provided and return a dictionary instead: def clean_turret_sheet_data(currentTurrets): turrets = [Turret(**t) for t in currentTurrets] return {turret.turret_name: turret for turret in turrets} turret_data = clean_turret_sheet_data(currentTurrets) print(turret_data['SmallSuppressor'].burst) RE: Help creating a class instance dynamically - Gribouillis - Aug-16-2018 Here is a complete working code. I assume that SHEET_DATA is the list that you linkedfrom collections import namedtuple import re def to_underscore(word): return '_'.join(x.lower() for x in re.findall(r'[A-Z]+[a-z]*', word)) def clean_turret_sheet_data(currentTurrets): _Turret = namedtuple('Turret', [to_underscore(k) for k in currentTurrets[0].keys()]) class Turret(_Turret): __slots__ = () def is_fast(self): return self.speed > 500 instances = [ Turret(**dict((to_underscore(k), v) for k, v in t.items())) for t in currentTurrets] return dict((t.turret_name, t) for t in instances) turret_by_name = clean_turret_sheet_data(SHEET_DATA) print(turret_by_name.keys()) print(turret_by_name['SmallSuppressor'].burst) print('SmallSuppressor is fast:', turret_by_name['SmallSuppressor'].is_fast())The output is
RE: Help creating a class instance dynamically - Kotevski - Aug-17-2018 I keep getting an error "line 48 def get_turret_sheet_data(): ^ SyntaxError: invalid syntax" and im not sure why, I dont understand this code at all really lol Line 48 would be def to_underscore(word): return '_'.join(x.lower() for x in re.findall(r'[A-Z]+[a-z]*', word)) RE: Help creating a class instance dynamically - Gribouillis - Aug-17-2018 If you copy and paste the whole code as I wrote it, there is no syntax error (double click the code to select it). You only need to add at the beginning SHEET_DATA = [{...}, {...}, ...] # the list you provided in hastebin |