Using strings as a check in __init__?

90 views
Skip to first unread message

likage

unread,
Oct 26, 2016, 12:42:28 PM10/26/16
to Python Programming for Autodesk Maya
I would like some opinions on the way I am using instance variables in my class as I am not so sure if I am doing it right.. To be honest, this is my first time using parameters in my class __init__..

class HierarchyDialog(QtGui.QDialog):
   
def __init__(self, state, parent=None):
       
QtGui.QDialog.__init__(self, parent)
       
self.setWindowTitle('Hierarchy Dialog')
       
self.setModal(False)

       
self.state = state

       
if self.state == "root_sels":
           
# Run function_A()
       
elif self.state == "user_sels":
           
# Run function_B()
       
else:
            cmds
.warning("Please check your selections. Either select some nodes or a root node")
       
       
...
       
...


def run_dialog():
    state
= ""
    selection
= cmds.ls(selection=True)
   
if not selection:
        cmds
.warning("Please select a Stack or some nodes")
       
return

   
if len(selection) == 1 and cmds.nodeType(selection) == 'nurbsSurface':
        state
= "root_sels"
   
elif len(selection) >= 1:
       
for items in selection:
           
if not cmds.nodeType(selection) == 'nurbsSurface' in items:
                state
= "user_sels"
       
    dialog
= HierarchyDialog(state)
    dialog
.show()
   
return dialog

In my  `run_dialog`, I am checking for selections in the scene.
There are only 2 types of selections - Selecting a nurbs surface node - suppose that is the top node of the hierarchy, or any of its children (suppose they are all meshs) within that nurbs suface node

Is checking against a string as defined in my `__init__` function the right way to do so?

Marcus Ottosson

unread,
Oct 26, 2016, 1:06:52 PM10/26/16
to python_in...@googlegroups.com

Looks perfectly reasonable to me!

Things I like:

  1. Your logic is kept separate from your GUI code; it makes me warm inside knowing that I could use the very same GUI, regardless of its complexity, for any number of my own logical needs, without having to think about the internal complexity.
  2. You call show from outside; you might consider it obvious, in which case that’s good, but I have both seen and been guilty of it myself of calling show from within __init__ which limits the use of the GUI and complicates reasoning when it comes time to hide it and potentially show or otherwise manage it’s liveliness later on.

Things I don’t like:

  1. Nothing! Except perhaps apart from a lack of super, e.g. super(HierarchyDialog, self).__init__(parent) but it’s a detail.

Overall I’d say you’ve got it right so far!

Justin Israel

unread,
Oct 26, 2016, 3:16:41 PM10/26/16
to python_in...@googlegroups.com
The only suggestion I would make here is that you move your literal strings representing your available states into constants. This has a couple of benefits: 
It prevents typos when you constantly retype those literal strings in different places. Your code editor has the opportunity to warn you when you mistype a non-existing variable name, but not if you mistype a string literal.
It lets you enumerate the available options as code symbols, to pick an option  (via code completion, or introspection)
It makes it easier to documents them. 

They can still be strings if you want the constants to be printable in a meaningful way, or they can be ints:

class HierarchyDialog(QtGui.QDialog):

    # Documenting states
    STATE_ROOT_SELS = "root_sels"
    STATE_USER_SELS = "user_sels"

    def __init__(self, state, parent=None):
        QtGui.QDialog.__init__(self, parent)
        ...

        self.state = state

        if self.state == self.STATE_ROOT_SELS:
            # Run function_A()
        elif self.state == self.STATE_USER_SELS:
            # Run function_B()

        ...

def run_dialog():
    state = ""

    ...
    
if len(selection) == 1 and cmds.nodeType(selection) == 'nurbsSurface'
:
        state = HierarchyDialog.STATE_ROOT_SELS
    
elif len(selection) >= 1:
        for items in selection:
            if not cmds.nodeType(selection) == 'nurbsSurface' in
 items:
                state = HierarchyDialog.STATE_USER_SELS

    dialog = HierarchyDialog(state)
    ...

You can choose the naming you want for the constants. 
I was a little confused though on the expected behaviour of state not being either of the available options. Is that really a warning, or is it an error for your dialog? Can your dialog operate without the state set correctly? Anyways, you can expand on your state constants as needed.

Justin

 

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/afdd4e64-f331-467a-b46d-c5f46b0a9a66%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Message has been deleted
Message has been deleted

likage

unread,
Oct 26, 2016, 8:29:01 PM10/26/16
to Python Programming for Autodesk Maya
I re-post my message...

@Marcus
Thanks for the information! Glad to know that I am on track, to be honest, I was not able to find much info online, perhaps my searching skill was not that great in this aspect :p

@Justin
Thanks for the code. I have decided to use your format for my code.

Even so, I have a few questions.
1. I tried writing a doc string, again I would like to have some insights if possible? Instead of writing it after the `init` function, I wrote it after the class statement, accordingly to what I have read online

2. Is there any chance that I will need to add in an `else` statement should the self.state not conform to either `self.STATE_ROOT_SELS` or `self.STATE_USER_SELS`? Otherwise, I suppose I can stopped such from happening in the run_dialog function, right?

class HierarchyDialog(QtGui.QDialog):
   
"""
    Keywords:
        state:
            Denotes the selection case - 'root node selection' or 'user based selection'
        STATE_ROOT_SELS :
            States the case if the selection is Root Node
        STATE_USER_SELS :
            States the case if the selection is User-based
    """



   
   
# Documenting states
    STATE_ROOT_SELS
= "root_sels"
    STATE_USER_SELS
= "user_sels"




   
def __init__(self, state, parent=None):
       
QtGui.QDialog.__init__(self, parent)
       
...
       
       
self.state = state


       
if self.state == self.STATE_ROOT_SELS:
           
# Run function_A()
       
elif self.state == self.STATE_USER_SELS:
           
# Run function_B()

       
       
# Do I need to include in a bogus state if any of the above 2 conditions are not met
       
else:
            cmds
.warning("Please have a valid selection")

Justin Israel

unread,
Oct 26, 2016, 8:44:47 PM10/26/16
to Python Programming for Autodesk Maya


On Thu, 27 Oct 2016, 1:29 PM likage <dissid...@gmail.com> wrote:
I re-post my message...

@Marcus
Thanks for the information! Glad to know that I am on track, to be honest, I was not able to find much info online, perhaps my searching skill was not that great in this aspect :p

@Justin
Thanks for the code. I have decided to use your format for my code.

Even so, I have a few questions.
1. I tried writing a doc string, again I would like to have some insights if possible? Instead of writing it after the `init` function, I wrote it after the class statement, accordingly to what I have read online

I do the same. I document it at the class as opposed to docstrings on the __init__


2. Is there any chance that I will need to add in an `else` statement should the self.state not conform to either `self.STATE_ROOT_SELS` or `self.STATE_USER_SELS`? Otherwise, I suppose I can stopped such from happening in the run_dialog function, right?

Can you raise a ValueError if they don't pass a valid constant? 


class HierarchyDialog(QtGui.QDialog):
   
"""
    Keywords:
        state:
            Denotes the selection case - 'root node selection' or 'user based selection'
        STATE_ROOT_SELS :
            States the case if the selection is Root Node
        STATE_USER_SELS :

            States the case if the selection is User-based
    """



   
   
# Documenting states

    STATE_ROOT_SELS
= "root_sels"
    STATE_USER_SELS
= "user_sels"




   
def __init__(self, state, parent=None):
       
QtGui.QDialog.__init__(self, parent)
       
...
       
       
self.state = state


       
if self.state == self.STATE_ROOT_SELS:
           
# Run function_A()
       
elif self.state == self.STATE_USER_SELS:
           
# Run function_B()

       
       
# Do I need to include in a bogus state if any of the above 2 conditions are not met
       
else:
            cmds
.warning("Please have a valid selection")

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

likage

unread,
Oct 26, 2016, 9:16:51 PM10/26/16
to Python Programming for Autodesk Maya

2. Is there any chance that I will need to add in an `else` statement should the self.state not conform to either `self.STATE_ROOT_SELS` or `self.STATE_USER_SELS`? Otherwise, I suppose I can stopped such from happening in the run_dialog function, right? 

Can you raise a ValueError if they don't pass a valid constant?  
 
Hey Justin, was wondering if you could give me an example scenario as to when this will occurs?
I asked because I tried selecting objects of other node types etc, I am getting errors (need to rewrite my logic here) but only within the `run_dialog` and it does not seems to pass in this `else` statement..

Justin Israel

unread,
Oct 26, 2016, 9:45:01 PM10/26/16
to python_in...@googlegroups.com
In your run_dialog() function, it looks like there is the potential for "state" to be an empty string, and passed to your dialog constructor. If it is not acceptable for your dialog to operate without a valid state value, then your dialog should raise a ValueError. If it can operate with an invalid state value, then don't raise an exception.

So in your run_dialog(), what does it mean for your dialog to receive an empty string for state? Can the dialog still be useful? 

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

Alok Gandhi

unread,
Oct 26, 2016, 11:08:02 PM10/26/16
to python_in...@googlegroups.com
Most of what I wanted to comment is already covered by Justin and Marcus. Here are my very very minor comments (consider them as extras):

1. self._state instead self.state (~ by convention, self.state should be used only if `state` is public. From your code, and I presume, `state` is not public. I usually start with ALL attributes - (methods, properties) as private (starting with an '_') and then make them public, further down the development as the need arises.

2.    
# Documenting states
STATE_ROOT_SELS = "root_sels"
STATE_USER_SELS = "user_sels"

are just enums and just can be alternatively written as, which are more convenient to use
(
STATE_ROOT_SELS,
STATE_USER_SELS,
) = range(2)


This way you can add huge number of states, (though not required in your case), simply by adding another line, without having to worry about the corresponding strings. The bonus is more protection from potential bugs when you accidentally assign "same string val" to different attrs.

The above code can be made more procedural (although a bit convoluted), and can be used at module level -

from collections import namedtuple

ALLOWED_STATES = [
    'ROOT_SELS',
    'USER_SELS',
    # Feel free to add more states here
    ]

SELECTION_STATES = (namedtuple('SELECTION_STATES', ALLOWED_STATES)
                  (*range(len(ALLOWED_STATES))))

Enums became a part of python standard library as of 3.4, here is the PEP,

In the light of all of the above, the code becomes:

from collections import namedtuple

ALLOWED_STATES = [
    'ROOT_SELS',
    'USER_SELS',
    # Feel free to add more state here
    ]

SELECTION_STATES = (
    namedtuple('SELECTION_STATES', ALLOWED_STATES)(*range(len(ALLOWED_STATES))))


class HierarchyDialog(QtGui.QDialog):
    def __init__(self, state, parent=None):
        super(HierarchyDialog, self).__init(parent=parent)

        self.setWindowTitle('Hierarchy Dialog')
        self.setModal(False)

        self._state = state

        if self._state == SELECTION_STATE.ROOT_SELS:
            # Run function_A()
            pass
        elif self._state == SELECTION_STATES.USER_SELS:
            # Run function_B()
            pass
        else:
            cmds.warning("Please check your selections."
                         " Either select some nodes or a root node")
       

def run_dialog():
    selection = cmds.ls(selection=True)
    if not selection:
        cmds.warning("Please select a Stack or some nodes")
        return

    state = None
    if len(selection) == 1 and cmds.nodeType(selection) == 'nurbsSurface':
        state = SELECTION_STATES.ROOT_SELS
    
elif len(selection) >= 1:
        for items in selection:
            if not cmds.nodeType(selection) == 'nurbsSurface' in items:
                state = SELECTION_STATES.USER_SELS
       
    dialog = HierarchyDialog(state)
    dialog.show()
    return dialog


On Thu, Oct 27, 2016 at 9:44 AM, Justin Israel <justin...@gmail.com> wrote:
On Thu, Oct 27, 2016 at 2:16 PM likage <dissid...@gmail.com> wrote:

2. Is there any chance that I will need to add in an `else` statement should the self.state not conform to either `self.STATE_ROOT_SELS` or `self.STATE_USER_SELS`? Otherwise, I suppose I can stopped such from happening in the run_dialog function, right? 

Can you raise a ValueError if they don't pass a valid constant?  
 
Hey Justin, was wondering if you could give me an example scenario as to when this will occurs?
I asked because I tried selecting objects of other node types etc, I am getting errors (need to rewrite my logic here) but only within the `run_dialog` and it does not seems to pass in this `else` statement..

In your run_dialog() function, it looks like there is the potential for "state" to be an empty string, and passed to your dialog constructor. If it is not acceptable for your dialog to operate without a valid state value, then your dialog should raise a ValueError. If it can operate with an invalid state value, then don't raise an exception.

So in your run_dialog(), what does it mean for your dialog to receive an empty string for state? Can the dialog still be useful? 

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAPGFgA1EGuYDhMYN4LDGb%2BR3uX8D%3D3Aiom_3KUz9uv85jDBK9Q%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.



--

Marcus Ottosson

unread,
Oct 27, 2016, 3:26:37 AM10/27/16
to python_in...@googlegroups.com

On docstrings, here are some considerations to make.

  1. Is there a convention I need to follow? (e.g. within the company, previous or related code you have written etc.)
  2. Do I need/want automatic generation of documentation?

On 2, if you write your docstring in a particular way, then there are parsers out there (primarily Sphinx) capable of interpreting this and produce HTML documentation, similar to Python’s own documentation.

Personally, I’ve found that I rarely generate documentation, but still follow the syntax. That way, I don’t have to come up with my own syntax, and can benefit from the experience from others, linters and other goodies you get from sticking to standards. If one day the requirement came about that I do need documentation, well hey, that’s a neat bonus too.

On docstrings conventions, these are the most common that I know of.

I personally stick with Google’s approach because I found it a good balance between readability in the generated HTML pages, and the code itself. But I see a lot of Sphinx out there as well, and have no trouble understanding that either.

Hope it helps!


To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsubscribe@googlegroups.com.



--

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

Alok Gandhi

unread,
Oct 27, 2016, 7:39:22 AM10/27/16
to Python Programming for Autodesk Maya
Sorry about the slight typo in the last code I posted, should be

super(HierarchyDialog, self).__init__(parent=parent)

likage

unread,
Oct 27, 2016, 1:25:31 PM10/27/16
to Python Programming for Autodesk Maya
@Justin
Truth be told, initially I wrote it as:
if self.state == self.STATE_ROOT_SELS:
    # Run function_A()
if self.state == self.STATE_USER_SELS:
    # Run function_B()
There was no `else` and then before posting my thread, I rewrote it to using `if...elif...` but am unsure whether if I should add in `else` as while reading online, I was given the impression it should be `if...elif...else` and hence else is needed?

Additionally, seeing that I have pretty much put the 'checks' handling in the `run_dialog`, assuming that it fulfills the following...
1. if the root node is selected
2. the child selection are all of nodeType 'mesh' only
3. returns an error/warning if all other node types

@Alok
Any comments are welcome! I am still learning :D
I am not very familiar with using the underscores, in this case, public and private variables, as a matter of fact. If you read my code, pretty much everything is not of private variables..

Was not aware that I can add a number of states but in your code, can I suppose that both ALLOWED_STATES and SELECTION_STATES are considered as global variables then?

@Marcus
To your questions, yes, there are some conventions that I will need to follow but they are somewhat similar to the google docstring but I can hardly find much information for my case in my company's code. Been following the Google docstring conventions for my use, it has been useful :)


Alok Gandhi

unread,
Oct 27, 2016, 9:26:39 PM10/27/16
to python_in...@googlegroups.com
I am not very familiar with using the underscores, in this case, public and private variables, as a matter of fact. If you read my code, pretty much everything is not of private variables.
Sure, I understand. Please note that nothing is really private in python. There is nothing to prevent you from poking around inside and using various internals of a class. The pythonic idea is 'we're all consenting adults here'. Meaning that a leading '_' implies that the author wants the variable to be private. Nothing more, nothing less. If your variables are to be used used outside the class, there is no need for making them private. But do remember, whatever you expose, WILL be used by the cosumers and they will do everything they can, to that variable. Your logic should then be strong enough to be able to handle anything that is executed by the consumers. This may or may not apply in your example case, but keep that in mind, as a guiding principle, whenever you code. This way your code will be future-proofed.

Was not aware that I can add a number of states but in your code, can I suppose that both ALLOWED_STATES and SELECTION_STATES are considered as global variables then?
In my example code, they are globals but you can move them inside the class as well. The only reason to make them global is that other participating classes and interface functions can use them freely. Also note that, in python, classes can also acts as a namespace, Justin's code implements the `state`enums using the class as a namespace. In fact, if you look at it, a class is just like a module. The 'self' (recommened as a strong convention) is just a way to tell the methods that you are referring to this class' namespace in the instance. Otherwise, for all intents and purposes, a class can be used as a namespace or module.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--

Cesar Saez

unread,
Oct 28, 2016, 8:41:20 PM10/28/16
to python_in...@googlegroups.com

There's a fundamental problem with this in my view, the dounder init method of a class gets executed _after_ the instance (aka self) get created, doing checks there means you basically create an object that can potentially be invalid by passing the wrong thing and that's a problem.

You could use a classmethod instead or even a dounder new, but I would go the other way around by using a simple function instead! Classes are a very powerful tool but it's a bit overkill on this case (imho anyway).

Cheers!

Justin Israel

unread,
Oct 28, 2016, 9:30:14 PM10/28/16
to python_in...@googlegroups.com
On Sat, Oct 29, 2016 at 1:41 PM Cesar Saez <ces...@gmail.com> wrote:

There's a fundamental problem with this in my view, the dounder init method of a class gets executed _after_ the instance (aka self) get created, doing checks there means you basically create an object that can potentially be invalid by passing the wrong thing and that's a problem.

You could use a classmethod instead or even a dounder new, but I would go the other way around by using a simple function instead! Classes are a very powerful tool but it's a bit overkill on this case (imho anyway).


What's the "dounder init method"?  Did I miss some code somewhere?

Cheers!

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAPamJi9JY90vPHxJxaNJpU2C3D6zPix1TUv%2BcfXmMTN1gTW-5g%40mail.gmail.com.

Alok Gandhi

unread,
Oct 28, 2016, 9:51:34 PM10/28/16
to python_in...@googlegroups.com
What's the "dounder init method"?  Did I miss some code somewhere?
I think Cesar is referring to the 'double-underscore' aka 'dunder ' aka 'magic methods' aka 'special methods'-  def __init__()

On Sat, Oct 29, 2016 at 9:30 AM, Justin Israel <justin...@gmail.com> wrote:
On Sat, Oct 29, 2016 at 1:41 PM Cesar Saez <ces...@gmail.com> wrote:

There's a fundamental problem with this in my view, the dounder init method of a class gets executed _after_ the instance (aka self) get created, doing checks there means you basically create an object that can potentially be invalid by passing the wrong thing and that's a problem.

You could use a classmethod instead or even a dounder new, but I would go the other way around by using a simple function instead! Classes are a very powerful tool but it's a bit overkill on this case (imho anyway).


What's the "dounder init method"?  Did I miss some code somewhere?

Cheers!

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAPGFgA2OEPUi6hr2M%2BZwug672GKyjiC9hJUHoi75G3yHwSUqhw%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.



--

Justin Israel

unread,
Oct 28, 2016, 9:55:43 PM10/28/16
to python_in...@googlegroups.com
On Sat, Oct 29, 2016 at 2:51 PM Alok Gandhi <alok.ga...@gmail.com> wrote:
What's the "dounder init method"?  Did I miss some code somewhere?
I think Cesar is referring to the 'double-underscore' aka 'dunder ' aka 'magic methods' aka 'special methods'-  def __init__()

Oh right. It's like those illusion pictures, where they don't click until you stare at it the right way. Now I get it :-)
 

On Sat, Oct 29, 2016 at 9:30 AM, Justin Israel <justin...@gmail.com> wrote:
On Sat, Oct 29, 2016 at 1:41 PM Cesar Saez <ces...@gmail.com> wrote:

There's a fundamental problem with this in my view, the dounder init method of a class gets executed _after_ the instance (aka self) get created, doing checks there means you basically create an object that can potentially be invalid by passing the wrong thing and that's a problem.

You could use a classmethod instead or even a dounder new, but I would go the other way around by using a simple function instead! Classes are a very powerful tool but it's a bit overkill on this case (imho anyway).


What's the "dounder init method"?  Did I miss some code somewhere?

Cheers!

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAPaTLMTWREaRPUXwBn%3DnY_0dqe5AaMEy_PJOO5PFstdWRCtFTw%40mail.gmail.com.

Alok Gandhi

unread,
Oct 28, 2016, 10:21:43 PM10/28/16
to python_in...@googlegroups.com
There's a fundamental problem with this in my view, the dounder init method of a class gets executed _after_ the instance (aka self) get created, doing checks there means you basically create an object that can potentially be invalid by passing the wrong thing and that's a problem.
I don't see this as a problem. The __init__() method is for initialization of the instance. If something goes wrong during the initialization, you can always raise from within __init__(). I mean, whatever sanity checks you want to put in for 'filling in' the variables should happen in __init__() because that is the primary role of this method. If anything bad happens and the object becomes 'invalid' python will call __del__() to clean it after itself. So it is perfectly safe to raise from __init__().

Here's a snippet exhibiting the call to __del__() by python's memory management when __init__() fail:
class A(object):
    def __init__(self):
        raise ValueError('Something bad happened!')

    def __del__(self):
        print "Delete Called"


def main():
    try:
        a = A()
    except ValueError, e:
        print e

if __name__ == '__main__':
    main()

Would result in:
>>>Something bad happened!
>>>Delete Called



Cesar Saez

unread,
Oct 29, 2016, 2:20:37 AM10/29/16
to python_in...@googlegroups.com

Sure you can (although it forces the user to enclose any instantiation on a try except, but it works). I guess my point is that validation is usually done in the constructor and not initialisation, creating an instance just to destroy it later on without doing any work (contributing to solve the problem the programmer is trying to solve) is a bit wasteful and I would not recommend it as good practice to someone trying to learn.


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAPaTLMS434aqjf8AMrLVZTvE%3DCJxXXN7-ChHN%3DMd%2B8wG-6v1%2Bg%40mail.gmail.com.

Alok Gandhi

unread,
Oct 29, 2016, 6:03:17 AM10/29/16
to python_in...@googlegroups.com
It forces the user to enclose any instantiation on a try except
Actually, it doesn't, the try except block was just for demonstration purposes. The demo will still work without it.

class A(object):
    def __init__(self):
        raise ValueError('Something bad happened!')

    def __del__(self):
        print "Delete Called"


def main():
    a = A()

if __name__ == '__main__':
    main()
would produce
Traceback (most recent call last):
  File "/Users/alok/Desktop/python.py", line 13, in <module>
    main()
  File "/Users/alok/Desktop/python.py", line 10, in main
    A()
  File "/Users/alok/Desktop/python.py", line 3, in __init__
    raise ValueError('Something bad happened!')
ValueError: Something bad happened!
Delete Called
Point being __del__() is called always and it is a fail-safe mechanism.


I guess my point is that validation is usually done in the constructor and not initialisation
I most humbly would like to disagree. Actually, most of the time, not always, validation is a part of data initialization and should be done in __init__(), 
Here's some code from Python Standard Library that does that (there might be numerous other examples in the standard library, this is just one of them).

Also here's some interesting insight into the matter. Do note that the author here says -
Validating in __new__ will allow you to catch problems sooner, and give you the option of returning some sort of sentinel instead of just raising an exception, though that is probably not generally good practice.
The whole idea of `constructor` as it comes from other languages does not apply to python. __new__ is used for object creation, __init__ is used for object initialization. That's it.

Here is a post from Guido van Russom himself on why __new__ was introduced in python.


On Sat, Oct 29, 2016 at 2:20 PM, Cesar Saez <ces...@gmail.com> wrote:

Sure you can (although it forces the user to enclose any instantiation on a try except, but it works). I guess my point is that validation is usually done in the constructor and not initialisation, creating an instance just to destroy it later on without doing any work (contributing to solve the problem the programmer is trying to solve) is a bit wasteful and I would not recommend it as good practice to someone trying to learn.

On 29 Oct 2016 1:21 PM, "Alok Gandhi" <alok.ga...@gmail.com> wrote:
There's a fundamental problem with this in my view, the dounder init method of a class gets executed _after_ the instance (aka self) get created, doing checks there means you basically create an object that can potentially be invalid by passing the wrong thing and that's a problem.
I don't see this as a problem. The __init__() method is for initialization of the instance. If something goes wrong during the initialization, you can always raise from within __init__(). I mean, whatever sanity checks you want to put in for 'filling in' the variables should happen in __init__() because that is the primary role of this method. If anything bad happens and the object becomes 'invalid' python will call __del__() to clean it after itself. So it is perfectly safe to raise from __init__().

Here's a snippet exhibiting the call to __del__() by python's memory management when __init__() fail:
class A(object):
    def __init__(self):
        raise ValueError('Something bad happened!')

    def __del__(self):
        print "Delete Called"


def main():
    try:
        a = A()
    except ValueError, e:
        print e

if __name__ == '__main__':
    main()

Would result in:
>>>Something bad happened!
>>>Delete Called



--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--

Cesar Saez

unread,
Oct 29, 2016, 6:30:12 AM10/29/16
to python_in...@googlegroups.com
True, you don't need to enclose the instantiation in a try except if you don't need to keep executing the program after a bad input, it's fair enough if that's your goal (although I guess you can see my point when I mention it in the first place)

Look, It's ok to disagree on styles and all that jazz, but I feel like the waste of cpu cycles is something very hard to simply omit.

Of course performance is a trade off and everyone is free to do whatever, all I'm saying is try to not waste cpu cycles on stuff not helping to actually solve the problem you are trying to solve. If those cycles help you: go for it! if it doesn't and the way to skip that is simple maybe it worth a try, if the alternative introduce complexity maybe you decide to no go for it... or if you are totally closed to the idea of doing something different: well... there's no much benefit coming out of a discussion on the subject.

BTW, if you read my first reply carefully I'm not advocating to use dunder new as the only way to go about constructors (actually it's a bad idea). if anything I usually implement different constructors as classmethods so you can validate the user input before commiting to create an instance while failing gracefully (just like pyqt/pyside does in many cases). I didn't wanted to go in detail because of the first question being asked by someone trying to learn and probably all this is already very confusing to him.

Anyway, I feel lke this is going nowhere and I will politelly retire from this thread.
Good luck!




--

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

Alok Gandhi

unread,
Oct 29, 2016, 6:39:33 AM10/29/16
to python_in...@googlegroups.com
if you are totally closed to the idea of doing something different: well... there's no much benefit coming out of a discussion on the subject.
Hey Cesar, au contraire! I very much like the idea of exploration. In fact, the only reason of carrying on like a broken record :) is  to elicit some new ideas from participants and learn from other's insights. It is such brainstorming that let's us develop. For example, I see your perfectly valid point in wasting the CPU cycles. I did not think of this in the light of resource handling. I think enough is said on this topic. I will retire as well.

Cheers!

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Reply all
Reply to author
Forward
0 new messages