Dynamically determine base classes on instantiation
Hans Mulder
hansmu at xs4all.nl
Thu Aug 16 11:10:43 EDT 2012
On 16/08/12 14:52:30, Thomas Bach wrote:
> On Thu, Aug 16, 2012 at 12:16:03AM +0000, Steven D'Aprano wrote:
>> > Some comments:
>> >
>> > 1) What you show are not "use cases", but "examples". A use-case is a
>> > description of an actual real-world problem that needs to be solved. A
>> > couple of asserts is not a use-case.
> Thanks for the clarification on that one. So, here's the use-case: 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'.
>
> 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}, 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'.
The misunderstanding is that you feel F should return an object with
a 'merge' method and a varying abse type, while Steven and others
think that F should be a function.
Maybe something like:
def F(obj):
if obj is None:
return None
tp = type(obj)
if tp in (bool, int, float, str):
return tp
elif tp is list:
return merge([F(elem) for elem in obj])
elif tp is dict:
return dict((k, F(v)) for k,v in obj.iteritems())
else:
raise ValueError("Unexpected type %s for value %s" %(tp, obj))
def merge(lst):
if None in lst:
not_nones = [elem for elem in lst if elem is not None]
if not_nones:
not_none = not_nones[0]
lst = [not_none if elem is None else elem for elem in lst]
else:
return lst # all elements are None; nothing can be done
types = {}
for elem in lst:
if type(elem) is dict:
for k,v in elem.iteritems():
if v is None:
if k in types:
elem[k] = types[k]
else:
for other in lst:
if (other is not elem
and type(other) is dict
and k in other
and other[k] is not None
):
elem[k] = types[k] = other[k]
break
return lst
The merge logic you have in mind may be different from what I just
made up, but the idea remains: F and merge can be functions.
Hope this helps,
-- HansM
More information about the Python-list
mailing list