I have a list of class objects that I would like to distribute to other lists as objects and then these lists should be called to provide interaction with the objects within.
The issue that I cannot overcome at the moment is when trying to append the objects with a for loop from the first list to the second one and instead getting the new list populated with the class objects I get their pointers to the memory.
This is currently running on Python 3.x if any difference.
I have seen some cases where the suggestion is to play with __str__ and
__repr__ but I don't come to a solution for my case.
class Robot():
"""Test class"""
def __init__(self, age):
self.age = age
r = Robot(10)
r1 = Robot(15)
mylist1 = [r, r1]
mylist2=[]
for item in mylist1:
mylist2.append(item)
print(mylist2)
I would expect to get something like [r, r1]
This is the result I get instead:
[<__main__.Robot object at 0x000001285CEE33C8>, <__main__.Robot object at 0x000001285CEE3748>]
As pointed by others in comments.In your code at the moment you are getting the expected result as r and r1 are the instances of the class. In case you want to differentiate your instances on the basis of name and want to return the same you can pass name argument and define __repr__ to represent your output when str(instance) is being called. Just giving you a heads up:
class Robot():
"""Test class"""
def __init__(self, age, name):
self.age = age
self.name = name
def __repr__(self):
return self.name
r = Robot(10,'r')
r1 = Robot(15,'r1')
mylist1 = [r, r1]
mylist2 = []
for item in mylist1:
mylist2.append(item)
print(mylist2)
Result:
[r, r1]
Otherway could be to use a dictionary for mapping
class Robot():
"""Test class"""
def __init__(self, age,name):
self.age = age
self.name=name
r = Robot(10,'r')
r1 = Robot(15,'r1')
mylist1 = [r, r1]
d={}
for item in mylist1:
d[item.name]=item
print(d)
Output
{'r': <__main__.Robot instance at 0x0000000010BAD708>, 'r1': <__main__.Robot instance at 0x0000000010BAD148>}
Related
So I am creating some sort of structure where one object with higher hierarchy has some attributes and a list of other objects with lower hierarchy. Is it possible to build a method for the object of lower hierarchy to return the object in which list it is stored to? I am not talking about class inheritance since the two classes are completely different. The code is something like that:
class List_object:
def __init__(self,*elements):
self.list = []
for e in elements:
self.list.append(e)
class Element:
def __init__(self,name)
self.name = name
def get_parent_list():
# do some magic to return the object made in List_object
el = Element("Alpha")
L = List_object(el)
now calling el.get_parent_list() i would like to have it return the object L. Is that even possible? How should the get_parent_list function be defined?
Thanks
class List_object:
def __init__(self,*elements):
self.list = []
for e in elements:
self.list.append(e)
e.parent.append(self)
class Element:
def __init__(self,name):
self.name = name
self.parent= []
def get_parent_list(self):
return self.parent
Very similar to #hr.mousavi answer, he was faster than me, you could do it as follow.
Note: I don't think this way of doing things is very clean.
class List_object:
def __init__(self,*elements):
self.list = []
for e in elements:
e.parent = self
e.parent.append(self)
class Element:
def __init__(self,name, parent=None):
self.name = name
self.parent = parent
def get_parent_list(self):
return self.parent
Example:
el = Element("Alopha")
L = List_object(el)
el.get_parent_list()
Output:
<__main__.List_object at 0x7f88371d5210>
As an attribute to a certain class, I'm instantiating a bunch of objects of another class. My problem is that they have ugly names for memory addresses. How do I give them proper names?
class CaseReader(object):
def __init__(self, path):
cases_paths = glob(path + '//*')
cases_names = os.listdir(path)
self.case = [Case(i) for i in cases_paths]
Upon running:
a = CaseReader(path)
a
Out[4]: <__main__.CaseReader at 0x1c6dfc7fa88>
a.case
Out[5]:
[<__main__.Case at 0x1c6dfc99fc8>,
<__main__.Case at 0x1c6dfc99dc8>,
<__main__.Case at 0x1c6dfcaf3c8>,
<__main__.Case at 0x1c6dfcaf448>,
<__main__.Case at 0x1c6dfcaf208>]
Overwrite the __str__ function in the class definition and print what ever attributes you want to see, when you print the reference of the object.
Sample Code
class A:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
Suppose I have a data structure composed of objects in Python like this:
class Planet:
def __init__(self, name):
self.name = name
self.continents = []
class Continent:
def __init__(self, name):
self.name = name
self.countries = []
class Country:
def __init__(self, name):
self.name = name
self.states = []
class State:
def __init__(self, name):
self.name = name
self.cities = []
class City:
def __init__(self, name):
self.name = name
Now suppose I was to create a function that would be able to take an object and an attribute "path" as parameters and output a list of all the objects that "match" that path. Since I don't really know how to describe very well what I'm thinking of and most likely I'm using the wrong terminology, here is an idea of what it might look like in practice (let's call the function collect, and assume that the data structure is populated with data, with planet being the "root" object of the data structure):
planet = Planet("Earth")
... Code for populating data structure ...
collect(planet, "continents.countries.states.cities")
This function call would return a list of every cities in every state in every country in every continent on the planet. Or if I wanted all the states in the data model I would do:
collect(planet, "continents.countries.states")
Hopefully you get the idea. The problem is that I just have no clue how I would accomplish this. Here's what I've come up with so far:
def collect(obj, attr_path):
attrs = attr_path.split(".")
current_attr = obj
items = []
for attr in attrs:
current_attr = getitem(current_attr, attr)
# Not sure what to do here...
return items
Does anyone know how I can make this work?
If you would like to do a breadth first search:
def bfs(queue, results):
try:
obj, attr_path = queue.pop(0)
except IndexError:
return
if attr_path is None:
results.append(obj)
else:
if '.' in attr_path:
first, rest = attr_path.split('.', maxsplit=1)
else:
first, rest = attr_path, None
children = getattr(obj, first)
for child in children:
queue.append((child, rest))
bfs(queue, results)
def collect(obj, attr_path):
queue = [(obj, attr_path)]
results = []
bfs(queue, results)
return results
Disclaimer: untested
So I've got this class:
class Student(object):
def __init__(self, studentID, name):
self.__studentID = studentID
self.__name = name
def set_studentID(self, value):
self.__studentID = value
def get_name(self):
return self.__name
and running this code:
x = Student
x.set_name(x, input("Name: "))
x.set_studentID(x, len(students))
students.append(copy.deepcopy(x))
x.set_name(x, input("Name: "))
x.set_studentID(x, len(students))
students.append(copy.deepcopy(x))
for i in (students):
print(i.get_name(i))
gives an unexpected output:
For the input:
a
b
the output is:
b
b
The expected output is:
a
b
If you answer please give me a short explanation of why it doesn't work
The reason your code isn't working is because you never instantiate your class, instead, you assign the class object itself to the name x
x = Student
When you really needed
x = Student()
Then you call the methods on the class object, whilst passing the class object itself as the first parameter, thus your getters and setters act on the class object.
Finally, classes are meant to be singletons, and the copy module special cases them. So if x is a class
copy.deepcopy(x) is x
Is always True, thus you never actually make a copy.
As a side note, your class definition looks like it was written by a Java developer using Python for the first time. The Pythonic way to do it is not to use getters and setters use properties, and only when you need to. Also, don't use double-underscores name-mangling unless you actually want that, which in this case, you dont.
The other answer explains why your code doesn't work as you expect it to. Here's how you could rewrite your code in a more pythonic way.
class Student(object):
def __init__(self, studentID, name):
self.studentID = studentID
self.name = name
students = []
name = input("Name: ")
students.append(Student(len(students), name))
name = input("Name: ")
students.append(Student(len(students), name))
for student in students:
print(student.name)
You don't need to write getter and setter methods unless you have to do some special processing.
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()