Saving class instance state from inside class - python

I have read over the answers on Saving an Object (Data persistence) but it isn't really what I was looking for. I don't want to save the class state in a file.
Here's what I'm trying to implement:
class A():
def some_function(self):
# save class state here - (*)
if something:
#make changes to class attributes
if something_again():
# revert back to class state at - (*)
How can I save the class state at a particular point?

You could implement something like this
class A():
def __init__(self):
self.prev_state = dict()
self.field_1 = 1
self.field_2 = 2
self.save_fields = (
"field_1",
"field_2"
)
self.save_state()
def save_state(self):
for f in self.save_fields:
self.prev_state[f] = getattr(self, f)
def restore_state(self):
for f in self.save_fields:
setattr(self, f, self.prev_state[f])
a = A()
a.field_1 += 1
print(a.field_1) # 2
a.restore_state()
print(a.field_1) # 1

Related

generic Class in Python

I want to do a generic class in Python with one method
This class does not generate its instances
Some attributes are set in the body of the class
Method of this class uses the set attributes and in the generated classes the output of this method depends on these attributes
Method has only one input
I know that without metaclasses will not do, but I do not know how to apply them :)
something like this:
class GenericClass:
attr_a = ''
attr_b = ''
def count(text):
return len(text)/attr_a + attr_b
class A(GenericClass):
attr_a = 2
attr_b = 1
text = "Hello, I'm under the water"
print(A.count(text))
# 14
Defining count as a class method would make that work:
#classmethod
def count(cls, text):
return len(text) / cls.attr_a + cls.attr_b
class GenericClass:
def _count(text, a, b):
return len(text)/a + b
class A(GenericClass):
attr_a = 2
attr_b = 1
def count(text):
return GenericClass._count(text, A.attr_a, A.attr_b)
text = "Hello, I'm under the water"
print(A.count(text))

Python 2.7, defining a base class with attributes, id with init constructor

I am trying to define a generic base class Geometry, with a unique id for each object starting at 0. I am using init as the method.
I am trying to create a generic base class named Geometry that I will use to organize geometry objects like point or polygon and containing an id attribute starting at 0. I know all of the objects should have a unique ID. I'm using the constructor (__init__) when creating a new Geometry object (integer). And would like for the base class to automatically assign the ID of the Geometry object.
Current code:
class Geometry(object):
def__init__(self,id):
self.id = id
I think I am on the right path but I am not positive. Should I have id = 0 above def__init__(self,id)?
Any guidance will be appreciated.
If the first line of your class is id = 0 then it becomes a class attribute and is shared by all instances of Geometry and all of its children.
Here is an example of using a class scoped variable:
#!/usr/bin/env python2
class Geometry(object):
# ident is a class scoped variable, better known as Geometry.ident
ident = 0
def __init__(self):
self.ident = Geometry.ident
Geometry.ident += 1
class Circle(Geometry):
def __init__(self, radius):
Geometry.__init__(self)
self.radius = radius
def __str__(self):
return '<Circle ident={}, {}>'.format(self.ident, self.radius)
class Equilateral(Geometry):
def __init__(self, sides, length):
# super is another way to call Geometry.__init__() without
# needing the name of the parent class
super(Equilateral, self).__init__()
self.sides = sides
self.length = length
def __str__(self):
return '<Equilateral ident={}, {}, {}>'.format(self.ident,
self.sides, self.length)
# test that ident gets incremented between calls to Geometry.__init__()
c = Circle(12)
e = Equilateral(3, 8)
f = Circle(11)
print c
assert c.ident == 0
print e
assert e.ident == 1
print f
assert f.ident == 2
Something feels wrong about this, though I've not put my finger on it.
class Geometry(object):
def __init__(self,id=0):
self.id = id
__init__ in python is invoked when you create an instance of that class
circle = Geometry(1)

python using __init__ vs just defining variables in class - any difference?

I'm new to Python - and just trying to better understand the logic behind certain things.
Why would I write this way (default variables are in __init__):
class Dawg:
def __init__(self):
self.previousWord = ""
self.root = DawgNode()
self.uncheckedNodes = []
self.minimizedNodes = {}
def insert( self, word ):
#...
def finish( self ):
#...
Instead of this:
class Dawg:
previousWord = ""
root = DawgNode()
uncheckedNodes = []
minimizedNodes = {}
def insert( self, word ):
#...
def finish( self ):
#...
I mean - why do I need to use __init__ -> if I can just as easily add default variables to a class directly?
When you create variables in the Class, then they are Class variables (They are common to all the objects of the class), when you initialize the variables in __init__ with self.variable_name = value then they are created per instance and called instance variables.
For example,
class TestClass(object):
variable = 1
var_1, var_2 = TestClass(), TestClass()
print var_1.variable is var_2.variable
# True
print TestClass.variable is var_1.variable
# True
Since variable is a class variable, the is operator evaluates to True. But, in case of instance variables,
class TestClass(object):
def __init__(self, value):
self.variable = value
var_1, var_2 = TestClass(1), TestClass(2)
print var_1.variable is var_2.variable
# False
print TestClass.variable is var_1.variable
# AttributeError: type object 'TestClass' has no attribute 'variable'
And you cannot access an instance variable, with just the class name.
When you write this:
class Dawg:
previousWord = ""
root = DawgNode()
uncheckedNodes = []
minimizedNodes = {}
Those are not instance variables, they're class variables (meaning: the same variables with the same values are shared between all instances of the class.) On the other hand, this:
class Dawg:
def __init__(self):
self.previousWord = ""
self.root = DawgNode()
self.uncheckedNodes = []
self.minimizedNodes = {}
... Is declaring instance variables, meaning: the values are different for each instance of the class. As you see, each snippet means a completely different thing, and you have to pick the one that is appropriate for you. Hint: most of the time you're interested in instance variables, because class variables define a kind of shared global state for your objects, which is error prone.

How to deal with python inheritance with methods that have same names and depend each other?

I try to maintain a class. The basic program struct I hoped shows below.
class FooFather():
def __init__(self):
self.meta=0
def add(self):
self.meta+=1
def act(self):
self.add()
class FooChild(FooFather):
def __init__(self):
FooFather.__init__(self)
def add(self):
self.meta+=2
def act(self):
FooFather.act(self)
The result shows below.
foo=FooChild()
foo.act()
print(foo.meta)
=>2 //not 1 I want to have
I understand the mechanism. The child class overwrites the methods of father (both add and act). How can I overwrite a method meanwhile I can keep the relation between original methods?
self refers to the current instance. So when FooFather.act() calls self.add() it is referring to the add method of the current instance, which is a FooChild() instance. Therefore FooChild.add(self) is called.
If you want FooFather.act() to call FooFather.add() instead, you need to have FooFather.act() do so explicitly: i.e., FooFather.add(self)
You can use pseudo privates, see https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references
class FooFather:
def __init__(self):
self.meta = 0
def __add(self):
print self.meta, '-->',
self.meta += 1
print self.meta
def act(self):
self.__add()
class FooChild(FooFather):
def __add(self):
print self.meta, '==>',
self.meta += 2
print self.meta
def act2(self):
FooFather.act(self)
def act3(self):
self.__add()
>>> c = FooChild()
>>> c.act()
0 --> 1
>>> c.act2()
1 --> 2
>>> c.act3()
2 ==> 4
Not sure what you want really based on your question, but I'm guessing something like this, where act calls the superclass' add (using python 2.7 syntax):
class FooFather(object):
def __init__(self):
self.meta=0
def add(self):
self.meta+=1
def act(self):
self.add()
class FooChild(FooFather):
def __init__(self):
super(FooChild, self).__init__()
def add(self):
self.meta+=2
def act(self):
super(FooChild, self).add()

Creating an object with a reference to the object that created it

I have a program where an object creates another object. However, the second object that gets created needs to be able to access the first. Is this possible?
EG (pseudocode)
class parentObject():
parentVar = 1
# Create Child
x = childObject()
class childObject():
#Assign Var to the Var of the childs parent
childVar = parent.parentVar
>>> x.childVar = 1
is there a straitforward way to do this?
UPDATE:
I don't want to inheret the class, I need to be able to access the actual object that created it, as each object created from that class has different values.
Why not inherit the class?
class parentObject():
parentVar = 1
class childObject(parentObject):
childVar = parentObject.parentVar
>>> x = childObject()
>>> print(x.childVar)
1
If you are going to have different instances of the class, you should do it as this instead:
class parentObject(object):
def __init__(self):
self.parentVar = 1
class childObject(parentObject):
def __init__(self):
super(childObject, self).__init__()
self.childVar = self.parentVar
>>> x = childObject()
>>> print(x.childVar)
1
If you want a reference to the "parent" class, but inheritance is illogical, consider sending self in to the constructor:
class Room:
def __init__(self, name):
self.name = name
self.furniture = []
def add_chair(self):
self.furniture.append(Chair(self))
def __str__(self):
return '{} with {}'.format(self.name, self.furniture)
class Chair:
def __init__(self, room):
self.room = room
def __str__(self):
return 'Chair in {}'.format(self.room.name)
r = Room('Kitchen')
r.add_chair()
r.add_chair()
print r
print r.furniture[0]
Output:
Kitchen with [<__main__.Chair instance at 0x01F45F58>, <__main__.Chair instance at 0x01F45F80>]
Chair in Kitchen

Categories

Resources