Re: [Maya-Python] Controlled Class instantiation with multiple constructors

2020-04-19 Thread HarshadB
@Alok Thank you for the elaborate answer and clean code example. And thank 
you for your time.
 

> May we know what was the challenge in implementing the behavior in 
> __init__ ?


 It was more of a personal challenge to try __new__ as I was learning about 
metaclasses and other intermediate topics. This code is from a personal 
project where everything was accumulated in init. So, while writing the 
alternate constructors, I wanted to try that.

I would encourage you to read the docs  
> for 
> __new__, generally speaking you can achieve all you want from the __init__, 
> __new__ is usually required for subclassing immutables like str, tuple, 
> etc. 

 
+1 for the doc reference

Actually the object is passed to __init__, not the class. As I mentioned 
> above, if you are returning the object from __new__, this would cause 
> __init__ to be called on the object that is returned, which in your case 
> would be done from one of the alternative constructors.

 
This makes sense.
 
I will continue using init for now but am more familiar with __new__ now 
than before.

Thanks
- H

On Thursday, April 16, 2020 at 11:28:06 PM UTC+9, Alok Gandhi wrote:
>
> Harshad, I missed your original question, you already had all the 
> information in there, I should have given more attention, apologies
>
> Currently trying to implement this with __new__. Previously, all the 
>> "isinstance" checks were done in init which I wanted to simplify.
>> I couldn't get it to work exactly how I wanted to, but I did get it to 
>> work with all four arg input types (selection, str, mObjectHandle, mObject).
>
> May we know what was the challenge in implementing the behavior in 
> __init__ ?
>
> I would encourage you to read the docs 
> for 
> __new__, generally speaking you can achieve all you want from the __init__, 
> __new__ is usually required for subclassing immutables like str, tuple, 
> etc. I have personally used __new__ in the past for some meta programming 
> involving ORM/ Db stuff, implementing singleton pattern (though it can be 
> done in quite a few different ways) etc.
>
> Further, as the doc says, to avoid calling the __init__ you can simply 
> choose to not return the instance from __new__, but I guess that is not 
> what you are looking for, or maybe?
>
>
>> *Problem is when the argument is checked in __new__:*- A class is 
>> returned from the respective classmethod and passed to init.  
>
> Actually the object is passed to __init__, not the class. As I mentioned 
> above, if you are returning the object from __new__, this would cause 
> __init__ to be called on the object that is returned, which in your case 
> would be done from one of the alternative constructors.
>
> Finally, I feel that we can still get away in this case without using 
> __new__ still retaining the required behavior. Please find my code here 
> . This covers almost everything you need. 
> Let me know if this does not work.
>
> Cheers!
>
> On Thu, Apr 16, 2020 at 1:41 AM Justin Israel  > wrote:
>
>>
>>
>> On Wed, Apr 15, 2020, 11:01 PM HarshadB > 
>> wrote:
>>
>>> @alok
>>> Thank you for your reply.
>>>
>>> I already have working class constructors(classmethods) that do what I 
>>> want. That part is done.
>>> Sorry, I should have asked the question clearly in the first line.
>>>
>>> What I am actually doing is to further automate the instance creation of 
>>> the class based on the argument provided, or with no argument.
>>> For e.g with no argument, it should call cls.from_selection(cls)
>>> This part is also done but in a hackish sort of way. I have isinstance 
>>> checks in my class __new__ method. *I want to write this code in a 
>>> better, efficient way.*
>>>
>>>
>>> *Problem is when the argument is checked in __new__:*- A class is 
>>> returned from the respective classmethod and passed to init.
>>> - The original argument is still passed to init after already passing it 
>>> to the classmethod above.
>>> - So the init gets called twice.
>>>
>>
>> Since you are combining classmethod and __new__, you would have to 
>> implement your classmethod to also use super().__new__ so that it doesn't 
>> call the constructor. But that is a bit unintuitive if it is a public 
>> classmethod. So maybe you should define private class methods that can be 
>> called by your __new__. 
>>
>>
>> - I have worked around this for now by having a *isinstance(arg, 
>>> om.mObject)* check in the __init__.
>>>
>>> - H
>>>
>>> On Wednesday, April 15, 2020 at 3:35:30 PM UTC+9, Alok Gandhi wrote:

 Python @classmethod were added for this exact reason - Alternative 
 Contructors.

 class Foo(object):
 def __init__(self, bar=None, baz=None):
 self._bar = bar
 self._baz = baz
 print 'bar: {}, baz: {}'.format(self._bar, self._baz)

 

Re: [Maya-Python] Controlled Class instantiation with multiple constructors

2020-04-16 Thread Alok Gandhi
Harshad, I missed your original question, you already had all the
information in there, I should have given more attention, apologies

Currently trying to implement this with __new__. Previously, all the
> "isinstance" checks were done in init which I wanted to simplify.
> I couldn't get it to work exactly how I wanted to, but I did get it to
> work with all four arg input types (selection, str, mObjectHandle, mObject).

May we know what was the challenge in implementing the behavior in __init__
?

I would encourage you to read the docs
for
__new__, generally speaking you can achieve all you want from the __init__,
__new__ is usually required for subclassing immutables like str, tuple,
etc. I have personally used __new__ in the past for some meta programming
involving ORM/ Db stuff, implementing singleton pattern (though it can be
done in quite a few different ways) etc.

Further, as the doc says, to avoid calling the __init__ you can simply
choose to not return the instance from __new__, but I guess that is not
what you are looking for, or maybe?


> *Problem is when the argument is checked in __new__:*- A class is
> returned from the respective classmethod and passed to init.

Actually the object is passed to __init__, not the class. As I mentioned
above, if you are returning the object from __new__, this would cause
__init__ to be called on the object that is returned, which in your case
would be done from one of the alternative constructors.

Finally, I feel that we can still get away in this case without using
__new__ still retaining the required behavior. Please find my code here
. This covers almost everything you need.
Let me know if this does not work.

Cheers!

On Thu, Apr 16, 2020 at 1:41 AM Justin Israel 
wrote:

>
>
> On Wed, Apr 15, 2020, 11:01 PM HarshadB  wrote:
>
>> @alok
>> Thank you for your reply.
>>
>> I already have working class constructors(classmethods) that do what I
>> want. That part is done.
>> Sorry, I should have asked the question clearly in the first line.
>>
>> What I am actually doing is to further automate the instance creation of
>> the class based on the argument provided, or with no argument.
>> For e.g with no argument, it should call cls.from_selection(cls)
>> This part is also done but in a hackish sort of way. I have isinstance
>> checks in my class __new__ method. *I want to write this code in a
>> better, efficient way.*
>>
>>
>> *Problem is when the argument is checked in __new__:*- A class is
>> returned from the respective classmethod and passed to init.
>> - The original argument is still passed to init after already passing it
>> to the classmethod above.
>> - So the init gets called twice.
>>
>
> Since you are combining classmethod and __new__, you would have to
> implement your classmethod to also use super().__new__ so that it doesn't
> call the constructor. But that is a bit unintuitive if it is a public
> classmethod. So maybe you should define private class methods that can be
> called by your __new__.
>
>
> - I have worked around this for now by having a *isinstance(arg,
>> om.mObject)* check in the __init__.
>>
>> - H
>>
>> On Wednesday, April 15, 2020 at 3:35:30 PM UTC+9, Alok Gandhi wrote:
>>>
>>> Python @classmethod were added for this exact reason - Alternative
>>> Contructors.
>>>
>>> class Foo(object):
>>> def __init__(self, bar=None, baz=None):
>>> self._bar = bar
>>> self._baz = baz
>>> print 'bar: {}, baz: {}'.format(self._bar, self._baz)
>>>
>>> @classmethod
>>> def from_bar(cls, bar):
>>> return cls(bar=bar)
>>>
>>> @classmethod
>>> def from_baz(cls, baz):
>>> return cls(baz=baz)
>>>
>>> # Default
>>> foo = Foo('default bar', 'default baz')
>>> # bar: default bar, baz: default baz
>>>
>>> # From bar
>>> foo_bar = Foo.from_bar('from bar')
>>> # bar: from bar, baz: None
>>>
>>> # From baz
>>> foo_baz = Foo.from_baz('from baz')
>>> # bar: None, baz: from baz
>>>
>>>
>>> - Alok
>>>
>>> On Wed, Apr 15, 2020, 10:44 HarshadB  wrote:
>>>
 Hoping for some help with this, I am trying to understand Class
 construction(instantiation before init).

 I have a component class which encapsulates a hierarchy of nodes in
 Maya. Instantiated using a mObject as input.
 BaseComponent(mObject)

 I want to automate the instance construction of this class based on
 selection, mObjectHandle, string and have created classmethods (as
 alternative constructors) for the same. I wanted to allow initiation just
 by BaseComponent() that will take the selection and avoid
 BaseComponent.some_method as default.

 Goal:
 BaseComponent()  # Takes selection
 BaseComponent.fromString()  # Takes string name of an object in scene
 BaseComponent.fromMObjectHandle()  # Takes an mObjectHandle for an
 object in scene
 BaseComponent(mObject)  # Takes 

Re: [Maya-Python] Controlled Class instantiation with multiple constructors

2020-04-15 Thread Justin Israel
On Wed, Apr 15, 2020, 11:01 PM HarshadB  wrote:

> @alok
> Thank you for your reply.
>
> I already have working class constructors(classmethods) that do what I
> want. That part is done.
> Sorry, I should have asked the question clearly in the first line.
>
> What I am actually doing is to further automate the instance creation of
> the class based on the argument provided, or with no argument.
> For e.g with no argument, it should call cls.from_selection(cls)
> This part is also done but in a hackish sort of way. I have isinstance
> checks in my class __new__ method. *I want to write this code in a
> better, efficient way.*
>
>
> *Problem is when the argument is checked in __new__:*- A class is
> returned from the respective classmethod and passed to init.
> - The original argument is still passed to init after already passing it
> to the classmethod above.
> - So the init gets called twice.
>

Since you are combining classmethod and __new__, you would have to
implement your classmethod to also use super().__new__ so that it doesn't
call the constructor. But that is a bit unintuitive if it is a public
classmethod. So maybe you should define private class methods that can be
called by your __new__.


- I have worked around this for now by having a *isinstance(arg,
> om.mObject)* check in the __init__.
>
> - H
>
> On Wednesday, April 15, 2020 at 3:35:30 PM UTC+9, Alok Gandhi wrote:
>>
>> Python @classmethod were added for this exact reason - Alternative
>> Contructors.
>>
>> class Foo(object):
>> def __init__(self, bar=None, baz=None):
>> self._bar = bar
>> self._baz = baz
>> print 'bar: {}, baz: {}'.format(self._bar, self._baz)
>>
>> @classmethod
>> def from_bar(cls, bar):
>> return cls(bar=bar)
>>
>> @classmethod
>> def from_baz(cls, baz):
>> return cls(baz=baz)
>>
>> # Default
>> foo = Foo('default bar', 'default baz')
>> # bar: default bar, baz: default baz
>>
>> # From bar
>> foo_bar = Foo.from_bar('from bar')
>> # bar: from bar, baz: None
>>
>> # From baz
>> foo_baz = Foo.from_baz('from baz')
>> # bar: None, baz: from baz
>>
>>
>> - Alok
>>
>> On Wed, Apr 15, 2020, 10:44 HarshadB  wrote:
>>
>>> Hoping for some help with this, I am trying to understand Class
>>> construction(instantiation before init).
>>>
>>> I have a component class which encapsulates a hierarchy of nodes in
>>> Maya. Instantiated using a mObject as input.
>>> BaseComponent(mObject)
>>>
>>> I want to automate the instance construction of this class based on
>>> selection, mObjectHandle, string and have created classmethods (as
>>> alternative constructors) for the same. I wanted to allow initiation just
>>> by BaseComponent() that will take the selection and avoid
>>> BaseComponent.some_method as default.
>>>
>>> Goal:
>>> BaseComponent()  # Takes selection
>>> BaseComponent.fromString()  # Takes string name of an object in scene
>>> BaseComponent.fromMObjectHandle()  # Takes an mObjectHandle for an
>>> object in scene
>>> BaseComponent(mObject)  # Takes mObject as default
>>>
>>> Currently trying to implement this with __new__. Previously, all the
>>> "isinstance" checks were done in init which I wanted to simplify.
>>> I couldn't get it to work exactly how I wanted to, but I did get it to
>>> work with all four arg input types (selection, str, mObjectHandle, mObject).
>>>
>>> Problems:
>>> - The problem is there's no clear error/warning if the end-user makes a
>>> mistake.
>>> - All alternative constructors also pass to the init where I had to put
>>> a mObject isinstance check for it to work. If possible, I want to remove
>>> mObject check in init as mObject should be the only one passed to init.
>>>
>>> I have attached my extracted current working code in Pastebin. It has
>>> print statements and can be run in a new Maya session:
>>> https://pastebin.com/tN5bs6g0
>>>
>>> Any suggestions/recommendations are really appreciated. Please let me
>>> know if I wasn't clear enough.
>>> (I have a basic idea about metaclasses and class decorators, so any
>>> advice that includes those is welcome.)
>>>
>>> Thank you!
>>>
>>> --
>>> 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+unsubscr...@googlegroups.com.
>>> To view this discussion on the web visit
>>> https://groups.google.com/d/msgid/python_inside_maya/e97d389f-19c1-49b4-a868-79afafe965fc%40googlegroups.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+unsubscr...@googlegroups.com.
> To view this 

Re: [Maya-Python] Controlled Class instantiation with multiple constructors

2020-04-15 Thread HarshadB
@alok
Thank you for your reply.

I already have working class constructors(classmethods) that do what I 
want. That part is done.
Sorry, I should have asked the question clearly in the first line.

What I am actually doing is to further automate the instance creation of 
the class based on the argument provided, or with no argument.
For e.g with no argument, it should call cls.from_selection(cls)
This part is also done but in a hackish sort of way. I have isinstance 
checks in my class __new__ method. *I want to write this code in a better, 
efficient way.*


*Problem is when the argument is checked in __new__:*- A class is returned 
from the respective classmethod and passed to init.
- The original argument is still passed to init after already passing it to 
the classmethod above.
- So the init gets called twice.
- I have worked around this for now by having a *isinstance(arg, 
om.mObject)* check in the __init__.

- H

On Wednesday, April 15, 2020 at 3:35:30 PM UTC+9, Alok Gandhi wrote:
>
> Python @classmethod were added for this exact reason - Alternative 
> Contructors.
>
> class Foo(object):
> def __init__(self, bar=None, baz=None):
> self._bar = bar
> self._baz = baz
> print 'bar: {}, baz: {}'.format(self._bar, self._baz)
>
> @classmethod
> def from_bar(cls, bar):
> return cls(bar=bar)
>
> @classmethod
> def from_baz(cls, baz):
> return cls(baz=baz)
>
> # Default
> foo = Foo('default bar', 'default baz')
> # bar: default bar, baz: default baz
>
> # From bar
> foo_bar = Foo.from_bar('from bar')
> # bar: from bar, baz: None
>
> # From baz
> foo_baz = Foo.from_baz('from baz')
> # bar: None, baz: from baz
>
>
> - Alok
>
> On Wed, Apr 15, 2020, 10:44 HarshadB > 
> wrote:
>
>> Hoping for some help with this, I am trying to understand Class 
>> construction(instantiation before init).
>>
>> I have a component class which encapsulates a hierarchy of nodes in Maya. 
>> Instantiated using a mObject as input.
>> BaseComponent(mObject)
>>
>> I want to automate the instance construction of this class based on 
>> selection, mObjectHandle, string and have created classmethods (as 
>> alternative constructors) for the same. I wanted to allow initiation just 
>> by BaseComponent() that will take the selection and avoid 
>> BaseComponent.some_method as default.
>>
>> Goal:
>> BaseComponent()  # Takes selection
>> BaseComponent.fromString()  # Takes string name of an object in scene
>> BaseComponent.fromMObjectHandle()  # Takes an mObjectHandle for an object 
>> in scene
>> BaseComponent(mObject)  # Takes mObject as default
>>
>> Currently trying to implement this with __new__. Previously, all the 
>> "isinstance" checks were done in init which I wanted to simplify.
>> I couldn't get it to work exactly how I wanted to, but I did get it to 
>> work with all four arg input types (selection, str, mObjectHandle, mObject).
>>
>> Problems:
>> - The problem is there's no clear error/warning if the end-user makes a 
>> mistake.
>> - All alternative constructors also pass to the init where I had to put a 
>> mObject isinstance check for it to work. If possible, I want to remove 
>> mObject check in init as mObject should be the only one passed to init.
>>
>> I have attached my extracted current working code in Pastebin. It has 
>> print statements and can be run in a new Maya session:
>> https://pastebin.com/tN5bs6g0
>>
>> Any suggestions/recommendations are really appreciated. Please let me 
>> know if I wasn't clear enough.
>> (I have a basic idea about metaclasses and class decorators, so any 
>> advice that includes those is welcome.)
>>
>> Thank you!
>>
>> -- 
>> 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+unsubscr...@googlegroups.com .
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/python_inside_maya/e97d389f-19c1-49b4-a868-79afafe965fc%40googlegroups.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+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/python_inside_maya/4451bc9e-ddec-4296-87b9-9b1b12ce41e9%40googlegroups.com.


Re: [Maya-Python] Controlled Class instantiation with multiple constructors

2020-04-15 Thread Alok Gandhi
Python @classmethod were added for this exact reason - Alternative
Contructors.

class Foo(object):
def __init__(self, bar=None, baz=None):
self._bar = bar
self._baz = baz
print 'bar: {}, baz: {}'.format(self._bar, self._baz)

@classmethod
def from_bar(cls, bar):
return cls(bar=bar)

@classmethod
def from_baz(cls, baz):
return cls(baz=baz)

# Default
foo = Foo('default bar', 'default baz')
# bar: default bar, baz: default baz

# From bar
foo_bar = Foo.from_bar('from bar')
# bar: from bar, baz: None

# From baz
foo_baz = Foo.from_baz('from baz')
# bar: None, baz: from baz


- Alok

On Wed, Apr 15, 2020, 10:44 HarshadB  wrote:

> Hoping for some help with this, I am trying to understand Class
> construction(instantiation before init).
>
> I have a component class which encapsulates a hierarchy of nodes in Maya.
> Instantiated using a mObject as input.
> BaseComponent(mObject)
>
> I want to automate the instance construction of this class based on
> selection, mObjectHandle, string and have created classmethods (as
> alternative constructors) for the same. I wanted to allow initiation just
> by BaseComponent() that will take the selection and avoid
> BaseComponent.some_method as default.
>
> Goal:
> BaseComponent()  # Takes selection
> BaseComponent.fromString()  # Takes string name of an object in scene
> BaseComponent.fromMObjectHandle()  # Takes an mObjectHandle for an object
> in scene
> BaseComponent(mObject)  # Takes mObject as default
>
> Currently trying to implement this with __new__. Previously, all the
> "isinstance" checks were done in init which I wanted to simplify.
> I couldn't get it to work exactly how I wanted to, but I did get it to
> work with all four arg input types (selection, str, mObjectHandle, mObject).
>
> Problems:
> - The problem is there's no clear error/warning if the end-user makes a
> mistake.
> - All alternative constructors also pass to the init where I had to put a
> mObject isinstance check for it to work. If possible, I want to remove
> mObject check in init as mObject should be the only one passed to init.
>
> I have attached my extracted current working code in Pastebin. It has
> print statements and can be run in a new Maya session:
> https://pastebin.com/tN5bs6g0
>
> Any suggestions/recommendations are really appreciated. Please let me know
> if I wasn't clear enough.
> (I have a basic idea about metaclasses and class decorators, so any advice
> that includes those is welcome.)
>
> Thank you!
>
> --
> 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+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/python_inside_maya/e97d389f-19c1-49b4-a868-79afafe965fc%40googlegroups.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+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/python_inside_maya/CAPaTLMQ70FCh4JNBeY4fRL22ByR-%3DgGkE8AaGegWo8OMTfU05g%40mail.gmail.com.