What I am trying to do is simple, I have a huge dict like so:
class a():
m=0
def __init__(self, m):
self.m = m
def __int__(self):
return self.m
b=a(4)
c=a(6523)
d=a(741)
e=a(84521111)
dict={0:b,1:c,2:e,3:d,4:None,5:None,6:None}
for ele in dict.values():
if ele is not None:
print int(ele)
else:
print "None"
The real one has 4096 elements. Basically, when I decided to kill the object c, I do:
dict[1]=None
Because I don't want to remove the key number 1, and it is working fine, but the object if still alive somewhere and with 4096 objects it can be a problem on my small embedded system. I can check the alive objects with:
import gc
for obj in gc.get_objects():
if isinstance(obj, a):
print obj
Output:
<main.a instance at 0xb749c96c>
<main.a instance at 0xb749caac>
<main.a instance at 0xb749c9cc>
<main.a instance at 0xb749cc0c>
So, how can I delete these object definitely from my memory ?
Nota: del dict[1] doesn't work because it is removed the key as well, same for pop().
I am using Python 2.7, still ...
Ensure you're accounting for the fact that they were in memory before you added them to the dictionary.
>>> b=a(4)
>>> c=a(6523)
>>> d=a(741)
>>> e=a(84521111)
>>>
>>> dict={0:b,1:c,2:e,3:d,4:None,5:None,6:None}
>>>
>>> for obj in gc.get_objects():
... if isinstance(obj, a):
... print obj
...
<__main__.a instance at 0x7f4078a34dd0>
<__main__.a instance at 0x7f4078a34d88>
<__main__.a instance at 0x7f4078a34d40>
<__main__.a instance at 0x7f4078a34cf8>
Now delete the originals:
>>> del(b)
>>> del(c)
>>> del(d)
>>> del(e)
>>>
>>> for obj in gc.get_objects():
... if isinstance(obj, a):
... print obj
...
<__main__.a instance at 0x7f4078a34dd0>
<__main__.a instance at 0x7f4078a34d88>
<__main__.a instance at 0x7f4078a34d40>
<__main__.a instance at 0x7f4078a34cf8>
They're still in memory because they're in the dictionary. Now remove them from the dictionary:
>>> dict[3] = None
>>> dict[2] = None
>>>
>>> for obj in gc.get_objects():
... if isinstance(obj, a):
... print obj
...
<__main__.a instance at 0x7f4078a34dd0>
<__main__.a instance at 0x7f4078a34d88>
>>>
We just lost 2 objects with our delete.
Related
Given the class test, why it is not possible to instantiate it by calling one of its methods along with the constructor?
class test:
def __init__(self, a):
self.a = a
def print_a(self):
print(self.a)
Here is an example:
>>> obj = test("Hello").print_a() # Prints the desired output.
Hello
>>> obj
>>> print(obj) # But the object does not exist.
None
>>> obj = test("Hello") # It obviously works when doing it separately.
>>> obj
<__main__.test object at 0x7f537fea3940>
>>> obj.print_a()
Hello
Why is it not possible to chain a method call with the constructor call?
This was implemented in python3.
You are assigning obj to the return value of the function print_a (which is None as it has no return). The actual test object was never stored and is therefore no longer in scope when you try to print it.
I have two classes, B and C.
I want to instantiate B with C reference and C with B reference.
I could add a setter method, but was wondering if I can do it in the __init__ stage or any other elegant ways
It is not possible within __init__ directly due to a chicken and egg situation. However, it is possible in one assignment statement:
>>> class A:
... pass
...
>>> class B:
... pass
...
>>> a, b = b.a, a.b = A(), B()
>>> a.b is b
True
>>> b.a is a
True
This relies on the fact that Python evaluates assignments left to right.
It is not thread safe; if you need to guarantee that the references exist in a threaded application then you'll want to use a mutex to handle the possible race conditions. The GIL works at the opcode level, which is a finer-grained resolution than lines of Python code.
You could do it in __init__ if you make one of the class initializers take an object of the other class:
>>> class B:
... def __init__(self):
... self.c = C(self)
...
>>> class C:
... def __init__(self, b):
... self.b = b
...
>>> b = B()
>>> c = b.c
>>> b.c
<__main__.C object at 0x107a4f6d8>
>>> b.c.b.c
<__main__.C object at 0x107a4f6d8>
>>> b.c.b.c.b
<__main__.B object at 0x107a60e80>
>>> b
<__main__.B object at 0x107a60e80>
>>> c
<__main__.C object at 0x107a4f6d8>
>>> c.b
<__main__.B object at 0x107a60e80>
>>> b.c
<__main__.C object at 0x107a4f6d8>
>>> b.c.b.c
<__main__.C object at 0x107a4f6d8>
>>> c.b.c.b
<__main__.B object at 0x107a60e80>
Or even without any arguments to __init__:
>>> class B:
... def __init__(self):
... self.c = C()
... self.c.b = self
...
>>> class C:
... pass
...
>>> b = B()
>>> c = b.c
>>> b
<__main__.B object at 0x10835c048>
>>> c
<__main__.C object at 0x1085ccac8>
>>> b.c
<__main__.C object at 0x1085ccac8>
>>> c.b
<__main__.B object at 0x10835c048>
>>> b.c.b.c.b
<__main__.B object at 0x10835c048>
Reading the documentation, I understood that copy.deepcopy(obj) copies recursively any other object inside this one, but when I run:
>>> import copy
>>> class SomeObject:
... a=1
... b={1:1,2:2}
...
>>> o1=SomeObject()
>>> o2=copy.deepcopy(o1)
>>> id(o1)
140041523635624
>>> id(o2)
140041523635912
>>> id(o1.b)
30087968
>>> id(o2.b)
30087968
It does not seem to be copying the dictionary inside 'o1'. Can anyone tell me if I am doing something wrong, or how can I get a copy of the dictionary inside the object?
Thanks
Deepcopy only copies instance attributes. Your b attribute is a class attribute, instead.
Even if you did not create a copy but a new instance of SomeObject manually, b would still be shared:
>>> class SomeObject:
... a=1
... b={1:1,2:2}
...
>>> so1 = SomeObject()
>>> so2 = SomeObject()
>>> so1.b is so2.b
True
>>> so1.b is SomeObject.b
True
Make b an instance attribute:
>>> import copy
>>> class SomeObject:
... a = 1
... def __init__(self):
... self.b = {1: 1, 2: 2}
...
>>> so1 = SomeObject()
>>> so2 = copy.deepcopy(so1)
>>> so1.b is so2.b
False
I write a python file like :
class A(object):
def update(self, str):
pass
def say(self, str):
print "I update: " + str
def fun(obj, str):
obj.say(str)
a = A()
import types
setattr(A, "update", types.MethodType(fun, None, A))
a.update("hello")
b = A()
b.update("world?")
It change behave of class, the object b have been changed. but, I want to only change object a.
How to change Method of Object in python?
Here is a way to do it:
a.update = lambda x: fun(a, x)
You are setting the class method, while you want to set only the method bound to some instance.
>>> class MyClass(object):
... def a(self): pass
...
>>> MyClass.a = lambda x: x
>>> MyClass.a
<unbound method MyClass.<lambda>>
>>> a = MyClass()
>>> a.a
<bound method MyClass.<lambda> of <__main__.MyClass object at 0x1d7fed0>>
Changing the a method at class level changes also the a methods of all instances.
>>> class MyClass(object):
... def a(self): pass
...
>>> b = MyClass()
>>> b.a = lambda x: x
>>> MyClass.a
<unbound method MyClass.a>
>>> b.a
<function <lambda> at 0x1d88938>
>>> c = MyClass()
>>> c.a
<bound method MyClass.a of <__main__.MyClass object at 0x1d8d110>>
Changing the a method of an instance does not change the method of the class or other instances.
Using python, one can set an attribute of a instance via either of the two methods below:
>>> class Foo(object):
pass
>>> a = Foo()
>>> a.x = 1
>>> a.x
1
>>> setattr(a, 'b', 2)
>>> a.b
2
One can also assign properties via the property decorator.
>>> class Bar(object):
#property
def x(self):
return 0
>>> a = Bar()
>>> a.x
0
My question is, how can I assign a property to an instance?
My intuition was to try something like this...
>>> class Doo(object):
pass
>>> a = Doo()
>>> def k():
return 0
>>> a.m = property(k)
>>> a.m
<property object at 0x0380F540>
... but, I get this weird property object. Similar experimentation yielded similar results. My guess is that properties are more closely related to classes than instances in some respect, but I don't know the inner workings well enough to understand what's going on here.
It is possible to dynamically add properties to a class after it's already created:
class Bar(object):
def x(self):
return 0
setattr(Bar, 'x', property(Bar.x))
print Bar.x
# <property object at 0x04D37270>
print Bar().x
# 0
However, you can't set a property on an instance, only on a class. You can use an instance to do it:
class Bar(object):
def x(self):
return 0
bar = Bar()
setattr(bar.__class__, 'x', property(bar.__class__.x))
print Bar.x
# <property object at 0x04D306F0>
print bar.x
# 0
See How to add property to a class dynamically? for more information.
Properties use descriptors which only work on classes and thus
for all instances. But you could use a combination of a descriptor on
a class that would consult a per-instance function.
>>> class Foo(object):
... #property
... def x(self):
... if 'x' in self.__dict__:
... return self.__dict__['x'](self)
...
>>> a = Foo()
>>> def k(self):
... return 0
...
>>> a.__dict__['x'] = k
>>> a.x
0
You can assign the property directly to the class object:
>>> class Foo(object):
pass
>>> a = Foo()
>>> a.__class__
__main__.Foo
>>> setattr(a.__class__, 'm', property(lambda self: 0))
>>> a.m
0
>>> a.m = 24
AttributeError: can't set attribute
Here we have taken #agf's solution and used a lambda function to define the class property.
class A(object):
pass
a = A()
a.__class__.f = property(lambda self: 57)
a.f # 57
The following post provides more context: https://crosscompute.com/n/jAbsB6OIm6oCCJX9PBIbY5FECFKCClyV/_/Assign%20a%20class%20property%20to%20an%20instance