I have an list of objects called character like that:
characters=[character(0,0,20,20,keys1),character(50,50,50,50,keys2),character(200,200,100,20,keys1)]
where character class is defined as:
class character():
def __init__(self,x,y,w,h,keys=keys1):
self.x = x
self.y = y
self.w = w
self.h = h
self.keys = keys
self.vel = 200 /math.sqrt(self.w*self.h)
self.crashed=False
# I need an list to use here in a function of my "character" class
# my list must have all the elements in my initial list but self
what I mean is like
characters[0].myFunction() must have a list of [characters[1],characters[2]]
which is characters =[character(50,50,50,50,keys2),character(200,200,100,20,keys1)]
you have to pass as an argument to your .myFunction the full list to know from which list to exclude/filter self:
class character():
def __init__(self,x,y,w,h,keys=keys1):
self.x = x
self.y = y
self.w = w
self.h = h
self.keys = keys
self.vel = 200 /math.sqrt(self.w*self.h)
self.crashed = False
def __repr__(self):
return 'charcter({}, {}, {}, {}, {})'.format(
self.x, self.y, self.w, self.h, self.keys)
def myFunction(self, characters):
return [e for e in characters if e != self]
print(characters[0].myFunction(characters))
output:
[charcter(50, 50, 50, 50, keys2), charcter(200, 200, 100, 20, keys1)]
I Understand what you want but there are a few issues with your code that I decided to fix for you i guess. The first is to remember just for your sake that when making classes make the first letter upper case. Next your key creation does not make any sense because keys1 doesnt exsist. I assumed it to be a string in my example. Next I created an str function for your class so it can output the characters somehow so its not only the memory address. Next I created the function you want but it will be in the format
x = myFunc(characters[0], characters)
and on top of that if you print x it will give you a list of memory addresses and therefore you must loop through and print each character specifically to see which one it is. Here is the final code.
import math
class Character():
def __init__(self,x,y,w,h,keys="keys1"):
self.x = x
self.y = y
self.w = w
self.h = h
self.keys = keys
self.vel = 200 /math.sqrt(self.w*self.h)
self.crashed=False
# I need an list to use here in a function of my "character" class
# my list must have all the elements in my initial list but self
def __str__(self):
return "Character x:{}, y:{}, w:{}, h:{}, key:{}".format(self.x, self.y, self.w, self.h, self.keys)
def myFunc(chars, characters):
characters_copy = characters[:]
if chars in characters_copy:
ind = characters_copy.index(chars)
characters_copy.pop(ind)
return characters_copy
characters = [Character(0,0,20,20), Character(50,50,50,50), Character(200,200,100,20)]
x = myFunc(characters[0], characters)
for i in x:
print(i)
I believe this is somewhat what you wanted, I added the changes so its easier for me and you. But you should be able to work with this.
Related
This question already has answers here:
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 4 years ago.
I have a doubt about storing a class variables in a second variable, in order to be called later.
This is my code (simplified to be readable):
class Agent(object):
def __init__(self):
self.actual = []
class Play(object):
def __init__(self):
self.x = 0.45 * 400
self.y = 0.5 * 400
self.position = []
self.position.append([self.x, self.y])
self.x_change = 20
self.y_change = 0
def do_move(self, move, x, y):
move_array = [self.x_change, self.y_change]
if move == 1 and self.x_change == 0: # right
move_array = [20, 0]
self.x_change, self.y_change = move_array
self.x = x + self.x_change
self.y = y + self.y_change
self.update_position(self.x, self.y)
def update_position(self, x, y):
self.position[-1][0] = x
self.position[-1][1] = y
def run():
agent = Agent()
player1 = Play()
agent.actual = [player1.position]
print(agent.actual[0])
i = 1
player1.do_move(i, player1.x, player1.y)
print(agent.actual[0])
run()
>> [[180.0, 200.0]]
>> [[200.0, 200.0]]
This is what I cannot understand. Why, if agent.actual stores the player.position and it is not modified after agent.actual = [player1.position], its value actually changes between the two print()?
I modify player.position, but not agent.actual, which means it should stay the same. I cannot figure this out!
EDIT:
I tried, as suggested, with the following methods:
agent.actual = player1.position.copy()
agent.actual = player1.position[:]
agent.actual= list(player1.position)
import copy
agent.actual = copy.copy(player1.position)
agent.actual = copy.deepcopy(player1.position)
All these methods always return, as before, two different values:
>> [[180.0, 200.0]]
>> [[200.0, 200.0]]
Player.position is list, which means it's mutable type. If you put this list in another list, Python makes a reference to it, not a copy.
When you add/delete/change items in the list, it will change everywhere the reference is hold.
You need to make a copy when you assign to agent.actual. Look at the copy module in Python or restructure your code (Hint: tuple is immutable type)
class type_name:
def __init__(self, *field_names):
self.x = field_names[0]
self.y = field_names[1]
self._fields = [x for x in field_names]
def get_y(self):
return self.y
def __getitem__(self, ind):
fstr = 'self.get_' + str(self._fields[ind]) #this would give me 5 i want self.y so I construct a string such as 'self.get_y()'
#and then return eval on that string to return the value
Using this code above,
Point = pnamedtuple('Point', ['x','y'], mutable = False)
origin = Point(0,5)
print(origin[1])
It should also work with origin['y']
I'm surprised this isn't crashing, but I'm really not sure what's happened here. On mouse over + key press 'd' should bring up menu of objects under mouse (which it does). When selecting an object it should print a message to console from that objects description. It doesn't though, it prints something like <__main__.Object instance at 0x02AE1800>.
Here is the relevant code
def menu(header, options, width):
if len(options) > 26: raise ValueError('Cannot have a menu with more than 26 options.'
#calculate the total height for the header (afer auto wrap) and one line per option
header_height = libtcod.console_get_height_rect(con, 0, 0, width, SCREEN_HEIGHT, header)
height = len(options) + header_height
#create an off-screen console that represents the menu's window
window = libtcod.console_new(width, height)
#print the header, with auto wrap, baby.
libtcod.console_set_default_foreground(window, libtcod.white)
libtcod.console_print_rect_ex(window, 0, 0, width, height, libtcod.BKGND_NONE, libtcod.LEFT, header)
#print all the options
y = header_height
letter_index = ord('a')
for option_text in options:
text = '(' + chr(letter_index) + ') ' + option_text
libtcod.console_print_ex(window, 0, y, libtcod.BKGND_NONE, libtcod.LEFT, text)
y += 1
letter_index += 1
#blit the contents of "window" to the root console
x = SCREEN_WIDTH/2 - width/2
y = SCREEN_HEIGHT /2 - height/2
libtcod.console_blit(window, 0, 0, width, height, 0, x, y, 1.0, 0.7)
#present the root console to the player and wait for keypress
libtcod.console_flush()
key = libtcod.console_wait_for_keypress(True)
#convert the ASCII code to an index; if it corresponds to an option, return it
index = key.c - ord('a')
if index >= 0 and index < len(options): return index
return None
def handle_keys():
global keys;
if key_char == 'd':
#show the description menu, if an item is selected, describe it.
chosen_object = description_menu('Press the key next to an object to see its description.\n')
if chosen_object is not None:
chosen_object.describe()
else:
return 'cancelled'
return 'didnt-take-turn'
def description_menu(header):
global mouse
#return a string with the names of all objects under the mouse
(x, y) = (mouse.cx, mouse.cy)
#create a list with the names of all objects at the mouse's coordinates and in FOV
names = [obj for obj in objects if obj.x == x and obj.y == y and libtcod.map_is_in_fov(fov_map, obj.x, obj.y) and obj.description is not None]
#show a menu with each object under the mouse as an option
if len(names) == 0:
options = ['There is nothing here.']
else:
options = [object.name for object in names]
index = menu(header, options, INVENTORY_WIDTH)
#if an item was chosen, return it
if index is None or len(names) == 0: return None
return names[index]
Class Object:
#this is a generic object: the player, a monster, an item, the stairs...
#it's always represented by a character on screen.
def __init__(self, x, y, char, name, color, blocks=False, fighter=None, ai=None, item=None, description=None):
self.x = x
self.y = y
self.char = char
self.name = name
self.color = color
self.blocks = blocks
self.fighter = fighter
if self.fighter: #let the fighter component know who owns it
self.fighter.owner = self
self.ai = ai
if self.ai: #let the ai component know who owns it
self.ai.owner = self
self.item = item
if self.item: #let the item component know who owns it, like a bitch
self.item.owner = self
self.description = self
if self.description: #let the description component know who owns it
self.description.owner = self
def describe(self):
#describe this object
if self.description is None:
message('The ' + self.owner.name + ' cannot be described.')
else:
message(str(self.description), libtcod.white)`
My guess would be that you are passing a string representation of the Object instance to message when you really want to be passing a string that carries some easy-to-understand information. The str method calls Object.__str__ (one of python's magic methods) Object.__str__ has not been defined in your code, so str defaults to calling Object.__repr__ which is where you are getting the <__main__.Object instance at 0x02AE1800>.
Try defining Object.__str__ so that it returns a string holding the information you would want it to display when print-ing it.
For example:
Class Object:
def __init__(self, name, x, y):
self.name = name
self.x = x
self.y = y
def __str__(self):
return("Object " + self.name + " is at position [" + self.x + "," + self.y + "]")
In the end, I can't say for sure what the problem is because we don't have the definition of the message method. you should include the code for that method so that we can better understand what is going on. Good luck!
Python dictionaries have always confused me.
I have 3 dictionaries:
left_dict = {"N":"W", "W":"S", "S":"E", "E":"N"}
right_dict = {"N":"E", "E":"S", "S":"W", "W":"N"}
turn_dict = {"N":"S", "E":"W", "S":"N", "W":"E"}
I have a class Robot which is initialized as such:
class Robot:
def __init__(self, team, x, y, direction):
self.team = team
self.health = 50
self.x = x
self.y = y
self.direction = direction
In this class I have a method that changes the direction.
def left90(self):
self.direction = left_dict <---- **is this how I would change the direction**
I believe what you are looking for is:
def left90(self):
self.direction = left_dict[self.direction]
I am trying to get values from my dictionary VALUES. My program creates combination of possible positions and gets the last position. Then I want to get the value. Everything works well here except indicated .get_value method. When I execute this code I receive:
AttributeError: 'Combination' object has no attribute 'get_value'
Theoretically it should be easy but I am new to OOP and I don't see what is wrong here.
X = ['A','B','C']
Y = ['1','2','3']
VALUES = {'A':10, 'B': 50, 'C':-20}
class Combination:
def __init__(self,x,y):
if (x in X) and (y in Y):
self.x = x
self.y = y
else:
print "WRONG!!"
def __repr__ (self):
return self.x+self.y
def get_x(self):
return self.x
def get_y(self):
return self.y
class Position:
def __init__(self):
self.xy = []
for i in X:
for j in Y:
self.xy.append(Combination(i,j))
def choose_last(self):
return self.xy.pop()
def __str__(self):
return "List contains: " + str(self.xy)
class Operation1:
def __init__(self):
self.operation1 = []
def __str__(self):
s = str(self.operation1)
return s
def get_value(self):
V = VALUES.get(self)
return V
pos = Position()
print pos
last_item = pos.choose_last()
print "Last item:", last_item, pos
last_value = last_item.get_value() # <---- Here is a problem
How can I obtain value of my position? Value is determined by the X value - this is A,B or C. In the dictionary I have a numeral value for the letter.
You are appending objects of Combination into xy of Position. When you say choose_last, it will return the last Combination object inserted into xy. And you are trying to invoke get_value method on a Combination object, which doesnt have that method. Thats why you are getting that error.
Always use new style classes.