#python-3.x
#python-3.x
Вопрос:
Начинающий разработчик Python играет и пытается создать карточную игру. Работаю над собственной системой случайного выбора карточек.
import random
# list to draw random card from from:
card_names = ["ace_h", "two_h", "three_h"]
class Cards(object):
in_play = False
def __init__(self, face, color, value):
self.face = face
self.color = color
self.value = value
ace_h = Cards("Ace", "Hearts", 14)
two_h = Cards("Two", "Hearts", 2)
three_h = Cards("Three", "Hearts", 3)
random_1 = random.choice(card_names)
print (random_1 ".face")
Если предположение ace_h
было выбрано методом рандомизации, я надеялся, что печать в конце отобразит результат для печати ace_h.face
(который будет Ace). Скорее, печать просто отображается ace_h.face
в виде строки, а не фактического значения, связанного с ней.
Как я могу это изменить?
Обратите внимание, что простое использование print (ace_h.face)
дает желаемый результат.
Комментарии:
1. Почему бы не сделать
random_1 = random.choice([ace_h, two_h, three_h])
and thenprint(random_1.face)
?2. Спасибо, это сработало, но я не уверен, почему? В чем разница между вашим кодом и моим, кроме того, что мой ссылается на заранее определенный список?
3. Добавление к @elethan: здесь даже не нужны именованные переменные. Просто создайте сингл
list
с картами в нем напрямую, потому что они логически представляют собой набор опций, а не набор независимых переменных.4. @user2390206: код elethan создает список реальных объектов, а не строк, описывающих их, и ищет фактический атрибут, не объединяя имя атрибута.
5. @user2390206 как сказал @ShadowRanger, ваш код просто печатает строки, в то время как мой печатает возвращаемое значение
face
атрибута для любогоCard
выбранного. Вы могли бы заставить свой существующий код работать таким же образом, если быeval()
ваша строка, которая будет запускать строку, как если бы это был код Python:print (eval(random_1 ".face"))
, но использованиеeval()
часто не рекомендуется, поскольку существуют потенциальные риски для безопасности (хотя, поскольку вы не принимаете пользовательский ввод, в этом случае все должно быть в порядке, но случайный выбор изобъекты, а не имена, на мой взгляд, лучший вариант).
Ответ №1:
У вас фундаментальное непонимание того, как ссылаться на вещи в Python.
В Python у вас есть имена переменных:
ace_h = 1
two_h = 2
three_h = 3
Вы можете вызывать эти значения по имени:
print(ace_h) # => 1
Вы можете поместить значения в другую коллекцию:
cards = [ace_h, two_h, three_h]
print(cards) # [1, 2, 3]
Вы можете распечатать определенный элемент:
print(cards[0])
Вы можете распечатать случайный элемент:
print(random.choice(cards))
Но все они относятся к значениям 1, 2, 3
.
На самом деле вы можете увидеть это, проверив id
:
print(id(ace_h))
print(id(cards[0]))
не имеет значения, используете ли вы ace_h
cards[0]
метод or для присвоения имени значению, оно одно и то же.
Это работает одинаково для всего в Python — все они являются объектами. Вы можете присвоить им имена любого типа, будь то имена переменных, помещая их в список или словарь — если id(thing)
это одно и то же, вы говорите об одном и том же объекте.
ace_h = Cards("Ace", "Hearts", 14)
two_h = Cards("Two", "Hearts", 2)
three_h = Cards("Three", "Hearts", 3)
cards = [ace_h, two_h, three_h]
print(cards)
for card in cards:
print(id(card))
print(id(ace_h))
print(id(two_h))
print(id(three_h))
random_card = random.choice(cards)
print(id(random_card))
print(random_card.face)
print('random card is ace_h? {}'.format(random_card is ace_h))
print('random card is two_h? {}'.format(random_card is two_h))
print('random card is three_h? {}'.format(random_card is three_h))
Вам будет намного лучше, если вы просто будете думать о переменных как о метках, которые вы прикрепляете к значениям. В вашем случае вы создаете Card
значения и наклеиваете ace_h
на них ярлык. Вы также помещаете это Card
в список, где вы можете ссылаться на него по имени cards[0]
. Вы можете присвоить ему любое количество имен:
another_name = ace_h
cool_name = ace_h
king_arthur = ace_h
sir_lancelot = ace_h
minister_of_silly_walks = ace_h
Теперь каждое из этих имен ссылается на одно и то же значение. Вы можете проверить это с id
помощью , и вы можете увидеть, что все они имеют правильные свойства с print(dir(ace_h))
помощью и print(dir(minister_of_silly_walks)))
. И вы можете проверить, что они являются одним и тем же объектом ace_h is minister_of_silly_walks
.
Ответ №2:
Вы можете поместить все объекты в список, подобный этому:
objectList = [ace_h, two_h, three_h]
random_1 = random.choice(objectList)
а затем выведите нужный атрибут:
print(random_1.face)
Ответ №3:
Есть несколько способов, которыми вы могли бы это сделать, которые сразу приходят на ум.
-
Вы можете изменить свой MO и предварительно инициализировать список переменных:
import random class Cards(object): in_play = False def __init__(self, face, color, value): self.face = face self.color = color self.value = value ace_h = Cards("Ace", "Hearts", 14) two_h = Cards("Two", "Hearts", 2) three_h = Cards("Three", "Hearts", 3) # list to draw random card from from: cards = [ace_h, two_h, three_h] random_1 = random.choice(cards) print (random_1.face)
Как вы можете видеть, я просто немного изменил порядок вашего кода, чтобы
card_names
он мог содержать ссылки на фактическиеCard
объекты вместо их имен. Это, вероятно, самый простой способ сделать это. -
Вы можете получить доступ к глобальным переменным по имени. Это немного сложнее и, вероятно, не то, что вы хотите, но этот метод может быть полезен для других целей:
import random # list to draw random card from from: card_names = ["ace_h", "two_h", "three_h"] class Cards(object): in_play = False def __init__(self, face, color, value): self.face = face self.color = color self.value = value ace_h = Cards("Ace", "Hearts", 14) two_h = Cards("Two", "Hearts", 2) three_h = Cards("Three", "Hearts", 3) random_1 = random.choice(card_names) print(globals()[random_1].face)
Это больше похоже на ваш исходный код.
globals()
возвращает adict
, содержащий все имена, определенные на уровне модуля, включая функции, классы и переменные, все с ключом по имени.globals()[random_1]
следовательно, это будетCards
объект (который, я думаю, вам следует переименоватьCard
, кстати).Внутри функции вы могли бы использовать
locals()
, чтобы получить аналогичноеdict()
для локального пространства имен внутри этой функции. Например, вCards.__init__
, вы могли бы сделать что-то вродеlocals()['face']
доступа кface
параметру.