【问题标题】:Why I must I declare self.cards in the __init__() definition, rather than the __str__() definition?为什么我必须在 __init__() 定义中声明 self.cards 而不是 __str__() 定义?
【发布时间】:2013-08-18 20:36:45
【问题描述】:

我正在阅读我的一本书的源代码,并且我发现一些源代码的输出令人困惑。我认为我向你展示比试图完全解释它更好。

class Cards(object):
   RANK=["A","2","3","4","5","6","7","8","9","10","J","Q","K"]
   SUIT=["c","d","h","s"]

   def __init__(self,rank,suit):
      self.rank=rank
      self.suit=suit

   def __str__(self):
      rep=self.rank+self.suit
      return rep


class Hand(object):
   def __str__(self):
      self.cards=[]
      if self.cards:
         rep=" "
         for card in self.cards:
          rep+=str(card) + "  "
      else:
         rep="<empty>"

      return rep

   def add(self,card):
      self.cards.append(card)

   def give(self, card, other_hand):
      self.cards.remove(card)
      other_hand.add(card)


b=Cards(rank="A", suit="c")

myhand=Hand()
print(myhand)

myhand.add(b)
print(myhand)

在这种情况下,解释器在两种情况下都返回一个空值,即使我给 self.card 两个值。但是,如果我声明 init() 方法,并首先在该方法中初始化 self.card,那么它将正常运行并为我提供 myhand 的新值,这将是我添加的任何内容这是 self.card 属性。但是,为什么我必须先在init函数中声明并初始化first.card呢?为什么它可以在 str 函数中以相同的方式工作?是因为 init() 函数在我第一次调用类时首先执行还是什么?

此外,在我放置 rep=str(card) 的地方,如果我将 card 更改为 self.cards,它会在我告诉它打印时开始给我内存地址。再次,这是为什么?为什么它不只是向我显示代表中 self.cards 的值?

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:

    解释器正在返回&lt;empty&gt;,因为每次调用print(myhand),解释器都会打印myhand.__str__() 返回的内容。在本例中,您是:

    1. 设置self.cards 为空列表。
    2. 检查self.cards是否不为空,即false
    3. 代码继续执行else: 子句,返回&lt;empty&gt;

    如果您将self.cards = [] 放入__init__ 方法中,该方法仅在创建对象后调用一次,并从__str__ 中删除上述行,那么它应该可以正常工作 - 卡片列表不会被覆盖。

    另外,str(self.cards) 给你一个内存地址列表,因为list 对象的str 方法使用__repr__ 来打印它自己的值。如果你在Cards 类中定义一个方法__repr__,类似于__str__,那么它就可以正常工作。

    class NoRepr(object):
         def __str__(self):
             return '__str__'     
    
    class WithRepr(object):
         def __str__(self):
             return '__str__'
         def __repr__(self):
             return '__repr__'
    
    
    [NoRepr(), NoRepr()]
    [<__main__.NoRepr at 0x9907c0c>, <__main__.NoRepr at 0x9907a4c>]
    
    [WithRepr(), WithRepr()]
    [__repr__, __repr__]
    

    【讨论】:

      【解决方案2】:

      空手题

      • __init__ 方法在您创建类的实例时被调用。
      • 显示为空的原因是语句self.cards=[] 清除了卡片列表。因此,当您打印您有多少张卡片时,没有一张。

      第一个错误被您在添加b 之前打印了手的事实所掩盖。如果代码看起来像这样:

      myhand=Hand()
      myhand.add(b)
      print(myhand)
      

      声明 if self.cards: 会给你错误:AttributeError: 'Hand' object has no attribute 'cards'


      字符串表示题

      • rep=str(self.cards) 在 python 列表对象上调用 str 方法,因为它是 Cards 对象的列表。该方法将对列表中的每个对象调用__repr__。要修复它,请定义以下方法。
      # Cards class
      def __repr__(self):
         return str(self)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-24
        • 2021-08-07
        • 1970-01-01
        相关资源
        最近更新 更多