How much introspection is implementation dependent?

J

James Stroud

Hello,

I wanted to automagically generate an instance of a class from a
dictionary--which might be generated from yaml or json. I came up with this:


# automagical constructor
def construct(cls, adict):
dflts = cls.__init__.im_func.func_defaults
vnames = cls.__init__.im_func.func_code.co_varnames

argnames = vnames[1:-len(dflts)]
argvals = [adict.pop(n) for n in argnames]

return cls(*argvals, **adict)


I'm wondering, I did a lot of introspection here. How much of this
introspection can I count on in other implementations. Is this a
byproduct of CPython? Will all classes have these attributes, even
classes imported from shared objects? It would be nice to rely on these
things.

<aside> I know pyaml advertises the ability to do this, but, much to my
annoyance, I found it never actually calls __init__() of YAMLObject
subclasses, but this is another topic altogether. </aside>

Below is the example (optional reading).

James

==

#! /usr/bin/env python

# automagical constructor
def construct(cls, adict):
dflts = cls.__init__.im_func.func_defaults
vnames = cls.__init__.im_func.func_code.co_varnames

argnames = vnames[1:-len(dflts)]
argvals = [adict.pop(n) for n in argnames]

return cls(*argvals, **adict)


def test():

class C(object):
def __init__(self, arg1, arg2, kwa3=3):
self.argsum = arg1 + arg2
self.kwsum = kwa3
def __str__(self):
return "%s & %s" % (self.argsum, self.kwsum)

# now a dict for autmagical generation
adict = {'arg1':1, 'arg2':2, 'kwa3':42}

print '======== test 1 ========'
print adict
print construct(C, adict)

adict = {'arg1':1, 'arg2':2}
print
print '======== test 2 ========'
print adict
print construct(C, adict)

if __name__ == "__main__":
test()
 
G

George Sakkis

Hello,

I wanted to automagically generate an instance of a class from a
dictionary--which might be generated from yaml or json. I came up with this:

(snip)

==

#! /usr/bin/env python

# automagical constructor
def construct(cls, adict):
dflts = cls.__init__.im_func.func_defaults
vnames = cls.__init__.im_func.func_code.co_varnames

argnames = vnames[1:-len(dflts)]
argvals = [adict.pop(n) for n in argnames]

return cls(*argvals, **adict)

def test():

class C(object):
def __init__(self, arg1, arg2, kwa3=3):
self.argsum = arg1 + arg2
self.kwsum = kwa3
def __str__(self):
return "%s & %s" % (self.argsum, self.kwsum)

# now a dict for autmagical generation
adict = {'arg1':1, 'arg2':2, 'kwa3':42}

print '======== test 1 ========'
print adict
print construct(C, adict)

adict = {'arg1':1, 'arg2':2}
print
print '======== test 2 ========'
print adict
print construct(C, adict)

if __name__ == "__main__":
test()

What's the point of this ? You can call C simply by C(**adict). Am I
missing something ?

George
 
J

James Stroud

George said:
Hello,

I wanted to automagically generate an instance of a class from a
dictionary--which might be generated from yaml or json. I came up with this:

(snip)

==

#! /usr/bin/env python

# automagical constructor
def construct(cls, adict):
dflts = cls.__init__.im_func.func_defaults
vnames = cls.__init__.im_func.func_code.co_varnames

argnames = vnames[1:-len(dflts)]
argvals = [adict.pop(n) for n in argnames]

return cls(*argvals, **adict)

def test():

class C(object):
def __init__(self, arg1, arg2, kwa3=3):
self.argsum = arg1 + arg2
self.kwsum = kwa3
def __str__(self):
return "%s & %s" % (self.argsum, self.kwsum)

# now a dict for autmagical generation
adict = {'arg1':1, 'arg2':2, 'kwa3':42}

print '======== test 1 ========'
print adict
print construct(C, adict)

adict = {'arg1':1, 'arg2':2}
print
print '======== test 2 ========'
print adict
print construct(C, adict)

if __name__ == "__main__":
test()

What's the point of this ? You can call C simply by C(**adict). Am I
missing something ?

George

Maybe there is something wrong with my python.

py> class C:
.... def __init__(a, b, c=4):
.... print a,b,c
....
py> C(**{'a':10, 'b':5, 'c':4})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() got multiple values for keyword argument 'a'


James
 
J

James Stroud

George said:
Hello,

I wanted to automagically generate an instance of a class from a
dictionary--which might be generated from yaml or json. I came up with this:

(snip)

==

#! /usr/bin/env python

# automagical constructor
def construct(cls, adict):
dflts = cls.__init__.im_func.func_defaults
vnames = cls.__init__.im_func.func_code.co_varnames

argnames = vnames[1:-len(dflts)]
argvals = [adict.pop(n) for n in argnames]

return cls(*argvals, **adict)

def test():

class C(object):
def __init__(self, arg1, arg2, kwa3=3):
self.argsum = arg1 + arg2
self.kwsum = kwa3
def __str__(self):
return "%s & %s" % (self.argsum, self.kwsum)

# now a dict for autmagical generation
adict = {'arg1':1, 'arg2':2, 'kwa3':42}

print '======== test 1 ========'
print adict
print construct(C, adict)

adict = {'arg1':1, 'arg2':2}
print
print '======== test 2 ========'
print adict
print construct(C, adict)

if __name__ == "__main__":
test()

What's the point of this ? You can call C simply by C(**adict). Am I
missing something ?

George

Never mind. You're right.

py> class C(object):
.... def __init__(self, a, b, c=4):
.... print a,b,c
....
py> C(**adict)
10 5 4
<__main__.C object at 0x762530>


I guess I thought that, were it this easy, it would have been done in pyaml.

James
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,981
Messages
2,570,188
Members
46,733
Latest member
LonaMonzon

Latest Threads

Top