Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > finding abc's

Reply
Thread Tools

finding abc's

 
 
lars van gemerden
Guest
Posts: n/a
 
      01-25-2013
Hi all,

i was writing a function to determine the common base class of a number classes:

def common_base(classes):
if not len(classes):
return None
common = set(classes.pop().mro())
for cls in classes:
common.intersection_update(cls.mro())
while len(common) > 1:
cls1 = common.pop()
cls2 = common.pop()
if issubclass(cls1, cls2):
common.add(cls1)
elif issubclass(cls2, cls1):
common.add(cls2)
return common.pop()

and ran common_base(int, float), hoping to get numbers.Number.

this did not work because abstract base classes are not always in the mro() of classes.

My question is: is there a way to obtain the abc's of a class or otherwise a way to make the function above take abc's into account (maybe via a predefined function)?

Cheers, Lars
 
Reply With Quote
 
 
 
 
Ian Kelly
Guest
Posts: n/a
 
      01-25-2013
On Fri, Jan 25, 2013 at 10:40 AM, lars van gemerden
<(E-Mail Removed)> wrote:
> Hi all,
>
> i was writing a function to determine the common base class of a number classes:
>

[...]
>
> and ran common_base(int, float), hoping to get numbers.Number.
>
> this did not work because abstract base classes are not always in the mro() of classes.
>
> My question is: is there a way to obtain the abc's of a class or otherwise a way to make the function above take abc's into account (maybe via a predefined function)?



If the abstract base class's module has not been imported, it may not
even be loaded into memory, even though it is technically considered a
superclass. Consider this:


Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> def common_base(classes):

.... common = set()
.... for cls in object.__subclasses__():
.... if all(issubclass(c, cls) for c in classes):
.... common.add(cls)
.... return common
....
>>> common_base([int, float])

set([<class '_abcoll.Hashable'>])
>>> import numbers
>>> common_base([int, float])

set([<class 'numbers.Number'>, <class '_abcoll.Hashable'>])


If you're okay with that, then the approach above might work.


> while len(common) > 1:
> cls1 = common.pop()
> cls2 = common.pop()
> if issubclass(cls1, cls2):
> common.add(cls1)
> elif issubclass(cls2, cls1):
> common.add(cls2)


There is a flaw with your set reduction code here. If neither class
is a subclass of the other, then both will be removed. There may not
actually be a single closest common base class, however. What would
you expect the function to return in the following situation?

class A(object): pass
class B(object): pass
class C(A, B): pass
class D(A, B): pass

print common_base([C, D])
 
Reply With Quote
 
 
 
 
Peter Otten
Guest
Posts: n/a
 
      01-25-2013
lars van gemerden wrote:

> Hi all,
>
> i was writing a function to determine the common base class of a number
> classes:
>
> def common_base(classes):
> if not len(classes):
> return None
> common = set(classes.pop().mro())
> for cls in classes:
> common.intersection_update(cls.mro())
> while len(common) > 1:
> cls1 = common.pop()
> cls2 = common.pop()
> if issubclass(cls1, cls2):
> common.add(cls1)
> elif issubclass(cls2, cls1):
> common.add(cls2)
> return common.pop()
>
> and ran common_base(int, float), hoping to get numbers.Number.
>
> this did not work because abstract base classes are not always in the
> mro() of classes.
>
> My question is: is there a way to obtain the abc's of a class or otherwise
> a way to make the function above take abc's into account (maybe via a
> predefined function)?


The abstract base classes may run arbitrary code to determine the subclass
relationship:

>>> from abc import ABCMeta
>>> import random
>>> class Maybe(metaclass=ABCMeta):

.... @classmethod
.... def __subclasshook__(cls, C):
.... print("processing", C)
.... return random.choice((False, True))
....
>>> isinstance(1.1, Maybe)

processing <class 'float'>
True
>>> isinstance(1.1, Maybe)

True
>>> isinstance(1, Maybe)

processing <class 'int'>
False
>>> issubclass(float, Maybe)

True

You'd have to check every pair of classes explicitly and might still miss
(for example) numbers.Number as the module may not have been imported.

I think you are out of luck.

 
Reply With Quote
 
lars van gemerden
Guest
Posts: n/a
 
      01-25-2013
On Friday, January 25, 2013 8:04:32 PM UTC+1, Ian wrote:
> On Fri, Jan 25, 2013 at 10:40 AM, lars van gemerden
>
> <(E-Mail Removed)> wrote:
>
> > Hi all,

>
> >

>
> > i was writing a function to determine the common base class of a number classes:

>
> >

>
> [...]
>
> >

>
> > and ran common_base(int, float), hoping to get numbers.Number.

>
> >

>
> > this did not work because abstract base classes are not always in the mro() of classes.

>
> >

>
> > My question is: is there a way to obtain the abc's of a class or otherwise a way to make the function above take abc's into account (maybe via a predefined function)?

>
>
>
>
>
> If the abstract base class's module has not been imported, it may not
>
> even be loaded into memory, even though it is technically considered a
>
> superclass. Consider this:
>
>
>
>
>
> Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit
>
> (Intel)] on win32
>
> Type "help", "copyright", "credits" or "license" for more information.
>
> >>> def common_base(classes):

>
> ... common = set()
>
> ... for cls in object.__subclasses__():
>
> ... if all(issubclass(c, cls) for c in classes):
>
> ... common.add(cls)
>
> ... return common
>
> ...
>
> >>> common_base([int, float])

>
> set([<class '_abcoll.Hashable'>])
>
> >>> import numbers

>
> >>> common_base([int, float])

>
> set([<class 'numbers.Number'>, <class '_abcoll.Hashable'>])
>
>
>
>
>
> If you're okay with that, then the approach above might work.
>
>
>
>
>
> > while len(common) > 1:

>
> > cls1 = common.pop()

>
> > cls2 = common.pop()

>
> > if issubclass(cls1, cls2):

>
> > common.add(cls1)

>
> > elif issubclass(cls2, cls1):

>
> > common.add(cls2)

>
>
>
> There is a flaw with your set reduction code here. If neither class
>
> is a subclass of the other, then both will be removed. There may not
>
> actually be a single closest common base class, however. What would
>
> you expect the function to return in the following situation?
>
>
>
> class A(object): pass
>
> class B(object): pass
>
> class C(A, B): pass
>
> class D(A, B): pass
>
>
>
> print common_base([C, D])


thanks, good catch, and very concise answer. I'll give up on trying to get abc's and improve my algorithm.
 
Reply With Quote
 
lars van gemerden
Guest
Posts: n/a
 
      01-25-2013
On Friday, January 25, 2013 8:04:32 PM UTC+1, Ian wrote:
> On Fri, Jan 25, 2013 at 10:40 AM, lars van gemerden
>
> <(E-Mail Removed)> wrote:
>
> > Hi all,

>
> >

>
> > i was writing a function to determine the common base class of a number classes:

>
> >

>
> [...]
>
> >

>
> > and ran common_base(int, float), hoping to get numbers.Number.

>
> >

>
> > this did not work because abstract base classes are not always in the mro() of classes.

>
> >

>
> > My question is: is there a way to obtain the abc's of a class or otherwise a way to make the function above take abc's into account (maybe via a predefined function)?

>
>
>
>
>
> If the abstract base class's module has not been imported, it may not
>
> even be loaded into memory, even though it is technically considered a
>
> superclass. Consider this:
>
>
>
>
>
> Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit
>
> (Intel)] on win32
>
> Type "help", "copyright", "credits" or "license" for more information.
>
> >>> def common_base(classes):

>
> ... common = set()
>
> ... for cls in object.__subclasses__():
>
> ... if all(issubclass(c, cls) for c in classes):
>
> ... common.add(cls)
>
> ... return common
>
> ...
>
> >>> common_base([int, float])

>
> set([<class '_abcoll.Hashable'>])
>
> >>> import numbers

>
> >>> common_base([int, float])

>
> set([<class 'numbers.Number'>, <class '_abcoll.Hashable'>])
>
>
>
>
>
> If you're okay with that, then the approach above might work.
>
>
>
>
>
> > while len(common) > 1:

>
> > cls1 = common.pop()

>
> > cls2 = common.pop()

>
> > if issubclass(cls1, cls2):

>
> > common.add(cls1)

>
> > elif issubclass(cls2, cls1):

>
> > common.add(cls2)

>
>
>
> There is a flaw with your set reduction code here. If neither class
>
> is a subclass of the other, then both will be removed. There may not
>
> actually be a single closest common base class, however. What would
>
> you expect the function to return in the following situation?
>
>
>
> class A(object): pass
>
> class B(object): pass
>
> class C(A, B): pass
>
> class D(A, B): pass
>
>
>
> print common_base([C, D])


thanks, good catch, and very concise answer. I'll give up on trying to get abc's and improve my algorithm.
 
Reply With Quote
 
lars van gemerden
Guest
Posts: n/a
 
      01-25-2013
On Friday, January 25, 2013 8:08:18 PM UTC+1, Peter Otten wrote:
> lars van gemerden wrote:
>
>
>
> > Hi all,

>
> >

>
> > i was writing a function to determine the common base class of a number

>
> > classes:

>
> >

>
> > def common_base(classes):

>
> > if not len(classes):

>
> > return None

>
> > common = set(classes.pop().mro())

>
> > for cls in classes:

>
> > common.intersection_update(cls.mro())

>
> > while len(common) > 1:

>
> > cls1 = common.pop()

>
> > cls2 = common.pop()

>
> > if issubclass(cls1, cls2):

>
> > common.add(cls1)

>
> > elif issubclass(cls2, cls1):

>
> > common.add(cls2)

>
> > return common.pop()

>
> >

>
> > and ran common_base(int, float), hoping to get numbers.Number.

>
> >

>
> > this did not work because abstract base classes are not always in the

>
> > mro() of classes.

>
> >

>
> > My question is: is there a way to obtain the abc's of a class or otherwise

>
> > a way to make the function above take abc's into account (maybe via a

>
> > predefined function)?

>
>
>
> The abstract base classes may run arbitrary code to determine the subclass
>
> relationship:
>
>
>
> >>> from abc import ABCMeta

>
> >>> import random

>
> >>> class Maybe(metaclass=ABCMeta):

>
> ... @classmethod
>
> ... def __subclasshook__(cls, C):
>
> ... print("processing", C)
>
> ... return random.choice((False, True))
>
> ...
>
> >>> isinstance(1.1, Maybe)

>
> processing <class 'float'>
>
> True
>
> >>> isinstance(1.1, Maybe)

>
> True
>
> >>> isinstance(1, Maybe)

>
> processing <class 'int'>
>
> False
>
> >>> issubclass(float, Maybe)

>
> True
>
>
>
> You'd have to check every pair of classes explicitly and might still miss
>
> (for example) numbers.Number as the module may not have been imported.
>
>
>
> I think you are out of luck.


Thank you, interesting example. Added confirmation that trying to get the abc's is a bad idea.
 
Reply With Quote
 
lars van gemerden
Guest
Posts: n/a
 
      01-25-2013
On Friday, January 25, 2013 8:08:18 PM UTC+1, Peter Otten wrote:
> lars van gemerden wrote:
>
>
>
> > Hi all,

>
> >

>
> > i was writing a function to determine the common base class of a number

>
> > classes:

>
> >

>
> > def common_base(classes):

>
> > if not len(classes):

>
> > return None

>
> > common = set(classes.pop().mro())

>
> > for cls in classes:

>
> > common.intersection_update(cls.mro())

>
> > while len(common) > 1:

>
> > cls1 = common.pop()

>
> > cls2 = common.pop()

>
> > if issubclass(cls1, cls2):

>
> > common.add(cls1)

>
> > elif issubclass(cls2, cls1):

>
> > common.add(cls2)

>
> > return common.pop()

>
> >

>
> > and ran common_base(int, float), hoping to get numbers.Number.

>
> >

>
> > this did not work because abstract base classes are not always in the

>
> > mro() of classes.

>
> >

>
> > My question is: is there a way to obtain the abc's of a class or otherwise

>
> > a way to make the function above take abc's into account (maybe via a

>
> > predefined function)?

>
>
>
> The abstract base classes may run arbitrary code to determine the subclass
>
> relationship:
>
>
>
> >>> from abc import ABCMeta

>
> >>> import random

>
> >>> class Maybe(metaclass=ABCMeta):

>
> ... @classmethod
>
> ... def __subclasshook__(cls, C):
>
> ... print("processing", C)
>
> ... return random.choice((False, True))
>
> ...
>
> >>> isinstance(1.1, Maybe)

>
> processing <class 'float'>
>
> True
>
> >>> isinstance(1.1, Maybe)

>
> True
>
> >>> isinstance(1, Maybe)

>
> processing <class 'int'>
>
> False
>
> >>> issubclass(float, Maybe)

>
> True
>
>
>
> You'd have to check every pair of classes explicitly and might still miss
>
> (for example) numbers.Number as the module may not have been imported.
>
>
>
> I think you are out of luck.


Thank you, interesting example. Added confirmation that trying to get the abc's is a bad idea.
 
Reply With Quote
 
lars van gemerden
Guest
Posts: n/a
 
      01-26-2013
for future reference, i decided to go with 2 functions:

def common_bases(classes):
if not len(classes):
return None
common = set(classes.pop().mro())
for cls in classes:
common.intersection_update(cls.mro()) #all subclasses in common
return [cls for cls in common if not any(sub in common for sub in cls.__subclasses__())] #the classes of which no subclasses are present

def unique_common_base(classes):
while len(classes) > 1:
classes = common_bases(classes)
return classes.pop()

if i tested and understood correctly, they only take classes in the mro() into account (which might include abc's), the first gives all common base classes, the second recursively reduces further to one single class (the latter might not make to much sense, but in my program it is a safe bet for rare cases).

Thanks again for the help,

Cheers, Lars
 
Reply With Quote
 
lars van gemerden
Guest
Posts: n/a
 
      01-26-2013
for future reference, i decided to go with 2 functions:

def common_bases(classes):
if not len(classes):
return None
common = set(classes.pop().mro())
for cls in classes:
common.intersection_update(cls.mro()) #all subclasses in common
return [cls for cls in common if not any(sub in common for sub in cls.__subclasses__())] #the classes of which no subclasses are present

def unique_common_base(classes):
while len(classes) > 1:
classes = common_bases(classes)
return classes.pop()

if i tested and understood correctly, they only take classes in the mro() into account (which might include abc's), the first gives all common base classes, the second recursively reduces further to one single class (the latter might not make to much sense, but in my program it is a safe bet for rare cases).

Thanks again for the help,

Cheers, Lars
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Finding Server... Finding Host.... enough already!!! Leesa_Tay@softhome.net Computer Support 2 01-20-2006 10:23 AM
Finding Wireless Connection Icon =?Utf-8?B?TWFyaw==?= Wireless Networking 0 10-08-2005 07:05 PM
Finding a wireless vendor with XP64 Pro drivers =?Utf-8?B?V2FycmVuIFo=?= Wireless Networking 3 06-08-2005 10:29 PM
getting canned for finding security breaches Curious George Wireless Networking 2 02-04-2005 12:54 AM
Help finding wireless network OVS Wireless Networking 3 08-16-2004 10:09 PM



Advertisments