To simplify/narrow down this issue quite a bit, here's the problem:
#Problem
def testDct():
result = {}
l = [1, 2, 3]
for item in l:
result[str(item)] = type(str(item), (), {'test': lambda self: item})
return result
print testDct()['1']().test()
print testDct()['2']().test()
#This, however, gives me what I'd expect:
def testDct():
l = [1, 2, 3]
for item in l:
yield type(str(item), (), {'test': lambda self: item})
classes = []
for X in testDct():
print X().test()
classes.append(X)
#right until here
print classes[0]().test()
print classes[1]().test()
On Fri, Jan 14, 2011 at 10:43 PM, John Patrick <[email protected]> wrote:
> Hey Paul - I did leave out the last line by mistake, which is just 'return
> result', as you guessed. Thanks a bunch for checking it out. Here is a
> full chunk of code that can be run without modification:
>
>
> import logging, inspect
> import pymel.core as pm
>
> logger = logging.getLogger(__name__)
>
> logger.setLevel(logging.DEBUG)
>
>
> def make_square_crv():
>
> pm.curve(p=[(1, 0, 1), (-1, 0, 1), (-1, 0, -1), (1, 0, -1), (1, 0, 1)],
> k=[0, 1, 2, 3, 4], d=1)
>
>
> def make_circle_crv():
>
> pm.circle(nr=[0, 1, 0], sw=360, d=3, s=12)[0]
>
>
> class Dummy(object): pass
>
>
> def genShapeClasses():
>
> """
>
> A factory that generates shape creation classes
>
> @return: a dict of {'className': class}
>
> """
>
> result = {}
>
> fncs = inspect.getmembers(sys.modules[__name__], inspect.isfunction)
>
> fncs = [(name, fnc) for name, fnc in fncs if name.startswith('make_')]
>
>
> for fName, fnc in fncs:
>
> tmp, sName, sType = fName.split('_')
>
> msg = "Generating Shape Class:\n"
>
> msg += "name: %s\n" % sName
>
> msg += "shapeType: %s\n" % sType
>
> msg += "func: %s\n" % fnc.__name__
>
> msg += "func obj: %s\n" % str(fnc)
>
> msg += "fnc id: %s\n" % str(id(fnc))
>
> logger.debug(msg)
>
>
> name = sName.capitalize() + sType.capitalize() + 'Shape'
>
> assignFnc = lambda self: fnc()
>
> result[name] = type(name, (Dummy,), {'shapeFunc':assignFnc})
>
>
> return result
>
>
> #The objects end up being the same
>
> classes = genShapeClasses()
>
> print id(classes['CircleCrvShape'].shapeFunc)
>
> print id(classes['SquareCrvShape'].shapeFunc)
>
>
> I'm still stumped. This is the first time I've needed a class factory, and
> it sure is making me feel inept...
>
>
> On Fri, Jan 14, 2011 at 9:28 PM, Paul Molodowitch <[email protected]>wrote:
>
>> The problem must be somewhere in the portion of the code you're leaving
>> out... and you must be leaving out SOMETHING, since the genShapeClasses
>> function you've given doesn't return a value. I tried running the code you
>> gave (simply adding a 'return result' statement, and some dummy make_*
>> functions), and it worked fine. (ie, id(classes['TextCrvShape'].shapeFunc)
>> != print id(classes['SquareCrvShape'].shapeFunc)
>>
>> - Paul
>>
>> On Fri, Jan 14, 2011 at 6:09 PM, JP <[email protected]> wrote:
>>
>>> It might be worth mentioning that i was originally doing this inside
>>> the factory loop with the same issue:
>>>
>>> name = sName.capitalize() + sType.capitalize() + 'Shape'
>>> ##This is really what needs to happen anyways to since the
>>> method will be passed a 'self' arg
>>> assignmentFunc = lambda self: fnc()
>>> result[name] = type(name, (Shape,),
>>> {'shapeFunc':assignmentFunc})
>>>
>>> In the end, I end up with something like this:
>>> >>> id(result['class1']) != id(result['class2'])
>>> True
>>> >>> id(result['Class1'].shapeFunc) == id(result['Class2'].shapeFunc)
>>> True
>>>
>>> hrm...
>>>
>>> On Jan 14, 5:15 pm, John Patrick <[email protected]> wrote:
>>> > Hey all,
>>> >
>>> > I've been looking at this for quite a while, and I still can't figure
>>> it
>>> > out. I'm trying to write a class factory that generates 'Shape'
>>> subclasses,
>>> > each of which has a different 'shapeFunc' attribute that creates a
>>> shape.
>>> > The problem I'm running into is that all the classes come out with the
>>> same
>>> > function - the last one in the list. So it looks like I'm somehow
>>> creating
>>> > a reference to the same object in all the classes...but I'm not sure
>>> why.
>>> >
>>> > I have a number of 'make_someShapeName_crv' functions in the same
>>> module,
>>> > and I'm trying to get a dictionary of all the classes like this:
>>> >
>>> > def genShapeClasses():
>>> > """
>>> > A factory that generates shape creation classes
>>> >
>>> > @return: a dict of {'className': class}
>>> > """
>>> > result = {}
>>> >
>>> > fncs = inspect.getmembers(sys.modules[__name__],
>>> inspect.isfunction)
>>> > fncs = [(name, fnc) for name, fnc in fncs if
>>> name.startswith('make_')]
>>> >
>>> > for fName, fnc in fncs:
>>> > tmp, sName, sType = fName.split('_')
>>> >
>>> > #debugging log
>>> > msg = "Generating Shape Class:\n"
>>> > msg += "name: %s\n" % sName
>>> > msg += "shapeType: %s\n" % sType
>>> > msg += "func: %s\n" % fnc.__name__
>>> > msg += "func obj: %s\n" % str(fnc)
>>> > msg += "fnc id: %s\n" % str(id(fnc))
>>> > logger.debug(msg)
>>> >
>>> > name = sName.capitalize() + sType.capitalize() + 'Shape'
>>> >
>>> > result[name] = type(name, (Shape,), {'shapeFunc':fnc})
>>> >
>>> > Here are the last two log blocks:
>>> >
>>> > *# RigIt.lib.Shapes : Generating Shape Class:*
>>> >
>>> > *name: square*
>>> >
>>> > *shapeType: crv*
>>> >
>>> > *func: make_square_crv*
>>> >
>>> > *func obj: <function make_square_crv at 0x000000001827EF98>*
>>> >
>>> > *fnc id: 405270424*
>>> >
>>> > * # *
>>> >
>>> > *# RigIt.lib.Shapes : Generating Shape Class:*
>>> >
>>> > *name: text*
>>> >
>>> > *shapeType: crv*
>>> >
>>> > *func: make_text_crv*
>>> >
>>> > *func obj: <function make_text_crv at 0x000000001827E6D8>*
>>> >
>>> > *fnc id: 405268184*
>>> >
>>> > * #*
>>> >
>>> > Finally, here is the problem I'm having:
>>> >
>>> > >>>classes = Shapes.genShapeClasses()
>>> > >>>print id(classes['TextCrvShape'].shapeFunc)
>>> >
>>> > *478555520*
>>> >
>>> > >>>print id(classes['SquareCrvShape'].shapeFunc)
>>> >
>>> > *478555520*
>>> >
>>> > I've tried a shotgun approach and put a deepcopy() just about
>>> everywhere to
>>> > no avail. The thing that's stumping me is that i have a new object in
>>> > memory when the loop starts - but somehow in the process of assigning
>>> it to
>>> > the new class, they all end up referencing the same object. When I
>>> id() the
>>> > class itself, they are different Class objects.
>>> >
>>> > Any Pythonistas out there that could offer a hand?
>>> >
>>> > Thanks!
>>> >
>>> > -JP
>>> > --
>>> > John Patrick
>>> > 404-242-2675
>>> > [email protected]http://www.canyourigit.com
>>>
>>> --
>>> http://groups.google.com/group/python_inside_maya
>>>
>>
>> --
>> http://groups.google.com/group/python_inside_maya
>>
>
>
>
> --
> John Patrick
> 404-242-2675
> [email protected]
> http://www.canyourigit.com
>
--
John Patrick
404-242-2675
[email protected]
http://www.canyourigit.com
--
http://groups.google.com/group/python_inside_maya