Lewis
Lewis

Reputation: 11

Printing a variable outside of its class

I have a simple Python program that has 2 classes. I am trying to print a variable in class A into class B.

Code:

import sys
import csv


#This class reads in the command line args and assigns them to variables
class main:
    def __init__(self):
        #print program name
        print ("PRIT0 Analyser Tool Running...")
        #print the usage
        print ("[csv file] [errorfile] [prit0 time] ")
        #handle the arguments
        if (len(sys.argv) < 4):
            print("You are missing parameters!")
        else:
            #create variables to hold args
            csv_file   = ""
            err_file   = ""
            prt_0      = 0.0
            #assign command line args to variables
            csv_file = sys.argv[1]
            err_file = sys.argv[2]
            prt_0    = sys.argv[3]
            ob_c.readCsvFile()


#This class will read in the csv file and handle the data analysis
class csv:
    def readCsvFile():
        print(ob_m.csv_file)


#class instances
ob_m = main
ob_c = csv 

if __name__ == '__main__':
    main()

Error:

'Type object 'main' has no attribute to 'csv_file'

Not to sure why I am getting this issue. Any ideas would be appreciated

Upvotes: 0

Views: 110

Answers (2)

This looks a lot like a translation of Java and it has may non-Pythonic aspects to it.

  1. It is in general not a good practice to have cross-linked global variable (like the csv class referencing the global ob_m, and the main class referencing the global ob_c)
  2. It is also not a very good practice to instantiate object only for the side-effects (like triggering the ob_c.readCvsFile() in the __init__ of main)
  3. The __init__ function should either populate an object or raise an exception (in your case, if the number of arguments is too low, it return an unusable instance)
  4. Since the __init__ happens before the object has been assigned to a variable ob_m would still be undefined by the time you call to readCsvFile, so there is no way to make it work this way
  5. It is a bad bad idea to name your classes the same as others you import (name shadowing)

That said, your code could be re-written to work as follows

import sys
import csv

#This class reads in the command line args and assigns them to variables
class main:
    @staticmethod
    def build_main():
        #print program name
        print ("PRIT0 Analyser Tool Running...")
        #print the usage
        print ("[csv file] [errorfile] [prit0 time] ")
        #handle the arguments
        if (len(sys.argv) < 4):
            print("You are missing parameters!")
            return None
        else:
            return main(sys.argv[1], sys.argv[2], sys.argv[3])

    def __init__(self, csv_file, err_file, prt_0):
        self.csv_file = csv_file
        self.err_file = err_file
        self.prt_0 = prt_0

    def run(self):
        ob_c.readCsvFile()


#This class will read in the csv file and handle the data analysis
class my_csv:
    def readCsvFile():
        print(ob_m.csv_file)


#class instances
ob_c = my_csv 

if __name__ == '__main__':
    ob_m = main.build_main()
    if ob_m is not None:
        ob_m.run()

This solution still has the problem with the global variables. From the standard Python practice it would be better to create the instance of my_csv inside main either as a member

    def __init__(self, csv_file, err_file, prt_0):
        self.csv_file = csv_file
        self.err_file = err_file
        self.prt_0 = prt_0
        self.my_csv = my_csv

    def run(self):
        self.my_csv.readCsvFile()

or as a temporary object in run

    def run(self):
        ob_c = my_csv
        ob_c.readCsvFile()

Finally, there is the reference to the global main object, which is also non-explicit. It would be better to pass it as an argument to readCsvFile

class main:

    ...

    def run(self):
        ob_c = my_csv
        ob_c.readCsvFile(self)


#This class will read in the csv file and handle the data analysis
class my_csv:
    def readCsvFile(ob_main):
        print(ob_main.csv_file)

The final code looks like this:

import sys
import csv

#This class reads in the command line args and assigns them to variables
    class main:
        @staticmethod
        def build_main():
            #print program name
            print ("PRIT0 Analyser Tool Running...")
            #print the usage
            print ("[csv file] [errorfile] [prit0 time] ")
            #handle the arguments
            if (len(sys.argv) < 4):
                print("You are missing parameters!")
                return None
            else:
                return main(sys.argv[1], sys.argv[2], sys.argv[3])

        def __init__(self, csv_file, err_file, prt_0):
            self.csv_file = csv_file
            self.err_file = err_file
            self.prt_0 = prt_0

        def run(self):
            ob_c = my_csv
            ob_c.readCsvFile(self)


    #This class will read in the csv file and handle the data analysis
    class my_csv:
        def readCsvFile(ob_main):
            print(ob_main.csv_file)


if __name__ == '__main__':
    ob_m = main.build_main()
    if ob_m is not None:
        ob_m.run()

I hope it helps

Upvotes: 1

rassar
rassar

Reputation: 5680

In order to instantiate a class, you need to have parentheses after it:

ob_m = main()

As well, when you say main() in your last line, it simply instantiates that class. You should make it a function instead.

Upvotes: 0

Related Questions