Re: Disallowing instantiation of super class

2017-02-24 Thread Irv Kalb

> On Feb 24, 2017, at 1:24 AM, Steve D'Aprano  
> wrote:
> 
> On Fri, 24 Feb 2017 11:19 am, Irv Kalb wrote:
> 
>> Hi,
>> 
>> I have built a set of three classes:
>> 
>> -  A super class, let's call it: Base
> [...]
>> I would like to add is some "insurance" that I (or someone else who uses
>> my code) never instantiates my Base class,  It is not intended to be
>> instantiated because some of the needed instance variables are only
>> created in the __init__ method of ClassA and ClassB.
> 
> class Base:
>   def __init__(self):
>   if type(self) is Base:
>   raise TypeError("cannot instantiate Base class")
> 
> 
> Does that help?
> 
> 

Double D'oh!!

That's exactly what I was looking for.  (Why didn't I think of that?)

Thanks very much!

Irv

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Disallowing instantiation of super class

2017-02-24 Thread Steve D'Aprano
On Sat, 25 Feb 2017 05:40 am, MRAB wrote:

>> class Base:
>> def __init__(self):
>> if type(self) is Base:
>> raise TypeError("cannot instantiate Base class")
>>
>>
>> Does that help?
>>
> D'oh! Never thought of that! :-)
> 
> The OP is using Python 2.7, so you'll need to use new-style classes:
> 
> class Base(object):
>  def __init__(self):
>  if type(self) is Base:
>  raise TypeError("cannot instantiate Base class")

For "classic classes", you can use this:

if self.__class__ is Base:
raise TypeError("cannot instantiate Base class")



-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Disallowing instantiation of super class

2017-02-24 Thread MRAB

On 2017-02-24 09:24, Steve D'Aprano wrote:

On Fri, 24 Feb 2017 11:19 am, Irv Kalb wrote:


Hi,

I have built a set of three classes:

-  A super class, let's call it: Base

[...]

I would like to add is some "insurance" that I (or someone else who uses
my code) never instantiates my Base class,  It is not intended to be
instantiated because some of the needed instance variables are only
created in the __init__ method of ClassA and ClassB.


class Base:
def __init__(self):
if type(self) is Base:
raise TypeError("cannot instantiate Base class")


Does that help?


D'oh! Never thought of that! :-)

The OP is using Python 2.7, so you'll need to use new-style classes:

class Base(object):
def __init__(self):
if type(self) is Base:
raise TypeError("cannot instantiate Base class")

--
https://mail.python.org/mailman/listinfo/python-list


Re: Disallowing instantiation of super class

2017-02-24 Thread Wolfgang Maier

On 24.02.2017 01:19, Irv Kalb wrote:

Hi,
I have built a set of three classes:
-  A super class, let's call it: Base

-  A class that inherits from Base, let's call that: ClassA

-  Another class that inherits from Base, let's call that: ClassB

ClassA and ClassB have some code in their __init__ methods that set some 
instance variables to different values.  After doing so, they call the the 
__init__ method of their common super class (Base) to set some other instance 
variables to some common values.  This all works great.  Instances of ClassA 
and ClassB do just what I want them to.



[...]


If I can find a way to determine that the caller is attempting to instantiate 
Base directly, I will raise an exception.



A pattern I'm using sometimes to achieve this is:

class Base:
def __init__(self):
self.set_common()
self.set_specific()

def set_common(self):
self.a = 10

def set_specific(self):
raise NotImplementedError()


class A(Base):
def set_specific(self):
self.b = 20


class B(Base):
def set_specific(self):
self.b = 30


Of course, MRAB's and Peter's suggestion are very similar ideas.

--
https://mail.python.org/mailman/listinfo/python-list


Re: Disallowing instantiation of super class

2017-02-24 Thread Steve D'Aprano
On Fri, 24 Feb 2017 11:19 am, Irv Kalb wrote:

> Hi,
> 
> I have built a set of three classes:
> 
> -  A super class, let's call it: Base
[...]
> I would like to add is some "insurance" that I (or someone else who uses
> my code) never instantiates my Base class,  It is not intended to be
> instantiated because some of the needed instance variables are only
> created in the __init__ method of ClassA and ClassB.

class Base:
def __init__(self):
if type(self) is Base:
raise TypeError("cannot instantiate Base class")


Does that help?





-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Disallowing instantiation of super class

2017-02-23 Thread Irv Kalb

> On Feb 23, 2017, at 4:40 PM, MRAB  wrote:
> 
> On 2017-02-24 00:19, Irv Kalb wrote:
>> Hi,
>> 
>> I have built a set of three classes:
>> 
>> -  A super class, let's call it: Base
>> 
>> -  A class that inherits from Base, let's call that: ClassA
>> 
>> -  Another class that inherits from Base, let's call that: ClassB
>> 
>> ClassA and ClassB have some code in their __init__ methods that set some 
>> instance variables to different values.  After doing so, they call the the 
>> __init__ method of their common super class (Base) to set some other 
>> instance variables to some common values.  This all works great.  Instances 
>> of ClassA and ClassB do just what I want them to.
>> 
>> I would like to add is some "insurance" that I (or someone else who uses my 
>> code) never instantiates my Base class,  It is not intended to be 
>> instantiated because some of the needed instance variables are only created 
>> in the __init__ method of ClassA and ClassB.  I am looking for some way in 
>> the Base's __init__ method to determine if the method was called directly:
>> 
>>instanceOfBase = Base(... some data ...)  # I want this case to generate 
>> an error
>> 
>> I tried using "isinstance(self, Base)", but it returns True when I 
>> instantiate an object from ClassA, from ClassB, or from Base.
>> 
>> If I can find a way to determine that the caller is attempting to 
>> instantiate Base directly, I will raise an exception.
>> 
>> Thanks,
>> 
>> Irv
>> 
>> (If it makes a difference, I am doing this currently in Python 2.7 - please 
>> don't beat me up about that.)
>> 
> Apart from renaming Base to _Base as a hint, you could put Base's 
> initialisation code in, say, '_init' and have Base's __init__ just raise an 
> exception.
> 
> ClassA and ClassB would then call Base's _init instead of its __init__.
> 
> -- 
> https://mail.python.org/mailman/listinfo/python-list
> 

MRAB and Peter:  Thank you very much for your solutions.  I had considered both 
of these, but was wondering if there was another way.   Peter's solution does 
exactly what I want, but I'm not ready to get into metaclasses.  So I decided 
to go with MRAB's approach.  I've modified my code and it seems to work great.

Thank you both.

Irv

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Disallowing instantiation of super class

2017-02-23 Thread Peter Otten
Irv Kalb wrote:

> Hi,
> 
> I have built a set of three classes:
> 
> -  A super class, let's call it: Base
> 
> -  A class that inherits from Base, let's call that: ClassA
> 
> -  Another class that inherits from Base, let's call that: ClassB
> 
> ClassA and ClassB have some code in their __init__ methods that set some
> instance variables to different values.  After doing so, they call the the
> __init__ method of their common super class (Base) to set some other
> instance variables to some common values.  This all works great. 
> Instances of ClassA and ClassB do just what I want them to.
> 
> I would like to add is some "insurance" that I (or someone else who uses
> my code) never instantiates my Base class,  It is not intended to be
> instantiated because some of the needed instance variables are only
> created in the __init__ method of ClassA and ClassB.  I am looking for
> some way in the Base's __init__ method to determine if the method was
> called directly:
> 
> instanceOfBase = Base(... some data ...)  # I want this case to
> generate an error
> 
> I tried using "isinstance(self, Base)", but it returns True when I
> instantiate an object from ClassA, from ClassB, or from Base.
> 
> If I can find a way to determine that the caller is attempting to
> instantiate Base directly, I will raise an exception.
> 
> Thanks,
> 
> Irv
> 
> (If it makes a difference, I am doing this currently in Python 2.7 -
> please don't beat me up about that.)

>>> import abc
>>> class Base:
... __metaclass__ = abc.ABCMeta
... @abc.abstractmethod
... def __init__(self):
... self.z = self.x + self.y
... 
>>> class A(Base):
... def __init__(self):
... self.x = 2
... self.y = 3
... super(A, self).__init__()
... 
>>> A().z
5
>>> Base()
Traceback (most recent call last):
  File "", line 1, in 
TypeError: Can't instantiate abstract class Base with abstract methods 
__init__


-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Disallowing instantiation of super class

2017-02-23 Thread MRAB

On 2017-02-24 00:19, Irv Kalb wrote:

Hi,

I have built a set of three classes:

-  A super class, let's call it: Base

-  A class that inherits from Base, let's call that: ClassA

-  Another class that inherits from Base, let's call that: ClassB

ClassA and ClassB have some code in their __init__ methods that set some 
instance variables to different values.  After doing so, they call the the 
__init__ method of their common super class (Base) to set some other instance 
variables to some common values.  This all works great.  Instances of ClassA 
and ClassB do just what I want them to.

I would like to add is some "insurance" that I (or someone else who uses my 
code) never instantiates my Base class,  It is not intended to be instantiated because 
some of the needed instance variables are only created in the __init__ method of ClassA 
and ClassB.  I am looking for some way in the Base's __init__ method to determine if the 
method was called directly:

instanceOfBase = Base(... some data ...)  # I want this case to generate an 
error

I tried using "isinstance(self, Base)", but it returns True when I instantiate 
an object from ClassA, from ClassB, or from Base.

If I can find a way to determine that the caller is attempting to instantiate 
Base directly, I will raise an exception.

Thanks,

Irv

(If it makes a difference, I am doing this currently in Python 2.7 - please 
don't beat me up about that.)

Apart from renaming Base to _Base as a hint, you could put Base's 
initialisation code in, say, '_init' and have Base's __init__ just raise 
an exception.


ClassA and ClassB would then call Base's _init instead of its __init__.

--
https://mail.python.org/mailman/listinfo/python-list


Disallowing instantiation of super class

2017-02-23 Thread Irv Kalb
Hi,

I have built a set of three classes:

-  A super class, let's call it: Base

-  A class that inherits from Base, let's call that: ClassA

-  Another class that inherits from Base, let's call that: ClassB

ClassA and ClassB have some code in their __init__ methods that set some 
instance variables to different values.  After doing so, they call the the 
__init__ method of their common super class (Base) to set some other instance 
variables to some common values.  This all works great.  Instances of ClassA 
and ClassB do just what I want them to.

I would like to add is some "insurance" that I (or someone else who uses my 
code) never instantiates my Base class,  It is not intended to be instantiated 
because some of the needed instance variables are only created in the __init__ 
method of ClassA and ClassB.  I am looking for some way in the Base's __init__ 
method to determine if the method was called directly:

instanceOfBase = Base(... some data ...)  # I want this case to generate an 
error

I tried using "isinstance(self, Base)", but it returns True when I instantiate 
an object from ClassA, from ClassB, or from Base.  

If I can find a way to determine that the caller is attempting to instantiate 
Base directly, I will raise an exception.

Thanks,

Irv

(If it makes a difference, I am doing this currently in Python 2.7 - please 
don't beat me up about that.)
-- 
https://mail.python.org/mailman/listinfo/python-list