Python - Adding class instance name to a list - python

Each time I instantiate an object of the class, I want to add the instance to a list
example_obj_list = []
class RandomObject:
def __init__(self, some_property):
self.some_property = some_property
x = RandomObject('purple')
y = RandomObject('blue')
z = RandomObject('brown')
How do I add a step to __init__ so that it automatically appends each object to the list?

If you're going to do this within the class, then the list should be a class object:
class RandomObject:
example_obj_list = []
def __init__(self, some_property):
self.property = some_property
# This is accessing the class attribute (not instance attribute)
self.example_obj_list.append(self)
x = RandomObject('purple')
y = RandomObject('blue')
z = RandomObject('brown')
# Because this was defined at the class level, it can be accessed via the class itself.
for obj in RandomObject.example_obj_list:
print(obj.property)
Output:
purple
blue
brown

Related

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.

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

Creating an instance of type(self) dynamically without calling __init__?

This is quite hard to explain. I have a class which should support the method copy_stateonly(). It should return a crippled version of the object which only contains the (copied) data members that I want. I hope this example explains it better:
# everything inherits from this
class SuperBase:
def __init__(self):
self.state_var = 3 # this should be copied into future objects
self.non_state_var = 0 # we don't want to copy this
def copy_stateonly(self):
newobj = # ??????????? create instance without calling __init__
newobj.state_var = self.state_var
return newobj
# some clases inherit from this
class Base(SuperBase):
def __init__(self):
SuperBase.__init__(self)
self.isflying = True # we want to copy this, this is state
self.sprite = "sprites/plane_generic.png" # we must drop this
def copy_stateonly(self):
newobj = SuperBase.copy_stateonly(self)
newobj.isflying = self.isflying
return newobj
class A144fighter(Base):
def __init__(self, teamname): # note required __init__ argument
Base.__init__(self)
self.colors = ["black", "grey"] # we want to copy this, this is state
self.name = teamname # we must drop this
def copy_stateonly(self):
newobj = Base.copy_stateonly(self)
newobj.colors = self.colors[:]
return newobj
plane = A144fighter("team_blue")
plane_state = plane.copy_stateonly() # this should return an A144fighter object with only state_var, flying and colors set.
Python 2.7
I'm not aware of a way to create new instances of classic classes (which is what you used in your example) without calling __init__(). New instances of new-style classes (descendants of object) can be created using
object.__new__(cls)
where cls is the type of object you would like to create.
An alternative is to use copy.copy() for copying, possibly overwriting __getstate__() and __setstate__() to define what should be copied.
Edit: To create a new instance of a classic class cls without calling __init__(), you can use the following hack:
class EmptyClass:
pass
new_instance = EmptyClass()
new_instance.__class__ = cls
new_instance.__dict__.update(whatever)
Remember that every object has a attribute named __class__. If you do <object>.__class__ it, will return that object's class object (if that makes sense). The class object is callable so you can add parentheses to the end to create a new instance of that class.
newobj = self.__class__()
# everything inherits from this
class SuperBase:
def __init__(self):
self.state_var = 3 # this should be copied into future objects
self.non_state_var = 0 # we don't want to copy this
def __getstate__(self):
return { 'state_var' : self.state_var }
def __str__(self):
return self.__class__.__name__ + '(' + str(vars(self)) + ')'
# some clases inherit from this
class Base(SuperBase):
def __init__(self):
SuperBase.__init__(self)
self.isflying = True # we want to copy this, this is state
self.sprite = "sprites/plane_generic.png" # we must drop this
def __getstate__(self):
state = SuperBase.__getstate__(self)
state['isflying'] = self.isflying
return state
class A144fighter(Base):
def __init__(self, teamname): # note required __init__ argument
Base.__init__(self)
self.colors = ["black", "grey"] # we want to copy this, this is state
self.name = teamname # we must drop this
def __getstate__(self):
state = Base.__getstate__(self)
state['colors'] = self.colors[:]
return state
plane = A144fighter("team_blue")
print plane
import copy
print copy.copy(plane)
# or manually:
import types
print types.InstanceType(plane.__class__, plane.__getstate__())

Adding elements to a set , adds elements to all the instances of the object containing this set

Hi
I have created a List of Objects. Each object contains a Set. I want to update the set's contents for all the objects in the list. The code that i wrote to accomplish this is
class Player:
name = ""
cardsInHand = set()
hasBid = False
def __init__(self, name):
self.name = name
class CardDeck:
deck = []
def __init__(self):
for i in range(39) :
if i%10>0 and i%10<9 :
self.deck.append(i)
def dealCards(self,player):
cardIndex = 0
for tempPlayer in player:
for j in range(4): # since want to add four elements at a time
tempPlayer.cardsInHand.add(self.deck.pop(cardIndex))
cardIndex = cardIndex +1
in the main method I am calling the above classes with the following code
players = []
players.append(Player("Player0"))
players.append(Player("Player1"))
players.append(Player("Player2"))
players.append(Player("Player3"))
cards.dealCards(players)
The problem is that dealCards method adds the elements to all the sets of objects. Instead of 4 elements in each object's set, I endup with same 16 elements in each objects's set?
I am new to python, am i doing something wrong ?
You're creating class attributes.
class Player:
def __init__(self, name):
self.name = name
self.cardsInHand = set()
self.hasBid = False
You've defined cardsInHand (as well as name and hasBid) to be class variables instead of instance variables; by defining them in the class body, you're defining them to be variables shared by all instances. If you're familiar with Java, they are essentially like static variables. To make them instance variables, you need to declare them in the __init__ method, like so:
def __init__(self, name):
self.name = name
self.hasBid = False
self.cardsInHand = set()

Categories

Resources