Python Forum
Help creating a class instance dynamically
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help creating a class instance dynamically
#1
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 = color
For 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 += 1
It 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.
Reply
#2
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
99 percent of computer problems exists between chair and keyboard.
Reply
#3
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]
Reply
#4
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.
Reply
#5
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".
Reply
#6
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)
99 percent of computer problems exists between chair and keyboard.
Reply
#7
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)
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#8
Here is a complete working code. I assume that SHEET_DATA is the list that you linked
from 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
Output:
dict_keys(['MediumArbiter', 'MissileTitan', 'MediumBoltor', 'MediumHarpoon', 'BeamPrometheus', 'FighterTorpedo', 'TurretTitan', 'TachyonPrometheus', 'LargePrometheus', 'SmallFury', 'SmallSuppressor', 'LargeAssimilator', 'BomberTurret']) 1 SmallSuppressor is fast: True
Reply
#9
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))
Reply
#10
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
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Dynamically setting nested class be_ams 0 1,507 Apr-06-2022, 02:09 PM
Last Post: be_ams
  Access instance of a class Pavel_47 5 2,079 Nov-19-2021, 10:05 AM
Last Post: Gribouillis
  Class-Aggregation and creating a list/dictionary IoannisDem 1 1,917 Oct-03-2021, 05:16 PM
Last Post: Yoriz
  Class Instance angus1964 4 2,438 Jun-22-2021, 08:50 AM
Last Post: angus1964
  Can we access instance variable of parent class in child class using inheritance akdube 3 13,969 Nov-13-2020, 03:43 AM
Last Post: SalsaBeanDip
  Issue referencing new instance from other class nanok66 3 2,212 Jul-31-2020, 02:07 AM
Last Post: nanok66
  Class variable / instance variable ifigazsi 9 4,292 Jul-28-2020, 11:40 AM
Last Post: buran
  Python complains that class instance is not defined colt 3 5,629 Sep-17-2019, 12:32 AM
Last Post: ichabod801
  how to add class instance attributes from list 999masks 2 2,699 Jul-22-2019, 07:59 AM
Last Post: 999masks
  dynamically define class's michavardy 1 2,080 Feb-26-2019, 04:20 PM
Last Post: buran

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020