Jodgod
Jodgod

Reputation: 100

What is the 'Python' way of creating class attributes

I am a beginner in Python. I would like to know which is the better way of creating attributes...

In the first method I am explicitly defining the attribute and then having a method return a value to it:

class A:
    def __init__(self, number):
        self.a = self._meth( number)

    def _meth(self, num):
        #some executable code here

        return 8 ** num

In the second variant the method is being called by itself and is creating the attribute by it self.

class A:
    def __init__(self, number):
        self._meth(num)

    def _meth(self, num)
        #some executable code here
        self.a = 8 ** num

So my question is which one is the more accepted way of going about this?

this is the code I want to use this for...

class Initializer():
    def __init__(self):
        self.ParseArguments()
        self.InitializeLogger()

    # Parse command line arguments and display help text    
    def ParseArguments(self):
        help = textwrap.dedent('''\ Help text here''')
        Arguments = argparse.ArgumentParser('This Script Pulls NAV data from the '
                            'AMFI website', 
                            formatter_class=argparse.RawDescriptionHelpFormatter, 
                            description=help)
        Arguments.add_argument('-f', '--file',
                               help= 'location of the config')
        self.ArgumentDict = vars(Arguments.parse_args())
        self.ArgumentParser = Arguments




    def CreateLogFile(self, level, name,):
        path = self.ArgumentDict['loc']
        if path == None:
            if platform.system() == 'Windows':
                location = os.environ.get("TEMP") + '\\' + name
            elif platform.system == 'Linux':
                location = os.getenv("HOME") + '/' + name
            else:
                print "Unsupported OS"
                raise ValueError
        else:
            location = path
        formatter = logging.Formatter("%(asctime)s - %(name)s - "
                                      "%(levelname)s - %(message)s")
        logfile = logging.FileHandler(location)
        logfile.setLevel(logging.DEBUG)
        logfile.setFormatter(formatter)
        self.logger.addHandler(logfile)


    def InitializeLogger(self):
        self.logger = logging.getLogger('main')
        if self.ArgumentDict['debug'] == True:
            self.logger.setLevel(logging.DEBUG)
        else:
            self.logger.setLevel(logging.INFO)
        self.CreateLogFile(logging.INFO, 'NavUpdaterLog.log')) 

Upvotes: 2

Views: 255

Answers (5)

phihag
phihag

Reputation: 288230

Note that you're creating object attributes, not class attributes (Those go directly in the class body). If meth is only called on initialization, I'd prefer:

class A(object):
    def __init__():
         # Some executable code here
         self.a = 8

Otherwise, if your class can't handle meth being called every now and then, you should make it a private method by prefixing it with _ or __.

By the way return None (with a capitalized None) at the end of a method is unnecessary, that's the default final instruction anyway.

Looking at the updated code, I can't find any need to use classes in the first place. You may want to have a helper method initLogger, but that's it. Try to:

  • Use builtin-in functionality instead of reimplementing it yourself, for example tempfile
  • Roughly follow PEP8 in your style (i.e. don't capitalize method and variable names)

Upvotes: 3

user90150
user90150

Reputation:

using init is an understandable way (for other programmer) of creating attribute.

Usually __ init __ is thy way I start my reading of the python class and scan through the methods.

Upvotes: 0

Gaslight Deceive Subvert
Gaslight Deceive Subvert

Reputation: 20428

I think the answer is that it depends. If there is only one attribute, like in your example, then the whole body of meth can go into the __init__ method. If you have say 5-10 attributes to initialize, __init__ would get to long and I would definitely try to refactor the initialization code into functions. If the initialization of each attribute is independent of the other, I would first try to use functions.

def get_attr_a():
    # some code
    return a
def get_attr_b():
    ...
    return b
...
class A:
    def __init__():
        self.a = get_attr_a()
        self.b = get_attr_b()
        ...

If the initialization of attributes are dependent on each other, so that b can not be initialized before a is done, then it is a trickier case. That could warrant some kind of factory pattern where the initialization of the object is detached from the class:

class A:
    def__init__(self, a, b, c):
        self.a, self.b, self.c = a, b, c

def get_attr_a():
    return a
def get_attr_b(a):
    return b
def create_an_a_class():
    a = get_attr_a()
    b = get_attr_b(a)
    c = get_attr_c(a, b)
    ....
    return A(a, b, c)

Upvotes: 0

Thibault J
Thibault J

Reputation: 4456

I think the correct python way would be to do it the easiest way, removing all unnecessary code.

class A():
    def __init__(self):
        self.a = 8

If you need to define custom getter and setters, you can use python properties. This in an extract from python documentation :

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

Upvotes: 0

Jacob
Jacob

Reputation: 43299

In your second definition, you can only use the method to set the instance variable a. In your first, you can use the method again if you need it. Also, I don't like looking all over the place for instance variables, so I would go with number one.

Upvotes: 0

Related Questions