473,883 Members | 1,683 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

bug in copy.deepcopy or in getattr or in my understanding?

Dear experts,

I got some unexpected behavior in getattr and copy.deepcopy (see
transcript below). I'm not sure if this is actually a bug in
copy.deepcopy or if I'm doing something too magical with getattr.
Comments would be appreciated.

Thanks,
-Emin

######### Transcript follows ############### ###
Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit
(Intel)] on win32
Type "help", "copyright" , "credits" or "license" for more information.
>># THE FOLLOWING BREAKS
class a:
.... def foo(self):
.... print 'hi'
....
>>class b(a):
.... def __init__(self):
.... self.y = getattr(self,'f oo')
....
>>c = b()
import copy
copy.deepcopy (c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "c:\Python25\li b\copy.py", line 162, in deepcopy
y = copier(x, memo)
File "c:\Python25\li b\copy.py", line 291, in _deepcopy_inst
state = deepcopy(state, memo)
File "c:\Python25\li b\copy.py", line 162, in deepcopy
y = copier(x, memo)
File "c:\Python25\li b\copy.py", line 254, in _deepcopy_dict
y[deepcopy(key, memo)] = deepcopy(value, memo)
File "c:\Python25\li b\copy.py", line 189, in deepcopy
y = _reconstruct(x, rv, 1, memo)
File "c:\Python25\li b\copy.py", line 322, in _reconstruct
y = callable(*args)
File "c:\Python25\li b\copy_reg.py", line 92, in __newobj__
return cls.__new__(cls , *args)
TypeError: instancemethod expected at least 2 arguments, got 0
>># THE FOLLOWING WORKS
class b(a):
.... def __init__(self):
.... self.x = self.__class__. __bases__[0].__dict__['foo']
....
>>c=b()
copy.deepcopy (c)
<__main__.b instance at 0x00EADE18>

Jan 4 '07 #1
4 3695
At Thursday 4/1/2007 17:26, Emin wrote:
>I got some unexpected behavior in getattr and copy.deepcopy (see
transcript below). I'm not sure if this is actually a bug in
copy.deepcop y or if I'm doing something too magical with getattr.
Comments would be appreciated.
Both examples are different. #1 stores a *bound* method into an
instance attribute. Bound methods carry a reference to "self", this
creates a cyclic reference that may cause problems to the garbage
collector (and confuses deepcopy, apparently).
#2 uses and *unbound* method and it's the usual way.
>class a:
... def foo(self):
... print 'hi'
...
>class b(a): #1
... def __init__(self):
... self.y = getattr(self,'f oo')
>class b(a): #2
... def __init__(self):
... self.x = self.__class__. __bases__[0].__dict__['foo']
For #2 you can simply say:

class b(a):
x = a.foo

If you have to choose at runtime (a simplified version of your own code):

class b(a):
def __init__(self):
name = select_method_t o_use(..., default="foo")
self.x = getattr(a, name)

You *know* your bases because you wrote them in the class statement
(or use super() instead of playing with __bases__); and getattr works
fine here so you don't need to mess with the __dict__ details.

(Note that #1 was *almost* right, you had to replace self by the base class)
--
Gabriel Genellina
Softlab SRL


_______________ _______________ _______________ _____
Preguntá. Respondé. Descubrí.
Todo lo que querías saber, y lo que ni imaginabas,
está en Yahoo! Respuestas (Beta).
¡Probalo ya!
http://www.yahoo.com.ar/respuestas

Jan 5 '07 #2
Dear Gabriel,

Thank you for your reply. As you guessed, I want to be able to select
the method at runtime as in your final example, but when I tried your
suggestion I got the same error (see below). I think the problem is
that getattr is donig something different than in my example where I
explicitly get it from the dict (see the very end of the transcript
below):
--------------------------- Transcript Follows
----------------------------------------------------------

Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit
(Intel)] on win32
Type "help", "copyright" , "credits" or "license" for more information.
>># The following shows that using getattr to grab a method is
# incompatible with copy.deepcopy
class a:
.... def foo(self): pass
....
>>class b(a):
.... def __init__(self):
.... self.x = getattr(a,'foo' )
....
>>import copy
c=b()
copy.deepcopy (c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "c:\Python25\li b\copy.py", line 162, in deepcopy
y = copier(x, memo)
File "c:\Python25\li b\copy.py", line 291, in _deepcopy_inst
state = deepcopy(state, memo)
File "c:\Python25\li b\copy.py", line 162, in deepcopy
y = copier(x, memo)
File "c:\Python25\li b\copy.py", line 254, in _deepcopy_dict
y[deepcopy(key, memo)] = deepcopy(value, memo)
File "c:\Python25\li b\copy.py", line 189, in deepcopy
y = _reconstruct(x, rv, 1, memo)
File "c:\Python25\li b\copy.py", line 322, in _reconstruct
y = callable(*args)
File "c:\Python25\li b\copy_reg.py", line 92, in __newobj__
return cls.__new__(cls , *args)
TypeError: instancemethod expected at least 2 arguments, got 0
>>>
# The following shows that getattr is doing something different
# than looking in the __dict__ of base classes
b.__bases__[0].__dict__['foo']
<function foo at 0x009F0CF0>
>>getattr(a,'fo o')
<unbound method a.foo>
>>>

On Jan 4, 10:08 pm, Gabriel Genellina <gagsl...@yahoo .com.arwrote:
At Thursday 4/1/2007 17:26, Emin wrote:
I got some unexpected behavior in getattr and copy.deepcopy (see
transcript below). I'm not sure if this is actually a bug in
copy.deepcopy or if I'm doing something too magical with getattr.
Comments would be appreciated.Bot h examples are different. #1 stores a *bound* method into an
instance attribute. Bound methods carry a reference to "self", this
creates a cyclic reference that may cause problems to the garbage
collector (and confuses deepcopy, apparently).
#2 uses and *unbound* method and it's the usual way.
>>class a:
... def foo(self):
... print 'hi'
...
>>class b(a): #1
... def __init__(self):
... self.y = getattr(self,'f oo')
>>class b(a): #2
... def __init__(self):
... self.x = self.__class__. __bases__[0].__dict__['foo']For #2 you can simply say:

class b(a):
x = a.foo

If you have to choose at runtime (a simplified version of your own code):

class b(a):
def __init__(self):
name = select_method_t o_use(..., default="foo")
self.x = getattr(a, name)

You *know* your bases because you wrote them in the class statement
(or use super() instead of playing with __bases__); and getattr works
fine here so you don't need to mess with the __dict__ details.

(Note that #1 was *almost* right, you had to replace self by the base class)

--
Gabriel Genellina
Softlab SRL

_______________ _______________ _______________ _____
Preguntá. Respondé. Descubrí.
Todo lo que querías saber, y lo que ni imaginabas,
está en Yahoo! Respuestas (Beta).
¡Probalo ya!http://www.yahoo.com.ar/respuestas
Jan 5 '07 #3
Emin wrote:
Thank you for your reply. As you guessed, I want to be able to select
the method at runtime as in your final example, but when I tried your
suggestion I got the same error (see below). I think the problem is
that getattr is donig something different than in my example where I
explicitly get it from the dict (see the very end of the transcript
below):
This has nothing to do with getattr(). You currently can deep-copy
functions, but neither bound nor unbound methods:
>>import copy
def check(obj):
.... try:
.... copy.deepcopy(o bj)
.... except:
.... return "FAILED"
.... return "OK"
....
>>def function(*args) : pass
....
>>class A:
.... method = function
....
>>check(functio n), check(A.method) , check(A().metho d)
('OK', 'FAILED', 'FAILED')

Whether this a bug or a sensible limitation I don't know.

Peter
Jan 5 '07 #4
At Friday 5/1/2007 11:01, Emin wrote:
>Thank you for your reply. As you guessed, I want to be able to select
the method at runtime as in your final example, but when I tried your
suggestion I got the same error (see below). I think the problem is
that getattr is donig something different than in my example where I
explicitly get it from the dict (see the very end of the transcript
below):
I've modified it as follows:
- using new.instancemet hod to create the dynamic method
- copy uses __getstate__ to determine what is needed to copy/save.
Assuming that self.x is derived from other attributes, it's not
actually needed in the saved state, and can be omited.
- __setstate__ does the inverse: after reconstructing the object
state, sets self.x to the right value

=== cut ===
import new

class A:
def foo(self, arg):
print "in foo, self=%r arg=%r" % (self, arg)

class B(A):
def __init__(self):
self.update_dyn amic_methods()

def update_dynamic_ methods(self):
"Should assign the dynamic methods based on other attributes"
self.x = new.instancemet hod(getattr(A," foo"),self,B)

def __getstate__(se lf):
state = self.__dict__.c opy()
if 'x' in state: del state['x']
return state

def __setstate__(se lf, state):
self.__dict__.u pdate(state)
self.update_dyn amic_methods()

b=B()
b.something = 'something'
b.foo(123)
b.x(123)

import copy
b2 = copy.deepcopy(b )
assert b2.something==' something'
b2.foo(123)
b2.x(123)
=== cut ===

--
Gabriel Genellina
Softlab SRL


_______________ _______________ _______________ _____
Preguntá. Respondé. Descubrí.
Todo lo que querías saber, y lo que ni imaginabas,
está en Yahoo! Respuestas (Beta).
¡Probalo ya!
http://www.yahoo.com.ar/respuestas

Jan 5 '07 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
35785
by: Andreas Kuntzagk | last post by:
Hi, There are three ways to (shallow)copy a list l I'm aware of: >>> l2=list(l) >>> l2=l >>> l2.copy.copy(l) Are there any differences? Are there more (reasonable) ways? I think the first is the most pythonic, second looks more like this other
2
2250
by: Nick Jacobson | last post by:
This question is with regard to the * operator as used for sequence concatenation. There's the well-known gotcha: a = ] b = a*3 b = 4 print b
6
2235
by: Alexander Zatvornitskiy | last post by:
Hello! I have trouble with copy/deepcopy. It seems, I just don't understand something. Please explain where things goes wrong and how to do it the right way. I have one class: class Distribution: __gr_on_transp=dict() __ostatok_m=dict()
0
1709
by: Joshua Ginsberg | last post by:
Howdy -- I have a class that has an attribute that is a dictionary that contains an object that has a kword argument that is a lambda. Confused yet? Simplified example: import copy class Foo: def __init__(self, fn=None):
2
12360
by: Alex | last post by:
Entering the following in the Python shell yields >>> help(dict.copy) Help on method_descriptor: copy(...) D.copy() -> a shallow copy of D >>>
4
1420
by: KraftDiner | last post by:
I'm having trouble getting a copy of and object... (a deep copy) I'm writing a method that creates a mirror image of an object (on screen) In order to do this i need to get a copy of the object and then modify some of its attributes. I tried: objs = myListOfObjects
28
7440
by: robert | last post by:
In very rare cases a program crashes (hard to reproduce) : * several threads work on an object tree with dict's etc. in it. Items are added, deleted, iteration over .keys() ... ). The threads are "good" in such terms, that this core data structure is changed only by atomic operations, so that the data structure is always consistent regarding the application. Only the change-operations on the dicts and lists itself seem to cause problems...
0
1120
bartonc
by: bartonc | last post by:
I was playing around with the Simple Metaclassing thread and found something odd: >>> class aClass: ... classVar1 = 'hello' ... def __init__(self, arg1): ... self.instVar1 = arg1 ... >>> anInstance = aClass('world') >>> import copy >>> bClass = copy.deepcopy(anInstance.__class__) >>> bClass
3
1585
by: yoma | last post by:
python version 2.5 in module copy we all know that copy have two method: copy() and deepcopy(). and the explain is - A shallow copy constructs a new compound object and then (to the extent possible) inserts *the same objects* into it that the original contains. - A deep copy constructs a new compound object and then, recursively, inserts *copies* into it of the objects found in the original.
0
10742
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10847
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9572
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7971
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7125
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5797
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4611
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4218
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3232
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.