8

So I am trying to learn how to properly set Class attributes of a Python class, and wondering about using class functions to do so.

My beginners way has taught me to do:

class MyClass:
    """MyClass class instance"""
    def __init__(self, project, version, command):
        self.project = project
        self.__version = version
        self.__command = command


    """Get version used"""
    def getVersion(self):
        return self.__version

    """Get command executed"""
    def getCommand(self):
        return self.__command

    """Set version used"""
    def setVersion(self, version):
        self.__version = version

This is fine and simple, but this means that I already know the values of my attributes when I instantiate MyClass, since I am passing them to create my object, or if I don't pass them I would use my beginners way of setVersion(version) after creating MyClass object. In my search I read this, which lead me to read about properties, and made me realize that I should not use getter/setters in Python but rather utilize properties. Is this correct?

However, I am wondering if it's Pythonic (or just even correct) to set some of the MyClass instance attributes (project, version, command) using a function. I want to do this because I want this class to do the work of finding these values from specific files by only passing 1 argument. This came to mind, but thought it might be wrong:

class MyClass:
    """MyClass class instance"""
    def __init__(self, project):
        self.project = project
        self._version = self.version()
        self._command = self.command()

    """Get version used"""
    def version(self):
        ...
        use `project` attribute here to get `version` from file...
        ...
        return version

    """Get command executed"""
    def command(self):
        ...
        use `project` attribute here to get `command` from file...
        ...
        return command

Is it even a logical way of setting instance variables by calling a class function?

Should I utilize properties in some ways instead?

Should I make a function outside the MyClass that finds these values returns a MyClass instance instead?

Is there a more proper Pythonic way?

I basically want to create an object with all the extra information (version, command, etc..) by just instantiating it with 1 passed attribute.

Thank you in advance!

7
  • 2
    Direct attribute access is preferred to trivial getters and setters that do nothing more than wrap the access. Commented Apr 18, 2018 at 19:12
  • I should not use getter/setters in Python but rather utilize properties. Is this correct? Yes, there is nearly never a reason to use getter/setter instead of properties. Commented Apr 18, 2018 at 19:19
  • 1
    Complete aside, the string you're using to describe what a function does should be contained within the function rather than above a method definition. See the PEP On doctrings Commented Apr 18, 2018 at 19:20
  • The nice thing about properties is that if you expose an attribute directly, and people write code like c = MyClass(); c.version = 3, then that will continue to work (syntactically, anyway) if you change version to a property. Commented Apr 18, 2018 at 19:21
  • Thank you for the comments! Ok, I will start learning how to use properties properly then. Just starting to learn Python and I always feel when learning a new language that some basics change to more advance constructs, so property was a nice find. Commented Apr 19, 2018 at 15:47

2 Answers 2

7

There are many ways to solve this, but this is how I usually do it:

class MyClass:
    """MyClass class instance"""
    def __init__(self, project, version, command):
        self.project = project
        self.version = version
        self.command = command

    @classmethod
    def from_file(cls, project):
        """ 
        Alternate constructor that takes a project 
        and extracts the other attributes from a file
        """
        #... some code to use `project` 
        #... and get `version` and `command` from file
        return cls(project, version, command)

# usage
m = MyClass.from_file('project01')

classmethod is a decorator that makes a method able to be called directly in the class, instead of the instance. The method then will automatically get the class as first parameter. cls is just a name that means class, like we use self for instances but we could use any name really. The main object constructor in __init__ takes full parameters, but the the new from_file class method works as an alternative constructor, by creating an instance of the class and returning it.

Note that this is not a definite answer, but just a suggestion of a pythonic way to solve it.

Sign up to request clarification or add additional context in comments.

2 Comments

What is @classmethod, does it have a special significance? Notably, is cls a standard convention or does it mean "class". I'm assuming this is returning the version and command values found/set in the function back to the class...then creating the instance of MyClass? Which in-turn makes my m object?
@bretonics your assumptions are mostly correct. I have edited the answer and added some explanantions that might address your doubts.
0
  1. By using keyword variables in __init__, you get flexibility of passing only one variable while instantiation.
  2. using decorators such as, @property and @bar.setter enable you to access and modify the associated attributes. And I believe it is also a quite Pythonic way to do so.

The following would be my approach.

class MyClass:
    def __init__(self, project, version=None, command=None):
        self.project = project
        self.__version = version
        self.__command = command

    @property
    def version(self):
        return self.__version

    @version.setter
    def version(self, val):
        self.__version = val

    @property
    def command(self):
        return self.__command

    @command.setter
    def command(self, val):
        self.__command = val

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.