Dynamically determine base classes on instantiation

Steven D'Aprano steve+comp.lang.python at pearwood.info
Thu Aug 16 14:04:34 EDT 2012


On Thu, 16 Aug 2012 14:52:30 +0200, Thomas Bach wrote:

> I'm
> querying the crunchbase API which returns JSON data and is rather poorly
> documented. I want to create a data model for the companies listed on
> Crunchbase in order to be able to put the queried data in a data-base.
> As I am too lazy to examine all the data by hand I thought I automatize
> this. I thought that it would be nice to be able to pass a function a
> parsed JSON object (AFAIK these are lists, dicts, strings, ints, floats,
> strs in Python) and it returns me the type of these objects. For the
> simple classes (str, int, float) this is quite trivial: F('foo') should
> return `str' and F(8) should return `int'.

Um, this is utterly trivial for *any* object. Just call type(object), and 
it will return the type of the object.


> For a compound object like dict I would like it to return the data
> fields with their type. Hence, F({'foo': 8}) should return {'foo': int},

Your first problem is defining what you consider a compound object. Once 
you've done that, it just becomes a matter of recursion:

def recursive_type(obj):
    if isinstance(obj, dict):
        return dict((k, recursive_type(v)) for (k, v) in obj.items())
    elif isinstance(obj, list):
        pass  # whatever...
    else:
        return type(obj)



> and given that f = F({'foo': {'bar': 80}}) I would like f to equal to
> {'foo': dict}, with the option to query the type of 'foo' via f.foo,
> where the latter should equal to {'bar': int}. So far, this is not a
> complicated case. But, sometimes a data field on returned data set is
> simply None. Thus, I want to extract the types from another data set and
> merge the two.
> 
> So, my question (as far as I can see it, please correct me if I am
> wrong) is less of the "How do I achieve this?"-kind, but more of the
> "What is a clean design for this?"-kind. My intuitive thought was that
> the `merge' function should be a part of the object returned from `F'.

This isn't Java you know. Just write a function to merge the two data 
sets and be done with it.


>> Consider your two examples:
>> 
>> a = Foo(['a', 'list'])
>> b = Foo({'blah': 8})
>> 
>> According to your design:
>> 
>> a is a Foo
>> b is a Foo
> 
> I actually never said that. 

You might not have said that, but that's what instantiation implies. If 
you instantiate Foo, you get a Foo instance.


> I simply wanted `a' and `b' to share the
> same function (the `merge' function), I thought that the easiest way to
> achieve this is by letting them share the same name-space.

Or you could you use composition, or a mixin, or straits, or prototypes. 
Well, prototypes are hard in Python -- I'm not sure how you would go 
about doing that.



-- 
Steven



More information about the Python-list mailing list